diff --git a/docs/index.html b/docs/index.html index 3ffa283..c7116f4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -36,6 +36,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -93,6 +94,10 @@ druid.checkbox_group Checkbox group module + + druid.drag + Component to handle drag action on node. + druid.grid Component to handle placing components by row and columns. @@ -195,7 +200,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/component.html b/docs/modules/component.html index 37fd89c..aae8da2 100644 --- a/docs/modules/component.html +++ b/docs/modules/component.html @@ -43,6 +43,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -478,7 +479,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.back_handler.html b/docs/modules/druid.back_handler.html index 0bc2cc0..7e95a33 100644 --- a/docs/modules/druid.back_handler.html +++ b/docs/modules/druid.back_handler.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -217,7 +218,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.blocker.html b/docs/modules/druid.blocker.html index 02feafd..721f904 100644 --- a/docs/modules/druid.blocker.html +++ b/docs/modules/druid.blocker.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -236,7 +237,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.button.html b/docs/modules/druid.button.html index b59dd1c..883e585 100644 --- a/docs/modules/druid.button.html +++ b/docs/modules/druid.button.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -416,7 +417,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.checkbox.html b/docs/modules/druid.checkbox.html index 1411d1c..ea9bf32 100644 --- a/docs/modules/druid.checkbox.html +++ b/docs/modules/druid.checkbox.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -279,7 +280,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.checkbox_group.html b/docs/modules/druid.checkbox_group.html index 0a7c625..ee56ba9 100644 --- a/docs/modules/druid.checkbox_group.html +++ b/docs/modules/druid.checkbox_group.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -241,7 +242,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.drag.html b/docs/modules/druid.drag.html new file mode 100644 index 0000000..a25b190 --- /dev/null +++ b/docs/modules/druid.drag.html @@ -0,0 +1,286 @@ + + + + + Defold Druid UI Library + + + + +
    + +
    + +
    +
    +
    + + +
    + + + + + + +
    + +

    Module druid.drag

    +

    Component to handle drag action on node.

    +

    Drag have correct handling for multitouch and swap + touched while dragging. Drag will be processed even + the cursor is outside of node, if drag is already started

    + + +

    Functions

    + + + + + + + + + +
    init(node, on_drag_callback)Drag component constructor
    set_click_zone(zone)Strict drag click area.
    +

    Tables

    + + + + + + + + + + + + + +
    EventsComponent events
    FieldsComponents fields
    StyleComponent style params
    + +
    +
    + + +

    Functions

    + +
    +
    + + init(node, on_drag_callback) +
    +
    + Drag component constructor + + +

    Parameters:

    +
      +
    • node + node + GUI node to detect dragging +
    • +
    • on_drag_callback + function + Callback for ondragevent(self, dx, dy) +
    • +
    + + + + + +
    +
    + + set_click_zone(zone) +
    +
    + Strict drag click area. Useful for + restrict events outside stencil node + + +

    Parameters:

    +
      +
    • zone + node + Gui node +
    • +
    + + + + + +
    +
    +

    Tables

    + +
    +
    + + Events +
    +
    + Component events + + +

    Fields:

    +
      +
    • on_touch_start + druid_event + (self) Event on touch start +
    • +
    • on_touch_end + druid_event + (self) Event on touch end +
    • +
    • on_drag_start + druid_event + (self) Event on drag start +
    • +
    • on_drag + druid_event + (self, dx, dy) Event on drag progress +
    • +
    • on_drag_end + druid_event + (self) Event on drag end +
    • +
    + + + + + +
    +
    + + Fields +
    +
    + Components fields + + +

    Fields:

    +
      +
    • is_touch + bool + Is component now touching +
    • +
    • is_drag + bool + Is component now dragging +
    • +
    • can_x + bool + Is drag component process vertical dragging. Default - true +
    • +
    • can_y + bool + Is drag component process horizontal. Default - true +
    • +
    • x + number + Current touch x position +
    • +
    • y + number + Current touch y position +
    • +
    • touch_start_pos + vector3 + Touch start position +
    • +
    + + + + + +
    +
    + + Style +
    +
    + Component style params + + +

    Fields:

    +
      +
    • DRAG_DEADZONE + number + Distance in pixels to start dragging +
    • +
    + + + + + +
    +
    + + +
    +
    +
    +generated by LDoc 1.4.6 +Last updated 2020-05-04 00:51:46 +
    +
    + + diff --git a/docs/modules/druid.grid.html b/docs/modules/druid.grid.html index 0a0ae13..a487fda 100644 --- a/docs/modules/druid.grid.html +++ b/docs/modules/druid.grid.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -372,7 +373,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.helper.html b/docs/modules/druid.helper.html index 822ba15..e05799f 100644 --- a/docs/modules/druid.helper.html +++ b/docs/modules/druid.helper.html @@ -43,6 +43,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -100,6 +101,18 @@ get_pivot_offset(pivot) Get node offset for given gui pivot + + helper..is_mobile() + Check if device is mobile (Android or iOS) + + + is_web() + Check if device is HTML5 + + + get_border() + Distance from node to size border +
    @@ -230,6 +243,53 @@ + +
    + + helper..is_mobile() +
    +
    + Check if device is mobile (Android or iOS) + + + + + + + +
    +
    + + is_web() +
    +
    + Check if device is HTML5 + + + + + + + +
    +
    + + get_border() +
    +
    + Distance from node to size border + + + +

    Returns:

    +
      + + vector4 (left, top, right, down) +
    + + + +
    @@ -238,7 +298,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.hover.html b/docs/modules/druid.hover.html index 5313e41..7d36b64 100644 --- a/docs/modules/druid.hover.html +++ b/docs/modules/druid.hover.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -213,7 +214,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.html b/docs/modules/druid.html index 021f3db..ea8c216 100644 --- a/docs/modules/druid.html +++ b/docs/modules/druid.html @@ -43,6 +43,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -114,7 +115,9 @@ set_text_function(callback) - Set text function. + Set text function + Druid locale component will call this function + to get translated text. set_sound_function(callback) @@ -226,9 +229,9 @@ set_text_function(callback)
    - Set text function. + Set text function Druid locale component will call this function - to get translated text. After settextfuntion + to get translated text. After settextfuntion all existing locale component will be updated @@ -326,7 +329,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.input.html b/docs/modules/druid.input.html index 8f6b84b..737bc3d 100644 --- a/docs/modules/druid.input.html +++ b/docs/modules/druid.input.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -96,11 +97,11 @@ Return current input field text - set_max_length(max_length, Self) + set_max_length(max_length) Set maximum length for input field. - set_allowerd_characters(characters, Self) + set_allowerd_characters(characters) Set allowed charaters for input field. @@ -174,7 +175,7 @@
    - set_max_length(max_length, Self) + set_max_length(max_length)
    Set maximum length for input field. @@ -187,12 +188,14 @@ number Maximum length for input text field -
  • Self - druid.input - instance to make chain calls -
  • +

    Returns:

    +
      + + druid.input + Self instance to make chain calls +
    @@ -200,7 +203,7 @@
    - set_allowerd_characters(characters, Self) + set_allowerd_characters(characters)
    Set allowed charaters for input field. @@ -214,12 +217,14 @@ string Regulax exp. for validate user input -
  • Self - druid.input - instance to make chain calls -
  • +

    Returns:

    +
      + + druid.input + Self instance to make chain calls +
    @@ -383,7 +388,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.lang_text.html b/docs/modules/druid.lang_text.html index 3ffaa4c..8345b88 100644 --- a/docs/modules/druid.lang_text.html +++ b/docs/modules/druid.lang_text.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -242,7 +243,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.progress.html b/docs/modules/druid.progress.html index 2181941..60b3a72 100644 --- a/docs/modules/druid.progress.html +++ b/docs/modules/druid.progress.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -381,7 +382,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.radio_group.html b/docs/modules/druid.radio_group.html index e2de393..65b2d6f 100644 --- a/docs/modules/druid.radio_group.html +++ b/docs/modules/druid.radio_group.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -241,7 +242,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.scroll.html b/docs/modules/druid.scroll.html index a4b9263..e9aae94 100644 --- a/docs/modules/druid.scroll.html +++ b/docs/modules/druid.scroll.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -89,40 +90,48 @@

    Functions

    - - + + - + + + + + - - + + - - + + - - + + - - + + - - + + + + + +
    init(scroll_parent, input_zone)Component init functioninit(view_node, content_node)Scroll constructor.
    scroll_to(vector3[, is_instant])Start scroll to target pointStart scroll to target point.
    scroll_to_index(index[, skip_cb])Scroll to item in scroll by point index.
    scroll_to_percent(vector3[, is_instant]) Start scroll to target scroll percent
    init(index[, skip_cb])Scroll to item in scroll by point indexget_percent()Return current scroll progress status.
    set_points(points)Set points of interest.set_size(size)Set scroll content size.
    set_inert(state) Enable or disable scroll inert.
    on_point_move(callback)Set the callback on scrolling to point (if exist)is_inert()Return if scroll have inertion.
    set_border(border)Set the scroll possibly areaset_extra_strech_size(stretch_size)Set extra size for scroll stretching.
    get_scroll_percent()Return current scroll progressget_scroll_size()Return vector of scroll size with width and height.
    set_points(points)Set points of interest.

    Tables

    @@ -150,21 +159,21 @@
    - init(scroll_parent, input_zone) + init(view_node, content_node)
    - Component init function + Scroll constructor.

    Parameters:

      -
    • scroll_parent +
    • view_node node - Gui node where placed scroll content. This node will change position + GUI view scroll node
    • -
    • input_zone +
    • content_node node - Gui node where input is catched + GUI content scroll node
    @@ -178,18 +187,18 @@ scroll_to(vector3[, is_instant])
    - Start scroll to target point + Start scroll to target point.

    Parameters:

    • vector3 point - target point + Target point
    • is_instant bool - instant scroll flag + Instant scroll flag (optional)
    @@ -203,6 +212,32 @@
  • scroll:scroll_to(vmath.vector3(0), true)
  • +
    +
    + + scroll_to_index(index[, skip_cb]) +
    +
    + Scroll to item in scroll by point index. + + +

    Parameters:

    +
      +
    • index + number + Point index +
    • +
    • skip_cb + bool + If true, skip the point callback + (optional) +
    • +
    + + + + +
    @@ -235,48 +270,49 @@
    - - init(index[, skip_cb]) + + get_percent()
    - Scroll to item in scroll by point index + Return current scroll progress status. + Values will be in [0..1] interval -

    Parameters:

    - +

    Returns:

    +
      + + vector3 + New vector with scroll progress values +
    - - set_points(points) + + set_size(size)
    - Set points of interest. - Scroll will always centered on closer points + Set scroll content size. + It will change content gui node size

    Parameters:

    +

    Returns:

    +
      + + druid.scroll + Self instance +
    @@ -300,59 +336,71 @@ +

    Returns:

    +
      + + druid.scroll + Self instance +
    - - on_point_move(callback) + + is_inert()
    - Set the callback on scrolling to point (if exist) + Return if scroll have inertion. + + + +

    Returns:

    +
      + + bool + If scroll have inertion +
    + + + + +
    +
    + + set_extra_strech_size(stretch_size) +
    +
    + Set extra size for scroll stretching. + Set 0 to disable stretching effect

    Parameters:

    +

    Returns:

    +
      + + druid.scroll + Self instance +
    - - set_border(border) + + get_scroll_size()
    - Set the scroll possibly area - - -

    Parameters:

    - - - - - - -
    -
    - - get_scroll_percent() -
    -
    - Return current scroll progress + Return vector of scroll size with width and height. @@ -360,7 +408,35 @@
      vector3 - Scroll progress + Available scroll size +
    + + + + +
    +
    + + set_points(points) +
    +
    + Set points of interest. + Scroll will always centered on closer points + + +

    Parameters:

    + + +

    Returns:

    +
      + + druid.scroll + Self instance
    @@ -410,42 +486,51 @@

    Fields:

    @@ -479,13 +564,9 @@ number Multiplier for inertion speed -
  • DEADZONE +
  • POINTS_DEADZONE number - Deadzone for start scrol in pixels -
  • -
  • SOFT_ZONE_SIZE - number - Size of outside zone in pixels (for scroll back moving) + Speed to check points of interests in no_inertion mode
  • BACK_SPEED number @@ -495,6 +576,14 @@ number Scroll gui.animation speed for scroll_to function
  • +
  • EXTRA_STRECH_SIZE + number + extra size in pixels outside of scroll (stretch effect) +
  • +
  • SMALL_CONTENT_SCROLL + bool + If true, content node with size less than view node size can be scrolled +
  • @@ -509,7 +598,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.slider.html b/docs/modules/druid.slider.html index 2c42e44..c81ac6e 100644 --- a/docs/modules/druid.slider.html +++ b/docs/modules/druid.slider.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -280,7 +281,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.swipe.html b/docs/modules/druid.swipe.html index 15505fb..6589bc4 100644 --- a/docs/modules/druid.swipe.html +++ b/docs/modules/druid.swipe.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -250,7 +251,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.text.html b/docs/modules/druid.text.html index 15e8ccc..a081325 100644 --- a/docs/modules/druid.text.html +++ b/docs/modules/druid.text.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -309,7 +310,7 @@

    Returns:

      - boolean + bool Is text node with line break
    @@ -406,7 +407,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid.timer.html b/docs/modules/druid.timer.html index 3bf0f9d..c1ad7b9 100644 --- a/docs/modules/druid.timer.html +++ b/docs/modules/druid.timer.html @@ -44,6 +44,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -295,7 +296,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid_event.html b/docs/modules/druid_event.html index df96371..877e8bc 100644 --- a/docs/modules/druid_event.html +++ b/docs/modules/druid_event.html @@ -43,6 +43,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -241,7 +242,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/modules/druid_instance.html b/docs/modules/druid_instance.html index 0a4c8b4..ad27765 100644 --- a/docs/modules/druid_instance.html +++ b/docs/modules/druid_instance.html @@ -43,6 +43,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -96,6 +97,7 @@
  • druid.checkbox_group
  • druid.radio_group
  • druid.swipe
  • +
  • druid.drag
  • @@ -880,7 +882,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/01-components.md.html b/docs/topics/01-components.md.html index 9b1000c..7f48b5e 100644 --- a/docs/topics/01-components.md.html +++ b/docs/topics/01-components.md.html @@ -68,6 +68,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -412,7 +413,7 @@ Key is value from druid const: const.SIDE.X (or just "x") or const.SIDE.Y (or ju
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/02-creating_custom_components.md.html b/docs/topics/02-creating_custom_components.md.html index 0251ceb..67a5e37 100644 --- a/docs/topics/02-creating_custom_components.md.html +++ b/docs/topics/02-creating_custom_components.md.html @@ -56,6 +56,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -244,7 +245,7 @@ There is next interests in druid:
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/03-styles.md.html b/docs/topics/03-styles.md.html index 8d2a391..8bdb3b1 100644 --- a/docs/topics/03-styles.md.html +++ b/docs/topics/03-styles.md.html @@ -54,6 +54,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -134,7 +135,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/04-druid_assets.md.html b/docs/topics/04-druid_assets.md.html index 227822d..738e4fb 100644 --- a/docs/topics/04-druid_assets.md.html +++ b/docs/topics/04-druid_assets.md.html @@ -53,6 +53,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -91,7 +92,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/05-examples.md.html b/docs/topics/05-examples.md.html index 28a3d17..187c016 100644 --- a/docs/topics/05-examples.md.html +++ b/docs/topics/05-examples.md.html @@ -53,6 +53,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -89,7 +90,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/README.md.html b/docs/topics/README.md.html index f57e3ae..2205ddb 100644 --- a/docs/topics/README.md.html +++ b/docs/topics/README.md.html @@ -63,6 +63,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -336,7 +337,7 @@ https://insality.github.io/druid/

    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs/topics/changelog.md.html b/docs/topics/changelog.md.html index 9eba3e8..2cfc3d9 100644 --- a/docs/topics/changelog.md.html +++ b/docs/topics/changelog.md.html @@ -49,6 +49,7 @@
  • druid.button
  • druid.checkbox
  • druid.checkbox_group
  • +
  • druid.drag
  • druid.grid
  • druid.hover
  • druid.input
  • @@ -75,7 +76,7 @@

    Druid 0.3.0:

    @@ -125,7 +162,7 @@
    generated by LDoc 1.4.6 -Last updated 2020-04-18 14:39:17 +Last updated 2020-05-04 00:51:46
    diff --git a/docs_md/changelog.md b/docs_md/changelog.md index 0959b59..bf0018e 100644 --- a/docs_md/changelog.md +++ b/docs_md/changelog.md @@ -39,4 +39,37 @@ Druid 0.3.0: - Known issues: - Adjusting text size by height works wrong. Adjusting single line texting works fine - Space is not working in HTML5 - \ No newline at end of file + + + +Druid 0.4.0: + +- Add _Drag_ basic component + - Drag component allow you detect dragging on GUI node + - Drag will be processed even the cursor is outside of node, if drag is already started + - Drag provides correct handle of several touches. Drag can switch between them (no more scroll gliches with position) + - Drag have next events: + - on_touch_start (self) + - on_touch_end (self) + - on_drag_start (self) + - on_drag (self, dx, dy) + - on_drag_end (self) + - You can restriction side of draggin by changing _drag.can_x_ and _drag.can_y_ fields + - You can setup drag deadzone to detect, when dragging is started (by default 10 pixels) + +- Druid _Scroll_ component fully reworked. Input logic moved to _Drag_ component + - Updated scroll documentation + - Changed constructor order params + - Scroll now contains from view and content node + - _View node_ - static node, which size determine the "camera" zone + - _Content node_ - dynamic node, moving by _Scroll_ component + - Scroll will be disabled only if content size equals to view size (by width or height separatly) + - You can adjust scroll size via _.gui_ scene. Just setup correct node size + - Different anchoring is supported (for easier layout) + - Function _scroll_to_ now accept position relative to _content node_. It's more easier for handling. _Example:_ if you have children node of _content_node_, you can pass this node position to scroll to this. + - **Resolve #52**: _Content node size_ now can be less than _view node size_. In this case, content will be scrolled only inside _view size_ + - **Fix #50**: If style:SOFT_ZONE_SIZE equals to [0..1], scroll can be disappeared + +- _Grid_ anchor by default equals to node pivot (so, more gui settings in _.gui_ settings) + +- **Fix:** Blocker component bug (blocker had very high priority, so it's block even button components, created after bloker) \ No newline at end of file diff --git a/druid/base/blocker.lua b/druid/base/blocker.lua index 0b336bd..e5c3931 100644 --- a/druid/base/blocker.lua +++ b/druid/base/blocker.lua @@ -14,7 +14,7 @@ local Event = require("druid.event") local const = require("druid.const") local component = require("druid.component") -local M = component.create("blocker", { const.ON_INPUT_HIGH }) +local M = component.create("blocker", { const.ON_INPUT }) --- Component init function @@ -29,7 +29,7 @@ end function M.on_input(self, action_id, action) - if action_id ~= const.ACTION_TOUCH then + if action_id ~= const.ACTION_TOUCH and action_id ~= const.ACTION_MULTITOUCH then return false end diff --git a/druid/base/drag.lua b/druid/base/drag.lua new file mode 100644 index 0000000..8e1199a --- /dev/null +++ b/druid/base/drag.lua @@ -0,0 +1,245 @@ +--- Component to handle drag action on node. +-- Drag have correct handling for multitouch and swap +-- touched while dragging. Drag will be processed even +-- the cursor is outside of node, if drag is already started +-- @module druid.drag + +--- Component events +-- @table Events +-- @tfield druid_event on_touch_start (self) Event on touch start +-- @tfield druid_event on_touch_end (self) Event on touch end +-- @tfield druid_event on_drag_start (self) Event on drag start +-- @tfield druid_event on_drag (self, dx, dy) Event on drag progress +-- @tfield druid_event on_drag_end (self) Event on drag end + +--- Components fields +-- @table Fields +-- @tfield bool is_touch Is component now touching +-- @tfield bool is_drag Is component now dragging +-- @tfield bool can_x Is drag component process vertical dragging. Default - true +-- @tfield bool can_y Is drag component process horizontal. Default - true +-- @tfield number x Current touch x position +-- @tfield number y Current touch y position +-- @tfield vector3 touch_start_pos Touch start position + +--- Component style params +-- @table Style +-- @tfield number DRAG_DEADZONE Distance in pixels to start dragging + +local Event = require("druid.event") +local const = require("druid.const") +local helper = require("druid.helper") +local component = require("druid.component") + +local M = component.create("drag", { const.ON_INPUT_HIGH }) + + +local function start_touch(self, touch) + self.is_touch = true + self.is_drag = false + + self.touch_start_pos.x = touch.x + self.touch_start_pos.y = touch.y + + self.x = touch.x + self.y = touch.y + + self.on_touch_start:trigger(self:get_context()) +end + + +local function end_touch(self) + if self.is_drag then + self.on_drag_end:trigger(self:get_context()) + end + + self.is_drag = false + self.is_touch = false + self.on_touch_end:trigger(self:get_context()) + self:reset_input_priority() + self.touch_id = 0 +end + + +local function process_touch(self, touch) + if not self.can_x then + self.touch_start_pos.x = touch.x + end + + if not self.can_y then + self.touch_start_pos.y = touch.y + end + + local distance = helper.distance(touch.x, touch.y, self.touch_start_pos.x, self.touch_start_pos.y) + if not self.is_drag and distance >= self.style.DRAG_DEADZONE then + self.is_drag = true + self.on_drag_start:trigger(self:get_context()) + self:increase_input_priority() + end +end + + +--- Return current touch action from action input data +-- If touch_id stored - return exact this touch action +local function find_touch(action_id, action, touch_id) + local act = helper.is_mobile() and const.ACTION_MULTITOUCH or const.ACTION_TOUCH + + if action_id ~= act then + return + end + + if action.touch then + local touch = action.touch + for i = 1, #touch do + if touch[i].id == touch_id then + return touch[i] + end + end + return touch[1] + else + return action + end +end + + +--- Process on touch release. We should to find, if any other +-- touches exists to switch to another touch. +local function on_touch_release(self, action_id, action) + if #action.touch >= 2 then + -- Find next unpressed touch + local next_touch + for i = 1, #action.touch do + if not action.touch[i].released then + next_touch = action.touch[i] + break + end + end + + if next_touch then + self.x = next_touch.x + self.y = next_touch.y + self.touch_id = next_touch.id + else + end_touch(self) + end + elseif #action.touch == 1 then + end_touch(self) + end +end + + +--- Drag component constructor +-- @tparam node node GUI node to detect dragging +-- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy) +-- @function drag:init +function M.init(self, node, on_drag_callback) + self.style = self:get_style() + self.node = self:get_node(node) + + self.dx = 0 + self.dy = 0 + self.touch_id = 0 + self.x = 0 + self.y = 0 + self.is_touch = false + self.is_drag = false + self.touch_start_pos = vmath.vector3(0) + + self.can_x = true + self.can_y = true + + self.click_zone = nil + self.on_touch_start = Event() + self.on_touch_end = Event() + self.on_drag_start = Event() + self.on_drag = Event(on_drag_callback) + self.on_drag_end = Event() +end + + +function M.on_input_interrupt(self) + if self.is_drag or self.is_touch then + end_touch(self) + end +end + + +function M.on_input(self, action_id, action) + if action_id ~= const.ACTION_TOUCH and action_id ~= const.ACTION_MULTITOUCH then + return + end + + if not helper.is_enabled(self.node) then + return false + end + + local is_pick = gui.pick_node(self.node, action.x, action.y) + if self.click_zone then + is_pick = is_pick and gui.pick_node(self.click_zone, action.x, action.y) + end + + if not is_pick and not self.is_drag then + end_touch(self) + return false + end + + + local touch = find_touch(action_id, action, self.touch_id) + if not touch then + return false + end + + if touch.id then + self.touch_id = touch.id + end + + self.dx = 0 + self.dy = 0 + + if touch.pressed and not self.is_touch then + start_touch(self, touch) + end + + if touch.released and self.is_touch then + if action.touch then + -- Mobile + on_touch_release(self, action_id, action) + else + -- PC + end_touch(self) + end + end + + if self.is_touch then + process_touch(self, touch) + end + + local touch_modified = find_touch(action_id, action, self.touch_id) + if touch_modified and self.is_drag then + self.dx = touch_modified.x - self.x + self.dy = touch_modified.y - self.y + end + + if touch_modified then + self.x = touch_modified.x + self.y = touch_modified.y + end + + if self.is_drag then + self.on_drag:trigger(self:get_context(), self.dx, self.dy) + end + + return self.is_drag +end + + +--- Strict drag click area. Useful for +-- restrict events outside stencil node +-- @function drag:set_click_zone +-- @tparam node zone Gui node +function M.set_click_zone(self, zone) + self.click_zone = self:get_node(zone) +end + + +return M diff --git a/druid/base/grid.lua b/druid/base/grid.lua index 9bdd8e8..02fa03c 100644 --- a/druid/base/grid.lua +++ b/druid/base/grid.lua @@ -20,7 +20,7 @@ -- @tfield vector3 border_offer The border offset for correct anchor calculations local Event = require("druid.event") -local const = require("druid.const") +local helper = require("druid.helper") local component = require("druid.component") local M = component.create("grid") @@ -37,7 +37,7 @@ function M.init(self, parent, element, in_row) self.offset = vmath.vector3(0) - local pivot = const.PIVOTS[gui.get_pivot(self.parent)] + local pivot = helper.get_pivot_offset(gui.get_pivot(self.parent)) self.anchor = vmath.vector3(0.5 + pivot.x, 0.5 - pivot.y, 0) self.in_row = in_row or 1 diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 56a50aa..d3215da 100644 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -15,15 +15,17 @@ --- Component fields -- @table Fields --- @tfield node node Scroll parent node --- @tfield node input_zone Scroll input node --- @tfield vector3 zone_size Current scroll content size --- @tfield number soft_size Soft zone size from style table --- @tfield vector3 center_offset Distance from node to node's center +-- @tfield node view_node Scroll view node +-- @tfield node content_node Scroll content node -- @tfield bool is_inert Flag, if scroll now moving by inertion --- @tfield vector3 inert Current inert speed --- @tfield vector3 pos Current scroll posisition --- @tfield vector3 target Current scroll target position +-- @tfield vector3 inertion Current inert speed +-- @tfield vector3 position Current scroll posisition +-- @tfield vector3 target_position Current scroll target position +-- @tfield vector4 available_pos Available position for content node: (min_x, max_y, max_x, min_y) +-- @tfield vector3 available_size Size of available positions: (width, height, 0) +-- @tfield druid.drag drag Drag component +-- @tfield[opt] selected Current index of points of interests +-- @tfield bool is_animate Flag, if scroll now animating by gui.animate --- Component style params -- @table Style @@ -31,117 +33,136 @@ -- @tfield number FRICT Multiplier for free inertion -- @tfield number INERT_THRESHOLD Scroll speed to stop inertion -- @tfield number INERT_SPEED Multiplier for inertion speed --- @tfield number DEADZONE Deadzone for start scrol in pixels --- @tfield number SOFT_ZONE_SIZE Size of outside zone in pixels (for scroll back moving) +-- @tfield number POINTS_DEADZONE Speed to check points of interests in no_inertion mode -- @tfield number BACK_SPEED Scroll back returning lerp speed -- @tfield number ANIM_SPEED Scroll gui.animation speed for scroll_to function +-- @tfield number EXTRA_STRECH_SIZE extra size in pixels outside of scroll (stretch effect) +-- @tfield bool SMALL_CONTENT_SCROLL If true, content node with size less than view node size can be scrolled local Event = require("druid.event") -local helper = require("druid.helper") local const = require("druid.const") +local helper = require("druid.helper") local component = require("druid.component") -local M = component.create("scroll", { const.ON_UPDATE, const.ON_INPUT_HIGH }) +local M = component.create("scroll", { const.ON_UPDATE }) --- Global on all scrolls --- TODO: remove it -M.current_scroll = nil - - -local function get_border(node) - local pivot = gui.get_pivot(node) - local pivot_offset = helper.get_pivot_offset(pivot) - local size = vmath.mul_per_elem(gui.get_size(node), gui.get_scale(node)) - return vmath.vector4( - -size.x*(0.5 + pivot_offset.x), - size.y*(0.5 + pivot_offset.y), - size.x*(0.5 - pivot_offset.x), - -size.y*(0.5 - pivot_offset.y) - ) +local function inverse_lerp(min, max, current) + return helper.clamp((current - min) / (max - min), 0, 1) end -local function update_border(self) - local input_border = get_border(self.input_zone) - local content_border = get_border(self.node) +--- Update vector with next conditions: +-- Field x have to <= field z +-- Field y have to <= field w +local function get_border_vector(vector) + if vector.x > vector.z then + vector.x, vector.z = vector.z, vector.x + end + if vector.y > vector.w then + vector.y, vector.w = vector.w, vector.y + end - -- border.x - min content.x node pos - -- border.y - min content.y node pos - -- border.z - max content.x node pos - -- border.w - max content.y node pos - self.border = vmath.vector4( - input_border.x - content_border.x, - -input_border.w + content_border.w, - input_border.z - content_border.z, - -input_border.y + content_border.y - ) - self.can_x = (self.border.x ~= self.border.z) - self.can_y = (self.border.y ~= self.border.w) + return vector end +--- Return size from scroll border vector4 +local function get_size_vector(vector) + return vmath.vector3(vector.z - vector.x, vector.w - vector.y, 0) +end -local function set_pos(self, pos) - if self.pos.x ~= pos.x or self.pos.y ~= pos.y then - self.pos.x = pos.x - self.pos.y = pos.y - gui.set_position(self.node, self.pos) - self.on_scroll:trigger(self:get_context(), self.pos) +local function on_scroll_drag(self, dx, dy) + local t = self.target_position + local b = self.available_pos + local eb = self.available_pos_extra + + -- Handle soft zones + -- Percent - multiplier for delta. Less if outside of scroll zone + local x_perc = 1 + local y_perc = 1 + + -- Right border (minimum x) + if t.x < b.x and dx < 0 then + x_perc = inverse_lerp(eb.x, b.x, t.x) + end + -- Left border (maximum x) + if t.x > b.z and dx > 0 then + x_perc = inverse_lerp(eb.z, b.z, t.x) + end + -- Disable x scroll + if not self.drag.can_x then + x_perc = 0 + end + + -- Top border (minimum y) + if t.y < b.y and dy < 0 then + y_perc = inverse_lerp(eb.y, b.y, t.y) + end + -- Bot border (maximum y) + if t.y > b.w and dy > 0 then + y_perc = inverse_lerp(eb.w, b.w, t.y) + end + -- Disable y scroll + if not self.drag.can_y then + y_perc = 0 + end + + t.x = t.x + dx * x_perc + t.y = t.y + dy * y_perc +end + + +local function check_soft_zone(self) + local target = self.target_position + local border = self.available_pos + local speed = self.style.BACK_SPEED + + -- Right border (minimum x) + if target.x < border.x then + target.x = helper.step(target.x, border.x, math.abs(target.x - border.x) * speed) + end + -- Left border (maximum x) + if target.x > border.z then + target.x = helper.step(target.x, border.z, math.abs(target.x - border.z) * speed) + end + -- Top border (maximum y) + if target.y < border.y then + target.y = helper.step(target.y, border.y, math.abs(target.y - border.y) * speed) + end + -- Bot border (minimum y) + if target.y > border.w then + target.y = helper.step(target.y, border.w, math.abs(target.y - border.w) * speed) end end ---- Return scroll, if it outside of scroll area --- Using the lerp with BACK_SPEED koef -local function check_soft_target(self) - local t = self.target - local b = self.border - - if t.y < b.y then - t.y = helper.step(t.y, b.y, math.abs(t.y - b.y) * self.style.BACK_SPEED) - end - if t.x > b.x then - t.x = helper.step(t.x, b.x, math.abs(t.x - b.x) * self.style.BACK_SPEED) - end - if t.y > b.w then - t.y = helper.step(t.y, b.w, math.abs(t.y - b.w) * self.style.BACK_SPEED) - end - if t.x < b.z then - t.x = helper.step(t.x, b.z, math.abs(t.x - b.z) * self.style.BACK_SPEED) +--- Cancel animation on other animation or input touch +local function cancel_animate(self) + if self.is_animate then + self.target_position = gui.get_position(self.content_node) + self.position.x = self.target_position.x + self.position.y = self.target_position.y + gui.cancel_animation(self.content_node, gui.PROP_POSITION) + self.is_animate = false end end ---- Free inert update function -local function update_hand_scroll(self, dt) - local inert = self.inert - local delta_x = self.target.x - self.pos.x - local delta_y = self.target.y - self.pos.y - if helper.sign(delta_x) ~= helper.sign(inert.x) then - inert.x = 0 +local function set_scroll_position(self, position) + local available_extra = self.available_pos_extra + position.x = helper.clamp(position.x, available_extra.x, available_extra.z) + position.y = helper.clamp(position.y, available_extra.w, available_extra.y) + + if self.position.x ~= position.x or self.position.y ~= position.y then + self.position.x = position.x + self.position.y = position.y + gui.set_position(self.content_node, position) + + self.on_scroll:trigger(self:get_context(), self.position) end - if helper.sign(delta_y) ~= helper.sign(inert.y) then - inert.y = 0 - end - - inert.x = inert.x + delta_x - inert.y = inert.y + delta_y - - inert.x = math.abs(inert.x) * helper.sign(delta_x) - inert.y = math.abs(inert.y) * helper.sign(delta_y) - - inert.x = inert.x * self.style.FRICT_HOLD - inert.y = inert.y * self.style.FRICT_HOLD - - set_pos(self, self.target) -end - - -local function get_zone_center(self) - return self.pos + self.center_offset end @@ -154,13 +175,13 @@ local function check_points(self) return end - local inert = self.inert - if not self.is_inert then - if math.abs(inert.x) > self.style.DEADZONE then + local inert = self.inertion + if not self._is_inert then + if math.abs(inert.x) > self.style.POINTS_DEADZONE then self:scroll_to_index(self.selected - helper.sign(inert.x)) return end - if math.abs(inert.y) > self.style.DEADZONE then + if math.abs(inert.y) > self.style.POINTS_DEADZONE then self:scroll_to_index(self.selected + helper.sign(inert.y)) return end @@ -168,20 +189,22 @@ local function check_points(self) -- Find closest point and point by scroll direction -- Scroll to one of them (by scroll direction in priority) + local temp_dist = math.huge local temp_dist_on_inert = math.huge local index = false local index_on_inert = false - local pos = get_zone_center(self) + local pos = self.position + for i = 1, #self.points do local p = self.points[i] - local dist = helper.distance(pos.x, pos.y, p.x, p.y) + local dist = helper.distance(pos.x, pos.y, -p.x, -p.y) local on_inert = true -- If inert ~= 0, scroll only by move direction - if inert.x ~= 0 and helper.sign(inert.x) ~= helper.sign(p.x - pos.x) then + if inert.x ~= 0 and helper.sign(inert.x) ~= helper.sign(-p.x - pos.x) then on_inert = false end - if inert.y ~= 0 and helper.sign(inert.y) ~= helper.sign(p.y - pos.y) then + if inert.y ~= 0 and helper.sign(inert.y) ~= helper.sign(-p.y - pos.y) then on_inert = false end @@ -200,221 +223,173 @@ end local function check_threshold(self) - local inert = self.inert - if not self.is_inert or vmath.length(inert) < self.style.INERT_THRESHOLD then + local is_stopped = false + + if self.inertion.x ~= 0 and math.abs(self.inertion.x) < self.style.INERT_THRESHOLD then + is_stopped = true + self.inertion.x = 0 + end + if self.inertion.y ~= 0 and math.abs(self.inertion.y) < self.style.INERT_THRESHOLD then + is_stopped = true + self.inertion.y = 0 + end + + if is_stopped or not self._is_inert then check_points(self) - inert.x = 0 - inert.y = 0 end end -local function update_free_inert(self, dt) - local inert = self.inert - if inert.x ~= 0 or inert.y ~= 0 then - self.target.x = self.pos.x + (inert.x * dt * self.style.INERT_SPEED) - self.target.y = self.pos.y + (inert.y * dt * self.style.INERT_SPEED) +local function update_free_scroll(self, dt) + local target = self.target_position - inert.x = inert.x * self.style.FRICT - inert.y = inert.y * self.style.FRICT + if self._is_inert and (self.inertion.x ~= 0 or self.inertion.y ~= 0) then + -- Inertion apply + target.x = self.position.x + self.inertion.x * self.style.INERT_SPEED * dt + target.y = self.position.y + self.inertion.y * self.style.INERT_SPEED * dt - -- Stop, when low inert speed and go to points check_threshold(self) end - check_soft_target(self) - set_pos(self, self.target) -end + -- Inertion friction + self.inertion = self.inertion * self.style.FRICT - ---- Cancel animation on other animation or input touch -local function cancel_animate(self) - if self.animate then - self.target = gui.get_position(self.node) - self.pos.x = self.target.x - self.pos.y = self.target.y - gui.cancel_animation(self.node, gui.PROP_POSITION) - self.animate = false + check_soft_zone(self) + if self.position.x ~= target.x or self.position.y ~= target.y then + set_scroll_position(self, target) end end -local function add_delta(self, dx, dy) - local t = self.target - local b = self.border - local soft = self.soft_size +local function update_hand_scroll(self, dt) + local dx = self.target_position.x - self.position.x + local dy = self.target_position.y - self.position.y - -- TODO: Can we calc it more easier? - -- A lot of calculations for every side of border + self.inertion.x = (self.inertion.x + dx) * self.style.FRICT_HOLD + self.inertion.y = (self.inertion.y + dy) * self.style.FRICT_HOLD - -- Handle soft zones - -- Percent - multiplier for delta. Less if outside of scroll zone - local x_perc = 1 - local y_perc = 1 - - if t.x > b.x and dx < 0 then - x_perc = (soft - (b.x - t.x)) / soft - end - if t.x < b.z and dx > 0 then - x_perc = (soft - (t.x - b.z)) / soft - end - -- If disabled scroll by x - if not self.can_x then - x_perc = 0 - end - - if t.y < b.y and dy < 0 then - y_perc = (soft - (b.y - t.y)) / soft - end - if t.y > b.w and dy > 0 then - y_perc = (soft - (t.y - b.w)) / soft - end - -- If disabled scroll by y - if not self.can_y then - y_perc = 0 - end - - -- Reset inert if outside of scroll zone - if x_perc ~= 1 then - self.inert.x = 0 - end - if y_perc ~= 1 then - self.inert.y = 0 - end - - t.x = t.x + dx * x_perc - t.y = t.y + dy * y_perc + set_scroll_position(self, self.target_position) end ---- Component init function +local function on_touch_start(self) + self.inertion.x = 0 + self.inertion.y = 0 + self.target_position.x = self.position.x + self.target_position.y = self.position.y +end + + +local function on_touch_end(self) + check_threshold(self) +end + + +local function update_size(self) + local view_border = helper.get_border(self.view_node) + local view_size = vmath.mul_per_elem(gui.get_size(self.view_node), gui.get_scale(self.view_node)) + + local content_border = helper.get_border(self.content_node) + local content_size = vmath.mul_per_elem(gui.get_size(self.content_node), gui.get_scale(self.content_node)) + + self.available_pos = get_border_vector(view_border - content_border) + self.available_size = get_size_vector(self.available_pos) + + self.drag.can_x = self.available_size.x > 0 + self.drag.can_y = self.available_size.y > 0 + + -- Extra content size calculation + -- We add extra size only if scroll is available + -- Even the content zone size less than view zone size + local content_border_extra = helper.get_border(self.content_node) + + if self.drag.can_x then + local sign = content_size.x > view_size.x and 1 or -1 + content_border_extra.x = content_border_extra.x - self.extra_stretch_size * sign + content_border_extra.z = content_border_extra.z + self.extra_stretch_size * sign + end + + if self.drag.can_y then + local sign = content_size.y > view_size.y and 1 or -1 + content_border_extra.y = content_border_extra.y + self.extra_stretch_size * sign + content_border_extra.w = content_border_extra.w - self.extra_stretch_size * sign + end + + if not self.style.SMALL_CONTENT_SCROLL then + self.drag.can_x = content_size.x > view_size.x + self.drag.can_y = content_size.y > view_size.y + end + + self.available_pos_extra = get_border_vector(view_border - content_border_extra) + self.available_size_extra = get_size_vector(self.available_pos_extra) +end + + +--- Scroll constructor. -- @function scroll:init --- @tparam node scroll_parent Gui node where placed scroll content. This node will change position --- @tparam node input_zone Gui node where input is catched -function M.init(self, scroll_parent, input_zone) +-- @tparam node view_node GUI view scroll node +-- @tparam node content_node GUI content scroll node +function M.init(self, view_node, content_node) + self.druid = self:get_druid() self.style = self:get_style() - self.node = self:get_node(scroll_parent) - self.input_zone = self:get_node(input_zone) - self.zone_size = gui.get_size(self.input_zone) - self.soft_size = self.style.SOFT_ZONE_SIZE + self.view_node = self:get_node(view_node) + self.content_node = self:get_node(content_node) - -- Distance from node to node's center - local offset = helper.get_pivot_offset(gui.get_pivot(self.input_zone)) - self.center_offset = vmath.vector3(self.zone_size) - self.center_offset.x = self.center_offset.x * offset.x - self.center_offset.y = self.center_offset.y * offset.y + self.position = gui.get_position(self.content_node) + self.target_position = vmath.vector3(self.position) + self.inertion = vmath.vector3(0) - self.is_inert = true - self.inert = vmath.vector3(0) - self.pos = gui.get_position(self.node) - self.target = vmath.vector3(self.pos) - - self.input = { - touch = false, - start_x = 0, - start_y = 0, - side = false, - } - - update_border(self) + self.drag = self.druid:new_drag(view_node, on_scroll_drag) + self.drag.on_touch_start:subscribe(on_touch_start) + self.drag.on_touch_end:subscribe(on_touch_end) self.on_scroll = Event() self.on_scroll_to = Event() self.on_point_scroll = Event() + + self.selected = nil + self._is_inert = true + self.is_animate = false + self.extra_stretch_size = self.style.EXTRA_STRECH_SIZE + + update_size(self) end function M.update(self, dt) - if self.input.touch then - if M.current_scroll == self then - update_hand_scroll(self, dt) - end + if self.drag.is_drag then + update_hand_scroll(self, dt) else - update_free_inert(self, dt) + update_free_scroll(self, dt) end end -function M.on_input(self, action_id, action) - if action_id ~= const.ACTION_TOUCH then - return false - end - local inp = self.input - local inert = self.inert - local result = false - - if gui.pick_node(self.input_zone, action.x, action.y) then - if action.pressed then - inp.touch = true - inp.start_x = action.x - inp.start_y = action.y - inert.x = 0 - inert.y = 0 - self.target.x = self.pos.x - self.target.y = self.pos.y - else - local dist = helper.distance(action.x, action.y, inp.start_x, inp.start_y) - if not M.current_scroll and dist >= self.style.DEADZONE then - local dx = math.abs(inp.start_x - action.x) - local dy = math.abs(inp.start_y - action.y) - inp.side = (dx > dy) and const.SIDE.X or const.SIDE.Y - - -- Check scroll side if we can scroll - if (self.can_x and inp.side == const.SIDE.X or - self.can_y and inp.side == const.SIDE.Y) then - M.current_scroll = self - end - end - end - end - - if inp.touch and not action.pressed then - if M.current_scroll == self then - add_delta(self, action.dx, action.dy) - result = true - end - end - - if action.released then - inp.touch = false - inp.side = false - if M.current_scroll == self then - M.current_scroll = nil - result = true - end - - check_threshold(self) - end - - return result -end - - ---- Start scroll to target point +--- Start scroll to target point. -- @function scroll:scroll_to --- @tparam point vector3 target point --- @tparam[opt] bool is_instant instant scroll flag +-- @tparam point vector3 Target point +-- @tparam[opt] bool is_instant Instant scroll flag -- @usage scroll:scroll_to(vmath.vector3(0, 50, 0)) -- @usage scroll:scroll_to(vmath.vector3(0), true) function M.scroll_to(self, point, is_instant) - local b = self.border - local target = vmath.vector3(point) - target.x = helper.clamp(point.x - self.center_offset.x, b.x, b.z) - target.y = helper.clamp(point.y - self.center_offset.y, b.y, b.w) + local b = self.available_pos + local target = vmath.vector3(-point.x, -point.y, 0) + target.x = helper.clamp(target.x, b.x, b.z) + target.y = helper.clamp(target.y, b.y, b.w) cancel_animate(self) - self.animate = not is_instant + self.is_animate = not is_instant if is_instant then - self.target = target - set_pos(self, target) + self.target_position = target + set_scroll_position(self, target) else - gui.animate(self.node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, self.style.ANIM_SPEED, 0, function() - self.animate = false - self.target = target - set_pos(self, target) + gui.animate(self.content_node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, self.style.ANIM_SPEED, 0, function() + self.is_animate = false + self.target_position = target + set_scroll_position(self, target) end) end @@ -422,36 +397,15 @@ function M.scroll_to(self, point, is_instant) end ---- Start scroll to target scroll percent --- @function scroll:scroll_to_percent --- @tparam point vector3 target percent --- @tparam[opt] bool is_instant instant scroll flag --- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0)) -function M.scroll_to_percent(self, percent, is_instant) - local border = self.border - - local size_x = math.abs(border.z - border.x) - if size_x == 0 then - size_x = 1 - end - local size_y = math.abs(border.w - border.y) - if size_y == 0 then - size_y = 1 - end - - local pos = vmath.vector3( - -size_x * percent.x + border.x, - -size_y * percent.y + border.y, - 0) - M.scroll_to(self, pos, is_instant) -end - - ---- Scroll to item in scroll by point index --- @function scroll:init +--- Scroll to item in scroll by point index. +-- @function scroll:scroll_to_index -- @tparam number index Point index -- @tparam[opt] bool skip_cb If true, skip the point callback function M.scroll_to_index(self, index, skip_cb) + if not self.points then + return + end + index = helper.clamp(index, 1, #self.points) if self.selected ~= index then @@ -466,21 +420,46 @@ function M.scroll_to_index(self, index, skip_cb) end ---- Set points of interest. --- Scroll will always centered on closer points --- @function scroll:set_points --- @tparam table points Array of vector3 points -function M.set_points(self, points) - self.points = points - -- cause of parent move in other side by y - for i = 1, #self.points do - self.points[i].y = -self.points[i].y - end +--- Start scroll to target scroll percent +-- @function scroll:scroll_to_percent +-- @tparam point vector3 target percent +-- @tparam[opt] bool is_instant instant scroll flag +-- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0)) +function M.scroll_to_percent(self, percent, is_instant) + local border = self.available_pos - table.sort(self.points, function(a, b) - return a.x > b.x or a.y < b.y - end) - check_threshold(self) + local pos = vmath.vector3( + -helper.lerp(border.x, border.z, 1 - percent.x), + -helper.lerp(border.w, border.y, 1 - percent.y), + 0 + ) + + M.scroll_to(self, pos, is_instant) +end + + +--- Return current scroll progress status. +-- Values will be in [0..1] interval +-- @function scroll:get_percent +-- @treturn vector3 New vector with scroll progress values +function M.get_percent(self) + local x_perc = 1 - inverse_lerp(self.available_pos.x, self.available_pos.z, self.position.x) + local y_perc = inverse_lerp(self.available_pos.w, self.available_pos.y, self.position.y) + + return vmath.vector3(x_perc, y_perc, 0) +end + + +--- Set scroll content size. +-- It will change content gui node size +-- @function scroll:set_size +-- @tparam vector3 size The new size for content node +-- @treturn druid.scroll Self instance +function M.set_size(self, size) + gui.set_size(self.content_node, size) + update_size(self) + + return self end @@ -489,49 +468,57 @@ end -- If no points, just simple drag without inertion -- @function scroll:set_inert -- @tparam bool state Inert scroll state +-- @treturn druid.scroll Self instance function M.set_inert(self, state) - self.is_inert = state + self._is_inert = state + return self end ---- Set the callback on scrolling to point (if exist) --- @function scroll:on_point_move --- @tparam function callback Callback on scroll to point of interest -function M.on_point_move(self, callback) - self.on_point_scroll:subscribe(callback) +--- Return if scroll have inertion. +-- @function scroll:is_inert +-- @treturn bool If scroll have inertion +function M.is_inert(self) + return self._is_inert end ---- Set the scroll possibly area --- @function scroll:set_border --- @tparam vector3 border Size of scrolling area -function M.set_border(self, content_size) - gui.set_size(self.node, content_size) - update_border(self) +--- Set extra size for scroll stretching. +-- Set 0 to disable stretching effect +-- @function scroll:set_extra_strech_size +-- @tparam number stretch_size Size in pixels of additional scroll area +-- @treturn druid.scroll Self instance +function M.set_extra_strech_size(self, stretch_size) + self.extra_stretch_size = stretch_size or self.style.EXTRA_STRECH_SIZE + update_size(self) + + return self end ---- Return current scroll progress --- @function scroll:get_scroll_percent --- @treturn vector3 Scroll progress -function M.get_scroll_percent(self) - local border = self.border - local size_x = math.abs(border.z - border.x) - if size_x == 0 then - size_x = 1 - end +--- Return vector of scroll size with width and height. +-- @function scroll:get_scroll_size +-- @treturn vector3 Available scroll size +function M.get_scroll_size(self) + return self.available_size +end - local size_y = math.abs(border.w - border.y) - if size_y == 0 then - size_y = 1 - end - local pos = self.pos - return vmath.vector3( - (border.x - pos.x) / size_x, - (border.y - pos.y) / size_y, - 0 - ) +--- Set points of interest. +-- Scroll will always centered on closer points +-- @function scroll:set_points +-- @tparam table points Array of vector3 points +-- @treturn druid.scroll Self instance +function M.set_points(self, points) + self.points = points + + table.sort(self.points, function(a, b) + return a.x > b.x or a.y < b.y + end) + + check_threshold(self) + + return self end diff --git a/druid/base/text.lua b/druid/base/text.lua index 5a668ee..a6c7f2e 100644 --- a/druid/base/text.lua +++ b/druid/base/text.lua @@ -196,7 +196,7 @@ end --- Return true, if text with line break -- @function text:is_multiline --- @treturn boolean Is text node with line break +-- @treturn bool Is text node with line break function M.is_multiline(self) return gui.get_line_break(self.node) end diff --git a/druid/const.lua b/druid/const.lua index ae6d4ce..1db17e2 100644 --- a/druid/const.lua +++ b/druid/const.lua @@ -14,6 +14,7 @@ M.ACTION_ESC = hash("key_esc") M.ACTION_TOUCH = hash("touch") M.ACTION_SCROLL_UP = hash("scroll_up") +M.ACTION_MULTITOUCH = hash("multitouch") M.ACTION_SCROLL_DOWN = hash("scroll_down") @@ -63,11 +64,22 @@ M.UI_INPUT = { } +M.OS = { + ANDROID = "Android", + IOS = "iPhone OS", + MAC = "Darwin", + LINUX = "Linux", + WINDOWS = "Windows", + BROWSER = "HTML5", +} + + M.SIDE = { X = "x", Y = "y" } + M.SWIPE = { UP = "up", DOWN = "down", diff --git a/druid/druid.lua b/druid/druid.lua index eb10f44..c3b4533 100644 --- a/druid/druid.lua +++ b/druid/druid.lua @@ -73,11 +73,11 @@ function M.set_default_style(style) end ---- Set text function. +--- Set text function -- Druid locale component will call this function -- to get translated text. After set_text_funtion -- all existing locale component will be updated --- @function druid.set_text_function(callback) +-- @function druid.set_text_function -- @tparam function callback Get localized text function function M.set_text_function(callback) settings.get_text = callback or const.EMPTY_FUNCTION diff --git a/druid/helper.lua b/druid/helper.lua index ccd08a4..1e1076f 100644 --- a/druid/helper.lua +++ b/druid/helper.lua @@ -126,6 +126,11 @@ function M.round(num, numDecimalPlaces) end +function M.lerp(a, b, t) + return a + (b - a) * t +end + + --- Check if node is enabled in gui hierarchy. -- Return false, if node or any his parent is disabled -- @function helper.is_enabled @@ -152,4 +157,35 @@ function M.get_pivot_offset(pivot) end +--- Check if device is mobile (Android or iOS) +-- @function helper..is_mobile +function M.is_mobile() + local system_name = sys.get_sys_info().system_name + return system_name == const.OS.IOS or system_name == const.OS.ANDROID +end + + +--- Check if device is HTML5 +-- @function helper.is_web +function M.is_web() + local system_name = sys.get_sys_info().system_name + return system_name == const.OS.BROWSER +end + + +--- Distance from node to size border +-- @function helper.get_border +-- @return vector4 (left, top, right, down) +function M.get_border(node) + local pivot = gui.get_pivot(node) + local pivot_offset = M.get_pivot_offset(pivot) + local size = vmath.mul_per_elem(gui.get_size(node), gui.get_scale(node)) + return vmath.vector4( + -size.x*(0.5 + pivot_offset.x), + size.y*(0.5 - pivot_offset.y), + size.x*(0.5 - pivot_offset.x), + -size.y*(0.5 + pivot_offset.y) + ) +end + return M diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua index 817a4d4..cd21fe7 100644 --- a/druid/styles/default/style.lua +++ b/druid/styles/default/style.lua @@ -43,16 +43,24 @@ M["button"] = { } +M["drag"] = { + DRAG_DEADZONE = 10, -- Size in pixels of drag deadzone +} + + M["scroll"] = { - FRICT_HOLD = 0.8, -- mult. for inert, while touching + ANIM_SPEED = 0.2, -- gui.animation speed to point + BACK_SPEED = 0.35, -- Lerp speed of return to soft position FRICT = 0.93, -- mult for free inert - INERT_THRESHOLD = 2, -- speed to stop inertion - INERT_SPEED = 25, -- koef. of inert speed - DEADZONE = 6, -- in px - SOFT_ZONE_SIZE = 160, -- size of outside zone (back move) - SCROLL_WHEEL_SPEED = 10, - BACK_SPEED = 0.2, -- lerp speed - ANIM_SPEED = 0.3, -- gui.animation speed to point + FRICT_HOLD = 0.79, -- mult. for inert, while touching + INERT_THRESHOLD = 2.5, -- speed to stop inertion + INERT_SPEED = 30, -- koef. of inert speed + EXTRA_STRECH_SIZE = 100, -- extra size in pixels outside of scroll (stretch effect) + POINTS_DEADZONE = 20, -- Speed to check points of interests in no_inertion mode + + SCROLL_WHEEL_SPEED = 20, + + SMALL_CONTENT_SCROLL = true, -- If true, content node with size less than view node size can be scrolled } @@ -62,11 +70,6 @@ M["progress"] = { } -M["progress_rich"] = { - DELAY = 1, -- delay in seconds before main fill -} - - M["checkbox"] = { on_change_state = function(self, node, state) local target = state and 1 or 0 diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index 9c04b33..bd02e44 100644 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -16,6 +16,7 @@ -- @see druid.checkbox_group -- @see druid.radio_group -- @see druid.swipe +-- @see druid.drag local const = require("druid.const") local druid_input = require("druid.helper.druid_input") @@ -38,6 +39,7 @@ local checkbox_group = require("druid.base.checkbox_group") local radio_group = require("druid.base.radio_group") local input = require("druid.base.input") local swipe = require("druid.base.swipe") +local drag = require("druid.base.drag") -- local infinity_scroll = require("druid.base.infinity_scroll") -- @classmod Druid @@ -447,4 +449,13 @@ function Druid.new_swipe(self, ...) end +--- Create drag basic component +-- @function druid:new_drag +-- @tparam args ... drag init args +-- @treturn Componetn drag component +function Druid.new_drag(self, ...) + return Druid.create(self, drag, ...) +end + + return Druid diff --git a/example/gui/main/main.gui b/example/gui/main/main.gui index f1883f8..de6f1e6 100644 --- a/example/gui/main/main.gui +++ b/example/gui/main/main.gui @@ -198,7 +198,7 @@ nodes { } size { x: 600.0 - y: 1250.0 + y: 1500.0 z: 0.0 w: 1.0 } @@ -5334,7 +5334,7 @@ nodes { z: 0.0 w: 0.0 } - clipping_mode: CLIPPING_MODE_STENCIL + clipping_mode: CLIPPING_MODE_NONE clipping_visible: true clipping_inverted: false alpha: 1.0 @@ -5362,7 +5362,7 @@ nodes { } size { x: 600.0 - y: 1900.0 + y: 2100.0 z: 0.0 w: 1.0 } @@ -5389,7 +5389,7 @@ nodes { z: 0.0 w: 0.0 } - clipping_mode: CLIPPING_MODE_NONE + clipping_mode: CLIPPING_MODE_STENCIL clipping_visible: true clipping_inverted: false alpha: 1.0 @@ -5925,7 +5925,7 @@ nodes { } nodes { position { - x: -300.0 + x: -287.0 y: 0.0 z: 0.0 w: 1.0 @@ -6789,6 +6789,572 @@ nodes { text_leading: 1.0 text_tracking: 0.0 } +nodes { + position { + x: 0.0 + y: -1300.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: 300.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: "kenney/empty" + id: "scroll_with_points" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_page_content" + layer: "image" + 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 +} +nodes { + position { + x: -300.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: 2400.0 + y: 300.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.9019608 + y: 0.5019608 + z: 0.3019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "scroll_with_points_content" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_W + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_with_points" + layer: "image" + 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 +} +nodes { + position { + x: 300.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: 250.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.9019608 + y: 0.7019608 + z: 0.9019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "intereset_point_1" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_with_points_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 +} +nodes { + position { + x: 900.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: 250.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 0.7019608 + z: 0.7019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "intereset_point_2" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_with_points_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 +} +nodes { + position { + x: 1500.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: 250.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 0.9019608 + z: 0.7019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "intereset_point_3" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_with_points_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 +} +nodes { + position { + x: 2100.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: 250.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 0.6 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "intereset_point_4" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_with_points_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 +} +nodes { + position { + x: 0.0 + y: -1750.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: 550.0 + y: 500.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.5019608 + y: 0.2 + z: 0.3019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "scroll_smaller_view" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_page_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 +} +nodes { + position { + x: -197.0 + y: 223.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_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "View" + font: "game" + id: "scroll_smaller_view_hint" + 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: "scroll_smaller_view" + 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 +} +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: 200.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.4 + y: 0.3019608 + z: 0.7019608 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "scroll_smaller_content" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "scroll_smaller_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: 0.5 + template_node_child: false + size_mode: SIZE_MODE_MANUAL +} +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_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Content" + font: "game" + id: "scroll_smaller_content_hint" + 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: "scroll_smaller_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 +} nodes { position { x: 2400.0 diff --git a/example/gui/main/main.gui_script b/example/gui/main/main.gui_script index f38a0ae..3cf9b6a 100644 --- a/example/gui/main/main.gui_script +++ b/example/gui/main/main.gui_script @@ -3,12 +3,12 @@ local druid = require("druid.druid") local empty_style = require("druid.styles.empty.style") local default_style = require("druid.styles.default.style") -local main_page = require("example.page.main") -local text_page = require("example.page.texts") -local button_page = require("example.page.button") -local scroll_page = require("example.page.scroll") -local slider_page = require("example.page.slider") -local input_page = require("example.page.input") +local main_page = require("example.page.main_page") +local text_page = require("example.page.texts_page") +local button_page = require("example.page.button_page") +local scroll_page = require("example.page.scroll_page") +local slider_page = require("example.page.slider_page") +local input_page = require("example.page.input_page") local pages = { "main_page", @@ -21,12 +21,8 @@ local pages = { local function on_control_button(self, delta) self.page = self.page + delta - if self.page < 1 then - self.page = #pages - end - if self.page > #pages then - self.page = 1 - end + self.page = math.max(1, self.page) + self.page = math.min(self.page, #pages) self.header:translate(pages[self.page]) local node = gui.get_node("C_Anchor") @@ -35,6 +31,7 @@ end local function init_top_panel(self) + self.druid:new_blocker("panel_top") self.druid:new_button("button_left/button", on_control_button, -1) self.druid:new_button("button_right/button", on_control_button, 1) self.header = self.druid:new_lang_text("text_header", "main_page") @@ -64,8 +61,8 @@ function init(self) window.set_listener(on_window_callback) - init_top_panel(self) init_swipe_control(self) + self.page = 1 main_page.setup_page(self) text_page.setup_page(self) @@ -74,6 +71,8 @@ function init(self) slider_page.setup_page(self) input_page.setup_page(self) + init_top_panel(self) + -- Refresh state on_control_button(self, 0) end diff --git a/example/page/button_page.lua b/example/page/button_page.lua new file mode 100644 index 0000000..e736935 --- /dev/null +++ b/example/page/button_page.lua @@ -0,0 +1,53 @@ +local sprite_style = require("druid.styles.sprites.style") + +local M = {} + + +local function usual_callback() + print("Usual callback") +end + +local function long_tap_callback(self, params, button, hold_time) + print("Long tap callback", hold_time) +end + +local function hold_callback(self, params, button, hold_time) + print("On hold callback", hold_time) +end + +local function repeated_callback(self, params, button, click_in_row) + print("Repeated callback", click_in_row) +end + +local function double_tap_callback(self, params, button, click_in_row) + print("Double tap callback", click_in_row) +end + + +local function setup_buttons(self) + self.druid:new_button("button_usual/button", usual_callback) + + local custom_style = self.druid:new_button("button_custom_style/button", usual_callback) + custom_style:set_style(sprite_style) + + local long_button = self.druid:new_button("button_long_tap/button", usual_callback) + long_button.on_hold_callback:subscribe(hold_callback) + long_button.on_long_click:subscribe(long_tap_callback) + self.druid:new_button("button_repeated_tap/button", usual_callback) + .on_repeated_click:subscribe(repeated_callback) + self.druid:new_button("button_double_tap/button", usual_callback) + .on_double_click:subscribe(double_tap_callback) + + local button_space = self.druid:new_button("button_key_trigger/button", usual_callback) + button_space:set_key_trigger("key_space") + button_space.on_long_click:subscribe(long_tap_callback) + button_space.on_double_click:subscribe(double_tap_callback) +end + + +function M.setup_page(self) + setup_buttons(self) +end + + +return M diff --git a/example/page/input.lua b/example/page/input_page.lua similarity index 100% rename from example/page/input.lua rename to example/page/input_page.lua diff --git a/example/page/main.lua b/example/page/main_page.lua similarity index 97% rename from example/page/main.lua rename to example/page/main_page.lua index a56eab1..5563c0d 100644 --- a/example/page/main.lua +++ b/example/page/main_page.lua @@ -97,7 +97,7 @@ end local function setup_scroll(self) - self.scroll = self.druid:new_scroll("scroll_content", "main_page") + self.druid:new_scroll("main_page", "scroll_content") end diff --git a/example/page/scroll.lua b/example/page/scroll.lua deleted file mode 100644 index 73bc819..0000000 --- a/example/page/scroll.lua +++ /dev/null @@ -1,54 +0,0 @@ -local M = {} - - -local function init_grid(self) - local prefab = gui.get_node("grid_prefab") - - local grid_scroll = self.druid:new_scroll("grid_content", "scroll_with_grid_size") - local grid = self.druid:new_grid("grid_content", "grid_prefab", 20) - - for i = 1, 40 do - local clone_prefab = gui.clone_tree(prefab) - - grid:add(clone_prefab["grid_prefab"]) - gui.set_text(clone_prefab["grid_prefab_text"], "Node " .. i) - - local button = self.druid:new_button(clone_prefab["grid_button"], function() - local position = gui.get_position(clone_prefab["grid_prefab"]) - position.x = -position.x - grid_scroll:scroll_to(position) - end) - button:set_click_zone(gui.get_node("scroll_with_grid_size")) - end - - gui.set_enabled(prefab, false) - - grid_scroll:set_border(grid:get_size()) - - local scroll_slider = self.druid:new_slider("grid_scroll_pin", vmath.vector3(300, 0, 0), function(_, value) - grid_scroll:scroll_to_percent(vmath.vector3(value, 0, 0), true) - end) - - grid_scroll.on_scroll:subscribe(function(_, point) - scroll_slider:set(grid_scroll:get_scroll_percent().x, true) - end) -end - - -function M.setup_page(self) - self.druid:new_scroll("scroll_page_content", "scroll_page") - self.druid:new_scroll("simple_scroll_content", "simple_scroll_input") - - -- scroll contain scrolls: - -- parent first - self.druid:new_scroll("children_scroll_content", "children_scroll") - -- chilren next - self.druid:new_scroll("children_scroll_content_1", "children_scroll_1") - self.druid:new_scroll("children_scroll_content_2", "children_scroll_2") - self.druid:new_scroll("children_scroll_content_3", "children_scroll_3") - - init_grid(self) -end - - -return M diff --git a/example/page/scroll_page.lua b/example/page/scroll_page.lua new file mode 100644 index 0000000..f48ec74 --- /dev/null +++ b/example/page/scroll_page.lua @@ -0,0 +1,71 @@ +local M = {} + + +local function init_scroll_with_grid(self) + local prefab = gui.get_node("grid_prefab") + + local grid_scroll = self.druid:new_scroll("scroll_with_grid_size", "grid_content") + local grid = self.druid:new_grid("grid_content", "grid_prefab", 20) + + for i = 1, 40 do + local clone_prefab = gui.clone_tree(prefab) + + grid:add(clone_prefab["grid_prefab"]) + gui.set_text(clone_prefab["grid_prefab_text"], "Node " .. i) + + local button = self.druid:new_button(clone_prefab["grid_button"], function() + local position = gui.get_position(clone_prefab["grid_prefab"]) + grid_scroll:scroll_to(position) + end) + button:set_click_zone(gui.get_node("scroll_with_grid_size")) + end + + gui.set_enabled(prefab, false) + + grid_scroll:set_size(grid:get_size()) + + local scroll_slider = self.druid:new_slider("grid_scroll_pin", vmath.vector3(287, 0, 0), function(_, value) + grid_scroll:scroll_to_percent(vmath.vector3(value, 0, 0), true) + end) + + grid_scroll.on_scroll:subscribe(function(_, point) + scroll_slider:set(grid_scroll:get_percent().x, true) + end) +end + + +function M.setup_page(self) + -- Usual scroll for whole page + self.druid:new_scroll("scroll_page", "scroll_page_content") + + -- Simple scroll with no adjust + self.druid:new_scroll("simple_scroll_input", "simple_scroll_content") + + -- Scroll with grid example + init_scroll_with_grid(self) + + -- Scroll contain children scrolls: + -- Parent scroll + self.druid:new_scroll("children_scroll", "children_scroll_content") + -- Childre scrolls + self.druid:new_scroll("children_scroll_1", "children_scroll_content_1") + self.druid:new_scroll("children_scroll_2", "children_scroll_content_2") + self.druid:new_scroll("children_scroll_3", "children_scroll_content_3") + + -- Content with less size than view + self.druid:new_scroll("scroll_smaller_view", "scroll_smaller_content") + :set_extra_strech_size(0) + :set_inert(false) + + -- Scroll with points of interests + self.druid:new_scroll("scroll_with_points", "scroll_with_points_content") + :set_points({ + vmath.vector3(300, 0, 0), + vmath.vector3(900, 0, 0), + vmath.vector3(1500, 0, 0), + vmath.vector3(2100, 0, 0), + }) +end + + +return M diff --git a/example/page/slider.lua b/example/page/slider_page.lua similarity index 100% rename from example/page/slider.lua rename to example/page/slider_page.lua diff --git a/example/page/texts.lua b/example/page/texts_page.lua similarity index 100% rename from example/page/texts.lua rename to example/page/texts_page.lua diff --git a/input/game.input_binding b/input/game.input_binding index b873ebd..0b6d8ca 100644 --- a/input/game.input_binding +++ b/input/game.input_binding @@ -18,10 +18,6 @@ key_trigger { input: KEY_ESC action: "key_esc" } -mouse_trigger { - input: MOUSE_BUTTON_1 - action: "touch" -} mouse_trigger { input: MOUSE_WHEEL_UP action: "scroll_up" @@ -30,6 +26,14 @@ mouse_trigger { input: MOUSE_WHEEL_DOWN action: "scroll_down" } +mouse_trigger { + input: MOUSE_BUTTON_1 + action: "touch" +} +touch_trigger { + input: TOUCH_MULTI + action: "multitouch" +} text_trigger { input: TEXT action: "text"