Merge pull request #177 from Insality/custom_components

Update with custom components issues scope
This commit is contained in:
Maxim Tuprikov
2022-03-10 20:32:13 +02:00
committed by GitHub
75 changed files with 6662 additions and 585 deletions

View File

@@ -57,13 +57,25 @@ input_scroll_down = scroll_down
By default, **Druid** will auto-capture input focus, if any input component will be created. So you don't need to call `msg.post(".", "acquire_input_focus")`
If you don't need this behaviour, you can disable it by settings `druid.no_auto_input` field in _game.project_:
If you don't need this behaviour, you can disable it by setting `druid.no_auto_input` field in _game.project_:
```
[druid]
no_auto_input = 1
```
### Template name check [optional]
By default, **Druid** will auto check the parent component template name to build the full template name for component.
If for some reason you want to pass the full template name by yourself, you can disable it by setting `druid.no_auto_template` field in _game.project_:
```
[druid]
no_auto_template = 1
```
### Stencil check [optional]
When creating input components inside stencil nodes, you probably will use `component:set_click_zone()` to restrict clicks outside this stencil zone.
@@ -73,6 +85,7 @@ Druid can do it automatically on _late_init_ component step. To enable this feat
stencil_check = 1
```
### Code [optional]
Adjust **Druid** settings, if needed:
@@ -265,11 +278,6 @@ You can fund the full **Druid** documentation here:
https://insality.github.io/druid/
## Games powered by Druid
_You published your game and you using Druid? Note me!_
## License
- Developed and supported by [Insality](https://github.com/Insality)

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,12 @@ description='Documentation for Druid Library'
file={"./druid",
exclude = {
"./druid/styles/",
"./druid/system/middleclass.lua"
"./druid/system/middleclass.lua",
"./druid/templates/"
}
}
package='druid'
sort=false
sort=true
dir='./docs'
style='!fixed'
topics={}

30
druid.code-workspace Normal file
View File

@@ -0,0 +1,30 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"files.exclude": {
"**/.git": true, // this is a default value
"**/.DS_Store": true, // this is a default value
"**/node_modules": true, // this excludes all folders
// named "node_modules" from
// the explore tree
// alternative version
"node_modules": true, // this excludes the folder
// only from the root of
// your workspace
".internal": true,
"bundle": true,
"input": true,
"media": true,
"build": true,
".github": true,
".deployer_cache": true,
"dist": true
}
}
}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle back key (android, backspace)
-- @module BackHandler
@@ -6,7 +6,7 @@
-- @alias druid.back_handler
--- On back handler callback(self, params)
-- @tfield druid_event on_back
-- @tfield DruidEvent on_back @{DruidEvent}
--- Params to back callback
-- @tfield any params
@@ -21,7 +21,7 @@ local BackHandler = component.create("back_handler")
--- Component init function
-- @tparam BackHandler self
-- @tparam BackHandler self @{BackHandler}
-- @tparam callback callback On back button
-- @tparam[opt] any params Callback argument
function BackHandler.init(self, callback, params)
@@ -31,7 +31,7 @@ end
--- Input handler for component
-- @tparam BackHandler self
-- @tparam BackHandler self @{BackHandler}
-- @tparam string action_id on_input action id
-- @tparam table action on_input action
function BackHandler.on_input(self, action_id, action)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to block input on specify zone by node
-- @module Blocker
@@ -17,7 +17,7 @@ local Blocker = component.create("blocker")
--- Component init function
-- @tparam Blocker self
-- @tparam Blocker self @{Blocker}
-- @tparam node node Gui node
function Blocker.init(self, node)
self.node = self:get_node(node)
@@ -44,7 +44,7 @@ end
--- Set enabled blocker component state
-- @tparam Blocker self
-- @tparam Blocker self @{Blocker}
-- @tparam bool state Enabled state
function Blocker.set_enabled(self, state)
gui.set_enabled(self.node, state)
@@ -52,7 +52,7 @@ end
--- Return blocked enabled state
-- @tparam Blocker self
-- @tparam Blocker self @{Blocker}
-- @treturn bool True, if blocker is enabled
function Blocker.is_enabled(self)
return gui.is_enabled(self.node)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle basic GUI button
-- @module Button
@@ -6,22 +6,22 @@
-- @alias druid.button
--- On release button callback(self, params, button_instance)
-- @tfield druid_event on_click
-- @tfield DruidEvent on_click @{DruidEvent}
--- On repeated action button callback(self, params, button_instance, click_amount)
-- @tfield druid_event on_repeated_click
-- @tfield DruidEvent on_repeated_click @{DruidEvent}
---On long tap button callback(self, params, button_instance, time)
-- @tfield druid_event on_long_click
-- @tfield DruidEvent on_long_click @{DruidEvent}
---On double tap button callback(self, params, button_instance, click_amount)
-- @tfield druid_event on_double_click
-- @tfield DruidEvent on_double_click @{DruidEvent}
---On button hold before long_click callback(self, params, button_instance, time)
-- @tfield druid_event on_hold_callback
-- @tfield DruidEvent on_hold_callback @{DruidEvent}
---On click outside of button(self, params, button_instance)
-- @tfield druid_event on_click_outside
-- @tfield DruidEvent on_click_outside @{DruidEvent}
---Trigger node
-- @tfield node node
@@ -45,7 +45,7 @@
-- @tfield any params
---Druid hover logic component
-- @tfield druid.hover hover
-- @tfield Hover hover @{Hover}
---Restriction zone
-- @tfield[opt] node click_zone
@@ -193,7 +193,7 @@ end
--- Component init function
-- @tparam Button self
-- @tparam Button self @{Button}
-- @tparam node node Gui node
-- @tparam function callback Button callback
-- @tparam[opt] table params Button callback params
@@ -339,7 +339,7 @@ end
--- Set enabled button component state
-- @tparam Button self
-- @tparam Button self @{Button}
-- @tparam bool state Enabled state
-- @treturn Button Current button instance
function Button.set_enabled(self, state)
@@ -352,7 +352,7 @@ end
--- Return button enabled state
-- @tparam Button self
-- @tparam Button self @{Button}
-- @treturn bool True, if button is enabled
function Button.is_enabled(self)
return not self.disabled
@@ -361,7 +361,7 @@ end
--- Strict button click area. Useful for
-- no click events outside stencil node
-- @tparam Button self
-- @tparam Button self @{Button}
-- @tparam node zone Gui node
-- @treturn Button Current button instance
function Button.set_click_zone(self, zone)
@@ -373,7 +373,7 @@ end
--- Set key-code to trigger this button
-- @tparam Button self
-- @tparam Button self @{Button}
-- @tparam hash key The action_id of the key
-- @treturn Button Current button instance
function Button.set_key_trigger(self, key)
@@ -392,6 +392,7 @@ end
--- Set function for additional check for button click availability
-- @tparam Button self
-- @tparam[opt] function check_function Should return true or false. If true - button can be pressed.
-- @tparam[opt] function failure_callback Function what will be called on button click, if check function return false
-- @treturn Button Current button instance

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle drag action on node.
-- Drag have correct handling for multitouch and swap
@@ -9,19 +9,19 @@
-- @alias druid.drag
--- Event on touch start callback(self)
-- @tfield druid_event on_touch_start
-- @tfield DruidEvent on_touch_start @{DruidEvent}
--- Event on touch end callback(self)
-- @tfield druid_event on_touch_end
-- @tfield DruidEvent on_touch_end @{DruidEvent}
--- Event on drag start callback(self)
-- @tfield druid_event on_drag_start
-- @tfield DruidEvent on_drag_start @{DruidEvent}
--- on drag progress callback(self, dx, dy)
-- @tfield druid_event on_drag Event
-- @tfield DruidEvent on_drag Event @{DruidEvent}
--- Event on drag end callback(self)
-- @tfield druid_event on_drag_end
-- @tfield DruidEvent on_drag_end @{DruidEvent}
--- Is component now touching
-- @tfield bool is_touch
@@ -162,7 +162,7 @@ end
--- Drag component constructor
-- @tparam Drag self
-- @tparam Drag self @{Drag}
-- @tparam node node GUI node to detect dragging
-- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy)
function Drag.init(self, node, on_drag_callback)
@@ -277,7 +277,7 @@ end
--- Strict drag click area. Useful for
-- restrict events outside stencil node
-- @tparam Drag self
-- @tparam Drag self @{Drag}
-- @tparam node node Gui node
function Drag.set_click_zone(self, node)
self.click_zone = self:get_node(node)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle hover node interaction
-- @module Hover
@@ -6,10 +6,10 @@
-- @alias druid.hover
--- On hover callback(self, state)
-- @tfield druid_event on_hover
-- @tfield DruidEvent on_hover @{DruidEvent}
--- On mouse hover callback(self, state)
-- @tfield druid_event on_mouse_hover
-- @tfield DruidEvent on_mouse_hover @{DruidEvent}
---
@@ -22,7 +22,7 @@ local Hover = component.create("hover")
--- Component init function
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @tparam node node Gui node
-- @tparam function on_hover_callback Hover callback
function Hover.init(self, node, on_hover_callback)
@@ -90,7 +90,7 @@ end
--- Set hover state
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @tparam bool state The hover state
function Hover.set_hover(self, state)
if self._is_hovered ~= state then
@@ -100,7 +100,7 @@ function Hover.set_hover(self, state)
end
--- Set mouse hover state
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @tparam bool state The mouse hover state
function Hover.set_mouse_hover(self, state)
if self._is_mouse_hovered ~= state then
@@ -112,7 +112,7 @@ end
--- Strict hover click area. Useful for
-- no click events outside stencil node
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @tparam node zone Gui node
function Hover.set_click_zone(self, zone)
self.click_zone = self:get_node(zone)
@@ -122,7 +122,7 @@ end
--- Set enable state of hover component.
-- If hover is not enabled, it will not generate
-- any hover events
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @tparam bool state The hover enabled state
function Hover.set_enabled(self, state)
self._is_enabled = state
@@ -139,7 +139,7 @@ end
--- Return current hover enabled state
-- @tparam Hover self
-- @tparam Hover self @{Hover}
-- @treturn bool The hover enabled state
function Hover.is_enabled(self)
return self._is_enabled

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle scroll content.
-- Scroll consist from two nodes: scroll parent and scroll input
@@ -13,13 +13,13 @@
--- On scroll move callback(self, position)
-- @tfield druid_event on_scroll
-- @tfield DruidEvent on_scroll @{DruidEvent}
--- On scroll_to function callback(self, target, is_instant)
-- @tfield druid_event on_scroll_to
-- @tfield DruidEvent on_scroll_to @{DruidEvent}
--- On scroll_to_index function callback(self, index, point)
-- @tfield druid_event on_point_scroll
-- @tfield DruidEvent on_point_scroll @{DruidEvent}
--- Scroll view node
-- @tfield node view_node
@@ -46,7 +46,7 @@
-- @tfield vector3 available_size
--- Drag Druid component
-- @tfield Drag drag
-- @tfield Drag drag @{Drag}
--- Current index of points of interests
-- @tfield[opt] number selected
@@ -133,7 +133,7 @@ end
--- Scroll constructor
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam node view_node GUI view scroll node
-- @tparam node content_node GUI content scroll node
function Scroll.init(self, view_node, content_node)
@@ -211,7 +211,7 @@ end
--- Start scroll to target point.
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam vector3 point Target point
-- @tparam[opt] bool is_instant Instant scroll flag
-- @usage scroll:scroll_to(vmath.vector3(0, 50, 0))
@@ -245,7 +245,7 @@ end
--- Scroll to item in scroll by point index.
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam number index Point index
-- @tparam[opt] bool skip_cb If true, skip the point callback
function Scroll.scroll_to_index(self, index, skip_cb)
@@ -268,7 +268,7 @@ end
--- Start scroll to target scroll percent
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam vector3 percent target percent
-- @tparam[opt] bool is_instant instant scroll flag
-- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0))
@@ -277,7 +277,7 @@ function Scroll.scroll_to_percent(self, percent, is_instant)
local pos = vmath.vector3(
-helper.lerp(border.x, border.z, 1 - percent.x),
helper.lerp(border.y, border.w, 1 - percent.y),
-helper.lerp(border.y, border.w, 1 - percent.y),
0
)
@@ -287,7 +287,7 @@ end
--- Return current scroll progress status.
-- Values will be in [0..1] interval
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @treturn vector3 New vector with scroll progress values
function Scroll.get_percent(self)
local x_perc = 1 - inverse_lerp(self.available_pos.x, self.available_pos.z, self.position.x)
@@ -299,7 +299,7 @@ end
--- Set scroll content size.
-- It will change content gui node size
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam vector3 size The new size for content node
-- @tparam vector3 offset Offset value to set, where content is starts
-- @treturn druid.scroll Current scroll instance
@@ -317,7 +317,7 @@ end
--- Enable or disable scroll inert.
-- If disabled, scroll through points (if exist)
-- If no points, just simple drag without inertion
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam bool state Inert scroll state
-- @treturn druid.scroll Current scroll instance
function Scroll.set_inert(self, state)
@@ -328,7 +328,7 @@ end
--- Return if scroll have inertion.
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @treturn bool If scroll have inertion
function Scroll.is_inert(self)
return self._is_inert
@@ -337,7 +337,7 @@ end
--- Set extra size for scroll stretching.
-- Set 0 to disable stretching effect
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam[opt=0] number stretch_size Size in pixels of additional scroll area
-- @treturn druid.scroll Current scroll instance
function Scroll.set_extra_stretch_size(self, stretch_size)
@@ -349,7 +349,7 @@ end
--- Return vector of scroll size with width and height.
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @treturn vector3 Available scroll size
function Scroll.get_scroll_size(self)
return self.available_size
@@ -358,7 +358,7 @@ end
--- Set points of interest.
-- Scroll will always centered on closer points
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam table points Array of vector3 points
-- @treturn druid.scroll Current scroll instance
function Scroll.set_points(self, points)
@@ -375,7 +375,7 @@ end
--- Lock or unlock horizontal scroll
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam bool state True, if horizontal scroll is enabled
-- @treturn druid.scroll Current scroll instance
function Scroll.set_horizontal_scroll(self, state)
@@ -386,7 +386,7 @@ end
--- Lock or unlock vertical scroll
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam bool state True, if vertical scroll is enabled
-- @treturn druid.scroll Current scroll instance
function Scroll.set_vertical_scroll(self, state)
@@ -398,7 +398,7 @@ end
--- Check node if it visible now on scroll.
-- Extra border is not affected. Return true for elements in extra scroll zone
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam node node The node to check
-- @treturn boolean True if node in visible scroll area
function Scroll.is_node_in_view(self, node)
@@ -421,7 +421,7 @@ end
--- Bind the grid component (Static or Dynamic) to recalculate
-- scroll size on grid changes
-- @tparam Scroll self
-- @tparam Scroll self @{Scroll}
-- @tparam StaticGrid|DynamicGrid grid Druid grid component
-- @treturn druid.scroll Current scroll instance
function Scroll.bind_grid(self, grid)
@@ -524,7 +524,7 @@ function Scroll._check_soft_zone(self)
end
--- Cancel animation on other animation or input touch
-- Cancel animation on other animation or input touch
function Scroll._cancel_animate(self)
self.inertion.x = 0
self.inertion.y = 0

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle placing components by row and columns.
-- Grid can anchor your elements, get content size and other
@@ -7,19 +7,19 @@
-- @alias druid.static_grid
--- On item add callback(self, node, index)
-- @tfield druid_event on_add_item
-- @tfield DruidEvent on_add_item @{DruidEvent}
--- On item remove callback(self, index)
-- @tfield druid_event on_remove_item
-- @tfield DruidEvent on_remove_item @{DruidEvent}
--- On item add, remove or change in_row callback(self, index|nil)
-- @tfield druid_event on_change_items
-- @tfield DruidEvent on_change_items @{DruidEvent}
--- On grid clear callback(self)
-- @tfield druid_event on_clear
-- @tfield DruidEvent on_clear @{DruidEvent}
--- On update item positions callback(self)
-- @tfield druid_event on_update_positions
-- @tfield DruidEvent on_update_positions @{DruidEvent}
--- Parent gui node
-- @tfield node parent
@@ -79,7 +79,7 @@ end
--- Component init function
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam node parent The gui node parent, where items will be placed
-- @tparam node element Element prefab. Need to get it size
-- @tparam[opt=1] number in_row How many nodes in row can be placed
@@ -117,7 +117,7 @@ end
local _temp_pos = vmath.vector3(0)
--- Return pos for grid node index
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam number index The grid element index
-- @treturn vector3 Node position
function StaticGrid.get_pos(self, index)
@@ -135,7 +135,7 @@ end
--- Return index for grid pos
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam vector3 pos The node position in the grid
-- @treturn number The node index
function StaticGrid.get_index(self, pos)
@@ -151,7 +151,7 @@ end
--- Return grid index by node
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam node node The gui node in the grid
-- @treturn number The node index
function StaticGrid.get_index_by_node(self, node)
@@ -171,7 +171,7 @@ end
--- Set grid anchor. Default anchor is equal to anchor of grid parent node
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam vector3 anchor Anchor
function StaticGrid.set_anchor(self, anchor)
self.anchor = anchor
@@ -180,11 +180,11 @@ end
--- Add new item to the grid
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam node item Gui node
-- @tparam[opt] number index The item position. By default add as last item
-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT
-- @tparam[opt=false] boolean is_instance If true, update node positions instantly
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
function StaticGrid.add(self, item, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
index = index or ((self.last_index or 0) + 1)
@@ -219,10 +219,10 @@ end
--- Remove the item from the grid. Note that gui node will be not deleted
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam number index The grid node index to remove
-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT
-- @tparam[opt=false] boolean is_instance If true, update node positions instantly
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
-- @treturn Node The deleted gui node from grid
function StaticGrid.remove(self, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
@@ -252,7 +252,7 @@ end
--- Return grid content size
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @treturn vector3 The grid content size
function StaticGrid.get_size(self)
return vmath.vector3(
@@ -262,7 +262,6 @@ function StaticGrid.get_size(self)
end
function StaticGrid.get_size_for(self, count)
if not count or count == 0 then
return vmath.vector3(0)
@@ -286,7 +285,7 @@ end
--- Return grid content borders
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @treturn vector3 The grid content borders
function StaticGrid.get_borders(self)
return self.border
@@ -294,7 +293,7 @@ end
--- Return array of all node positions
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @treturn vector3[] All grid node positions
function StaticGrid.get_all_pos(self)
local result = {}
@@ -308,7 +307,7 @@ end
--- Change set position function for grid nodes. It will call on
-- update poses on grid elements. Default: gui.set_position
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam function callback Function on node set position
-- @treturn druid.static_grid Current grid instance
function StaticGrid.set_position_function(self, callback)
@@ -320,7 +319,7 @@ end
--- Clear grid nodes array. GUI nodes will be not deleted!
-- If you want to delete GUI nodes, use static_grid.nodes array before grid:clear
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @treturn druid.static_grid Current grid instance
function StaticGrid.clear(self)
self.border.x = 0
@@ -338,7 +337,7 @@ end
--- Return StaticGrid offset, where StaticGrid content starts.
-- @tparam StaticGrid self The StaticGrid instance
-- @tparam StaticGrid self @{StaticGrid} The StaticGrid instance
-- @treturn vector3 The StaticGrid offset
function StaticGrid:get_offset()
local borders = self:get_borders()
@@ -354,10 +353,10 @@ end
--- Set new in_row elements for grid
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam number in_row The new in_row value
-- @treturn druid.static_grid Current grid instance
function StaticGrid:set_in_row(in_row)
function StaticGrid.set_in_row(self, in_row)
self.in_row = in_row
self._grid_horizonal_offset = self.node_size.x * (self.in_row - 1) * self.anchor.x
self:_update(true)
@@ -368,7 +367,7 @@ end
--- Update grid inner state
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function StaticGrid._update(self, is_instant)
@@ -379,7 +378,7 @@ end
--- Update first and last indexes of grid nodes
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @local
function StaticGrid._update_indexes(self)
self.first_index = nil
@@ -395,7 +394,7 @@ end
--- Update grid content borders, recalculate min and max values
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @local
function StaticGrid._update_borders(self)
if not self.first_index then
@@ -414,7 +413,7 @@ end
--- Update grid nodes position
-- @tparam StaticGrid self
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function StaticGrid._update_pos(self, is_instant)
@@ -438,7 +437,6 @@ end
--- Return elements offset for correct posing nodes. Correct posing at
-- parent pivot node (0:0) with adjusting of node sizes and anchoring
-- @function static_grid:_get_zero_offset
-- @treturn vector3 The offset vector
-- @local
function StaticGrid:_get_zero_offset()
@@ -456,7 +454,6 @@ end
--- Return offset x for last row in grid. Used to align this row accorting to grid's anchor
-- @function static:_grid:_get_zero_offset_x
-- @treturn number The offset x value
-- @local
function StaticGrid:_get_zero_offset_x(row_index)
@@ -477,5 +474,4 @@ function StaticGrid:_get_zero_offset_x(row_index)
end
return StaticGrid

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle swipe gestures on node.
-- Swipe will be triggered, if swipe was started and
@@ -14,7 +14,7 @@
-- @tparam[opt] node click_zone
--- Trigger on swipe event(self, swipe_side, dist, delta_time
-- @tfield druid_event on_swipe)
-- @tfield DruidEvent on_swipe) @{DruidEvent}
---
@@ -84,7 +84,7 @@ end
--- Component init function
-- @tparam Swipe self
-- @tparam Swipe self @{Swipe}
-- @tparam node node Gui node
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
function Swipe.init(self, node, on_swipe_callback)
@@ -149,7 +149,7 @@ end
--- Strict swipe click area. Useful for
-- restrict events outside stencil node
-- @tparam Swipe self
-- @tparam Swipe self @{Swipe}
-- @tparam node zone Gui node
function Swipe.set_click_zone(self, zone)
self.click_zone = self:get_node(zone)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle all GUI texts.
-- Druid text can adjust itself for text node size
@@ -8,13 +8,13 @@
-- @alias druid.text
--- On set text callback(self, text)
-- @tfield druid_event on_set_text
-- @tfield DruidEvent on_set_text @{DruidEvent}
--- On adjust text size callback(self, new_scale)
-- @tfield druid_event on_update_text_scale
-- @tfield DruidEvent on_update_text_scale @{DruidEvent}
--- On change pivot callback(self, pivot)
-- @tfield druid_event on_set_pivot
-- @tfield DruidEvent on_set_pivot @{DruidEvent}
--- Text node
-- @tfield node node
@@ -185,7 +185,7 @@ end
--- Component init function
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam node node Gui text node
-- @tparam[opt] string value Initial text. Default value is node text from GUI scene.
-- @tparam[opt=0] int adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
@@ -234,7 +234,7 @@ end
--- Calculate text width with font with respect to trailing space
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam[opt] string text
function Text.get_text_width(self, text)
text = text or self.last_value
@@ -255,7 +255,7 @@ end
--- Set text to text field
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam string set_to Text for node
-- @treturn Text Current text instance
function Text.set_to(self, set_to)
@@ -273,7 +273,7 @@ end
--- Set color
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam vector4 color Color for node
-- @treturn Text Current text instance
function Text.set_color(self, color)
@@ -285,7 +285,7 @@ end
--- Set alpha
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam number alpha Alpha for node
-- @treturn Text Current text instance
function Text.set_alpha(self, alpha)
@@ -297,7 +297,7 @@ end
--- Set scale
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam vector3 scale Scale for node
-- @treturn Text Current text instance
function Text.set_scale(self, scale)
@@ -309,7 +309,7 @@ end
--- Set text pivot. Text will re-anchor inside text area
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam gui.pivot pivot Gui pivot constant
-- @treturn Text Current text instance
function Text.set_pivot(self, pivot)
@@ -335,7 +335,7 @@ end
--- Return true, if text with line break
-- @tparam Text self
-- @tparam Text self @{Text}
-- @treturn bool Is text node with line break
function Text.is_multiline(self)
return gui.get_line_break(self.node)
@@ -343,7 +343,7 @@ end
--- Set text adjust, refresh the current text visuals, if needed
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam[opt] number adjust_type See const.TEXT_ADJUST. If pass nil - use current adjust type
-- @tparam[opt] number minimal_scale If pass nil - not use minimal scale
-- @treturn Text Current text instance
@@ -357,7 +357,7 @@ end
--- Set minimal scale for DOWNSCALE_LIMITED or SCALE_THEN_SCROLL adjust types
-- @tparam Text self
-- @tparam Text self @{Text}
-- @tparam number minimal_scale If pass nil - not use minimal scale
-- @treturn Text Current text instance
function Text.set_minimal_scale(self, minimal_scale)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Basic class for all Druid components.
-- To create you component, use `component.create`
@@ -12,6 +12,8 @@ local helper = require("druid.helper")
local BaseComponent = class("druid.component")
local IS_AUTO_TEMPLATE = not (sys.get_config("druid.no_auto_template") == "1")
--- Component Interests
BaseComponent.ON_INPUT = const.ON_INPUT
@@ -55,10 +57,10 @@ function BaseComponent.static.get_uid()
end
--- Set current component style table.
--- Set current component style table (protected).
-- Invoke `on_style_change` on component, if exist. BaseComponent should handle
-- their style changing and store all style params
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam table druid_style Druid style module
function BaseComponent.set_style(self, druid_style)
self._meta.style = druid_style or const.EMPTY_TABLE
@@ -70,24 +72,60 @@ function BaseComponent.set_style(self, druid_style)
end
--- Set current component template name
-- @tparam BaseComponent self
--- Set current component template name (protected)
-- It will check parent template name to build full template name
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string template BaseComponent template name
-- @treturn BaseComponent @{BaseComponent}
function BaseComponent.set_template(self, template)
template = template or const.EMPTY_STRING
local parent = self:get_parent_component()
if parent and IS_AUTO_TEMPLATE then
local parent_template = parent:get_template()
if #parent_template > 0 then
if #template > 0 then
template = "/" .. template
end
template = parent_template .. template
end
end
self._meta.template = template
return self
end
--- Set current component nodes
-- @tparam BaseComponent self
--- Get current component template name (protected)
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn string Component full template name
function BaseComponent.get_template(self)
return self._meta.template
end
--- Set current component nodes (protected)
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam table nodes BaseComponent nodes table
-- @treturn BaseComponent @{BaseComponent}
function BaseComponent.set_nodes(self, nodes)
self._meta.nodes = nodes
-- When we use gui.clone_tree in inner template (template inside other template)
-- this nodes have no id. We have table: hash(correct_id) : hash("")
-- It's wrong and we use this hack to fix this
if nodes then
for id, node in pairs(nodes) do
gui.set_id(node, id)
end
end
return self
end
--- Get current component context
-- @tparam BaseComponent self
--- Get current component context (protected)
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn table BaseComponent context
function BaseComponent.get_context(self)
return self._meta.context
@@ -95,47 +133,54 @@ end
--- Increase input priority in current input stack
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @local
function BaseComponent.increase_input_priority(self)
helper.deprecated("The component:increase_input_priority is deprecated. Please use component:set_input_priority(druid_const.PRIORITY_INPUT_MAX) instead")
end
--- Get node for component by name.
-- If component has nodes, node_or_name should be string
-- It auto pick node by template name or from nodes by clone_tree
-- if they was setup via component:set_nodes, component:set_template
-- @tparam BaseComponent self
-- if they was setup via component:set_nodes, component:set_template.
-- If node is not found, the exception will fired
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string|node node_or_name Node name or node itself
-- @treturn node Gui node
function BaseComponent.get_node(self, node_or_name)
local template_name = self:__get_template() or const.EMPTY_STRING
local template_name = self:get_template()
local nodes = self:__get_nodes()
if template_name ~= const.EMPTY_STRING then
if #template_name > 0 then
template_name = template_name .. "/"
end
local node
local node_type = type(node_or_name)
if nodes then
assert(node_type == const.STRING, "You should pass node name instead of node")
return nodes[template_name .. node_or_name]
node = nodes[template_name .. node_or_name]
else
if node_type == const.STRING then
return gui.get_node(template_name .. node_or_name)
node = gui.get_node(template_name .. node_or_name)
else
-- Assume it's already node from gui.get_node
return node_or_name
node = node_or_name
end
end
if not node then
assert(node, "No component with name: " .. template_name .. node_or_name)
end
return node
end
--- Return druid with context of calling component.
--- Return druid with context of calling component (protected).
-- Use it to create component inside of other components.
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn Druid Druid instance with component context
function BaseComponent.get_druid(self)
local context = { _context = self }
@@ -144,7 +189,7 @@ end
--- Return component name
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn string The component name
function BaseComponent.get_name(self)
return self._component.name
@@ -152,7 +197,7 @@ end
--- Return component input priority
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn number The component input priority
function BaseComponent.get_input_priority(self)
return self._component.input_priority
@@ -160,7 +205,7 @@ end
--- Set component input priority
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam number value The new input priority value
-- @treturn number The component input priority
function BaseComponent.set_input_priority(self, value)
@@ -181,7 +226,7 @@ end
--- Reset component input priority to default value
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn number The component input priority
function BaseComponent.reset_input_priority(self)
self:set_input_priority(self._component.default_input_priority)
@@ -189,8 +234,9 @@ function BaseComponent.reset_input_priority(self)
end
--- Return component uid. UID generated in component creation order
-- @tparam BaseComponent self
--- Return component uid (protected).
--- UID generated in component creation order
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn number The component uid
function BaseComponent.get_uid(self)
return self._component._uid
@@ -199,7 +245,7 @@ end
--- Set component input state. By default it enabled
-- You can disable any input of component by this function
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam bool state The component input state
-- @treturn BaseComponent BaseComponent itself
function BaseComponent.set_input_enabled(self, state)
@@ -213,9 +259,9 @@ function BaseComponent.set_input_enabled(self, state)
end
--- Return the parent for current component
-- @tparam BaseComponent self
-- @treturn druid.base_component|nil The druid component instance or nil
--- Return the parent for current component (protected)
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn BaseComponent|nil The druid component instance or nil
function BaseComponent.get_parent_component(self)
local context = self:get_context()
@@ -228,14 +274,15 @@ end
--- Setup component context and his style table
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam table druid_instance The parent druid instance
-- @tparam table context Druid context. Usually it is self of script
-- @tparam table style Druid style module
-- @treturn component BaseComponent itself
-- @local
function BaseComponent.setup_component(self, druid_instance, context, style)
self._meta = {
template = nil,
template = "",
context = nil,
nodes = nil,
style = nil,
@@ -246,6 +293,7 @@ function BaseComponent.setup_component(self, druid_instance, context, style)
self:__set_context(context)
self:set_style(style)
self:set_template("")
local parent = self:get_parent_component()
if parent then
@@ -258,7 +306,7 @@ end
--- Basic constructor of component. It will call automaticaly
-- by `BaseComponent.static.create`
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string name BaseComponent name
-- @tparam[opt=DEFAULT] number input_priority The input priority. The bigger number processed first
-- @local
@@ -274,7 +322,7 @@ end
--- Return true, if input priority was changed
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @local
function BaseComponent._is_input_priority_changed(self)
return self._component._is_input_priority_changed
@@ -282,7 +330,7 @@ end
--- Reset is_input_priority_changed field
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @local
function BaseComponent._reset_input_priority_changed(self)
self._component._is_input_priority_changed = false
@@ -295,7 +343,7 @@ end
--- Set current component context
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam table context Druid context. Usually it is self of script
-- @local
function BaseComponent.__set_context(self, context)
@@ -304,7 +352,7 @@ end
--- Get current component interests
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn table List of component interests
-- @local
function BaseComponent.__get_interests(self)
@@ -320,26 +368,22 @@ function BaseComponent.__get_interests(self)
end
--- Get current component template name
-- @tparam BaseComponent self
-- @treturn string BaseComponent template name
-- @local
function BaseComponent.__get_template(self)
return self._meta.template
end
--- Get current component nodes
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn table BaseComponent nodes table
-- @local
function BaseComponent.__get_nodes(self)
return self._meta.nodes
local nodes = self._meta.nodes
local parent = self:get_parent_component()
if parent then
nodes = nodes or parent:__get_nodes()
end
return nodes
end
--- Add child to component children list
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam component children The druid component instance
-- @local
function BaseComponent.__add_children(self, children)
@@ -348,7 +392,7 @@ end
--- Remove child from component children list
-- @tparam BaseComponent self
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam component children The druid component instance
-- @local
function BaseComponent.__remove_children(self, children)
@@ -360,8 +404,8 @@ function BaseComponent.__remove_children(self, children)
end
--- Return all children components, recursive
-- @tparam BaseComponent self
--- Return all children components, recursive (protected)
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn table Array of childrens if the Druid component instance
function BaseComponent.get_childrens(self)
local childrens = {}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid constants
-- @local

View File

@@ -0,0 +1,182 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
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: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.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/slider_move"
id: "pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,123 @@
-- Copyright (c) 2022 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid pin knob custom component.
-- It's simple rotating input element
-- @module PinKnob
-- @within BaseComponent
-- @alias druid.pin_knob
--- The component druid instance
-- @tfield DruidInstance druid @{DruidInstance}
--- Is currently under user control
-- @tfield bool is_drag
--- The pin node
-- @tfield node node
---
local const = require("druid.const")
local component = require("druid.component")
local PinKnob = component.create("druid.pin_knob", { const.ON_INPUT })
local SCHEME = {
ROOT = "root",
PIN = "pin",
}
local function update_visual(self)
local rotation = vmath.vector3(0, 0, self.angle)
gui.set_rotation(self.node, rotation)
end
local function set_angle(self, value)
local prev_value = self.angle
self.angle = value
self.angle = math.min(self.angle, self.angle_max)
self.angle = math.max(self.angle, self.angle_min)
update_visual(self)
if prev_value ~= self.angle and self.callback then
local output_value = self.angle
if output_value ~= 0 then
output_value = -output_value
end
self.callback(self:get_context(), output_value)
end
end
--- Component init function
-- @tparam PinKnob self @{PinKnob}
-- @tparam function callback Callback(self, value) on value changed
-- @tparam string template The template string name
-- @tparam table nodes Nodes table from gui.clone_tree
function PinKnob.init(self, callback, template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.druid = self:get_druid()
self.node = self:get_node(SCHEME.PIN)
self.is_drag = false
self.callback = callback
self:set_angle(0, -100, 100)
self._friction = 0.75
end
--- Set current and min/max angles for component
-- @tparam PinKnob self @{PinKnob}
-- @tparam number cur_value The new value for pin knob
-- @tparam number min The minimum value for pin knob
-- @tparam number max The maximum value for pin knob
-- @treturn PinKnob @{PinKnob}
function PinKnob.set_angle(self, cur_value, min, max)
self.angle_min = min or self.angle_min
self.angle_max = max or self.angle_max
set_angle(self, cur_value)
return self
end
--- Set current and min/max angles for component
-- @tparam PinKnob self @{PinKnob}
-- @tparam[opt=1] number value The spin speed multiplier
-- @treturn PinKnob @{PinKnob}
function PinKnob.set_friction(self, value)
self._friction = value or 1
return self
end
function PinKnob.on_input(self, action_id, action)
if action_id ~= const.ACTION_TOUCH then
return false
end
if gui.pick_node(self.node, action.x, action.y) then
if action.pressed then
self.pos = gui.get_position(self.node)
self.is_drag = true
end
end
if self.is_drag and not action.pressed then
set_angle(self, self.angle - action.dx * self._friction - action.dy * self._friction)
end
if action.released then
self.is_drag = false
end
return self.is_drag
end
return PinKnob

View File

@@ -0,0 +1,371 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 190.0
y: 45.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/progress_back"
id: "button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.5
y: 0.5
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.9490196
y: 0.9490196
z: 0.9490196
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Placeholder"
font: "game"
id: "placeholder_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.4
y: 0.4
z: 0.4
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.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: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 60.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: "User input"
font: "game"
id: "input_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 67.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "cursor_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: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 2.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: 20.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.2
y: 0.2
z: 0.2
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "|"
font: "game"
id: "cursor_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "cursor_node"
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
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,95 @@
-- Copyright (c) 2022 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid Rich Input custom component.
-- It's wrapper on Input component with cursor and placeholder text
-- @module RichInput
-- @within Input
-- @alias druid.rich_input
--- The component druid instance
-- @tfield DruidInstance druid @{DruidInstance}
--- On input field text change callback(self, input_text)
-- @tfield Input input @{Input}
--- On input field text change to empty string callback(self, input_text)
-- @tfield node cursor
--- On input field text change to max length string callback(self, input_text)
-- @tfield druid.text placeholder @{Text}
---
local component = require("druid.component")
local RichInput = component.create("druid.rich_input")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
PLACEHOLDER = "placeholder_text",
INPUT = "input_text",
CURSOR = "cursor_node",
}
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 text_width = self.input.total_width
animate_cursor(self)
gui.set_position(self.cursor, vmath.vector3(text_width/2, 0, 0))
gui.set_scale(self.cursor, self.input.text.scale)
end
local function on_select(self)
gui.set_enabled(self.cursor, true)
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.placeholder.node, true and #self.input:get_text() == 0)
end
--- Component init function
-- @tparam RichInput self @{RichInput}
-- @tparam string template The template string name
-- @tparam table nodes Nodes table from gui.clone_tree
function RichInput.init(self, template, nodes)
self:set_template(template)
self:set_nodes(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.placeholder = self.druid:new_text(self:get_node(SCHEME.PLACEHOLDER))
self.input.on_input_text:subscribe(update_text)
self.input.on_input_select:subscribe(on_select)
self.input.on_input_unselect:subscribe(on_unselect)
on_unselect(self)
update_text(self, "")
end
--- Set placeholder text
-- @tparam RichInput self @{RichInput}
-- @tparam string placeholder_text The placeholder text
function RichInput.set_placeholder(self, placeholder_text)
self.placeholder:set_to(placeholder_text)
return self
end
return RichInput

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid UI Library.
-- Powerful Defold component based UI library. Use standart

View File

@@ -1,8 +1,8 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Lua event small library
--- Druid lua event library
-- @module DruidEvent
-- @alias druid_event
-- @alias druid.event
local class = require("druid.system.middleclass")
@@ -10,7 +10,7 @@ local DruidEvent = class("druid.event")
--- Event constructur
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function initial_callback Subscribe the callback on new event, if callback exist
function DruidEvent.initialize(self, initial_callback)
self._callbacks = {}
@@ -22,7 +22,7 @@ end
--- Subscribe callback on event
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function callback Callback itself
-- @tparam table context Additional context as first param to callback call
function DruidEvent.subscribe(self, callback, context)
@@ -39,7 +39,7 @@ end
--- Unsubscribe callback on event
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function callback Callback itself
-- @tparam table context Additional context as first param to callback call
function DruidEvent.unsubscribe(self, callback, context)
@@ -53,7 +53,7 @@ end
--- Return true, if event have at lease one handler
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
-- @treturn bool True if event have handlers
function DruidEvent.is_exist(self)
return #self._callbacks > 0
@@ -61,14 +61,14 @@ end
--- Clear the all event handlers
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
function DruidEvent.clear(self)
self._callbacks = {}
end
--- Trigger the event and call all subscribed callbacks
-- @tparam DruidEvent self
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam any ... All event params
function DruidEvent.trigger(self, ...)
for index, callback_info in ipairs(self._callbacks) do

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid checkbox component
-- @module Checkbox
@@ -6,7 +6,7 @@
-- @alias druid.checkbox
--- On change state callback(self, state)
-- @tfield druid_event on_change_state
-- @tfield DruidEvent on_change_state @{DruidEvent}
--- Visual node
-- @tfield node node
@@ -15,7 +15,7 @@
-- @tfield[opt=node] node click_node
--- Button component from click_node
-- @tfield Button button
-- @tfield Button button @{Button}
---
@@ -45,7 +45,7 @@ end
--- Component init function
-- @tparam Checkbox self
-- @tparam Checkbox self @{Checkbox}
-- @tparam node node Gui node
-- @tparam function callback Checkbox callback
-- @tparam[opt=node] node click_node Trigger node, by default equals to node
@@ -68,7 +68,7 @@ end
--- Set checkbox state
-- @tparam Checkbox self
-- @tparam Checkbox self @{Checkbox}
-- @tparam bool state Checkbox state
-- @tparam bool is_silent Don't trigger on_change_state if true
-- @tparam bool is_instant If instant checkbox change
@@ -85,7 +85,7 @@ end
--- Return checkbox state
-- @tparam Checkbox self
-- @tparam Checkbox self @{Checkbox}
-- @treturn bool Checkbox state
function Checkbox.get_state(self)
return self.state

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Checkbox group module
-- @module CheckboxGroup
@@ -6,10 +6,10 @@
-- @alias druid.checkbox_group
--- On any checkbox click callback(self, index)
-- @tfield druid_event on_checkbox_click
-- @tfield DruidEvent on_checkbox_click @{DruidEvent}
--- Array of checkbox components
-- @tfield table checkboxes
-- @tfield table checkboxes @{Checkbox}
---
@@ -20,7 +20,7 @@ local CheckboxGroup = component.create("checkbox_group")
--- Component init function
-- @tparam CheckboxGroup self
-- @tparam CheckboxGroup self @{CheckboxGroup}
-- @tparam node[] nodes Array of gui node
-- @tparam function callback Checkbox callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
@@ -42,7 +42,7 @@ end
--- Set checkbox group state
-- @tparam CheckboxGroup self
-- @tparam CheckboxGroup self @{CheckboxGroup}
-- @tparam bool[] indexes Array of checkbox state
-- @tparam boolean is_instant If instant state change
function CheckboxGroup.set_state(self, indexes, is_instant)
@@ -55,7 +55,7 @@ end
--- Return checkbox group state
-- @tparam CheckboxGroup self
-- @tparam CheckboxGroup self @{CheckboxGroup}
-- @treturn bool[] Array if checkboxes state
function CheckboxGroup.get_state(self)
local result = {}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to manage data for huge dataset in scroll.
-- It requires Druid Scroll and Druid Grid (Static or Dynamic) components
@@ -8,10 +8,10 @@
--- The Druid scroll component
-- @tfield druid.scroll scroll
-- @tfield Scroll scroll @{Scroll}
--- The Druid Grid component
-- @tfield druid.static_grid grid
-- @tfield StaticGrid|DynamicGrid grid @{StaticGrid}, @{DynamicGrid}
--- The current visual top data index
-- @tfield number top_index
@@ -23,7 +23,7 @@
-- @tfield number scroll_progress
--- Event triggered when scroll progress is changed; event(self, progress_value)
-- @tfield druid_event on_scroll_progress_change
-- @tfield DruidEvent on_scroll_progress_change @{DruidEvent}
---
@@ -36,9 +36,9 @@ local DataList = component.create("data_list")
--- Data list constructor
-- @tparam DataList self
-- @tparam druid.scroll scroll The Scroll instance for Data List component
-- @tparam druid.grid grid The Grid instance for Data List component
-- @tparam DataList self @{DataList}
-- @tparam Scroll scroll The @{Scroll} instance for Data List component
-- @tparam StaticGrid|DynamicGrid grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
function DataList.init(self, scroll, grid, create_function)
self.druid = self:get_druid()
@@ -65,14 +65,14 @@ end
--- Druid System on_remove function
-- @tparam DataList self
-- @tparam DataList self @{DataList}
function DataList.on_remove(self)
self.scroll.on_scroll:unsubscribe(self._check_elements, self)
end
--- Set new data set for DataList component
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam table data The new data array
-- @treturn druid.data_list Current DataList instance
function DataList.set_data(self, data)
@@ -85,7 +85,7 @@ end
--- Add element to DataList. Currenly untested
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam table data
-- @tparam number index
-- @tparam number shift_policy The constant from const.SHIFT.*
@@ -113,7 +113,7 @@ end
--- Remove element from DataList. Currenly untested
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @tparam number shift_policy The constant from const.SHIFT.*
-- @local
@@ -124,7 +124,7 @@ end
--- Remove element from DataList by data value. Currenly untested
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam tabe data
-- @tparam number shift_policy The constant from const.SHIFT.*
-- @local
@@ -138,7 +138,7 @@ end
--- Clear the DataList and refresh visuals
-- @tparam DataList self
-- @tparam DataList self @{DataList}
function DataList.clear(self)
self._data = {}
self:_refresh()
@@ -146,28 +146,28 @@ end
--- Return first index from data. It not always equals to 1
-- @tparam DataList self
-- @tparam DataList self @{DataList}
function DataList.get_first_index(self)
return self._data_first_index
end
--- Return last index from data
-- @tparam DataList self
-- @tparam DataList self @{DataList}
function DataList.get_last_index(self)
return self._data_last_index
end
--- Return amount of data
-- @tparam DataList self
-- @tparam DataList self @{DataList}
function DataList.get_length(self)
return self._data_length
end
--- Return index for data value
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam table data
function DataList.get_index(self, data)
for index, value in pairs(self._data) do
@@ -181,7 +181,7 @@ end
--- Instant scroll to element with passed index
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam number index
function DataList.scroll_to_index(self, index)
local target = helper.clamp(index, self:get_first_index(), self:get_last_index())
@@ -195,7 +195,7 @@ end
--- Add element at passed index
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @local
function DataList._add_at(self, index)
@@ -213,7 +213,7 @@ end
--- Remove element from passed index
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @local
function DataList._remove_at(self, index)
@@ -230,7 +230,7 @@ end
--- Fully refresh all DataList elements
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @local
function DataList._refresh(self)
for index, _ in pairs(self._data_visual) do
@@ -241,7 +241,7 @@ end
--- Check elements which should be created
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @local
function DataList._check_elements(self)
for index, data in pairs(self._data_visual) do
@@ -279,7 +279,7 @@ end
--- Check elements which should be created.
-- Start from index with step until element is outside of scroll view
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @tparam number step
-- @local
@@ -312,9 +312,8 @@ function DataList._check_elements_from(self, index, step)
end
--- Update actual data params
-- @tparam DataList self
-- @tparam DataList self @{DataList}
-- @local
function DataList._update_data_info(self)
self._data_first_index = false

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle placing components in row
-- @module DynamicGrid
@@ -6,19 +6,19 @@
-- @alias druid.dynamic_grid
--- On item add callback(self, node, index)
-- @tfield druid_event on_add_item
-- @tfield DruidEvent on_add_item @{DruidEvent}
--- On item remove callback(self, index)
-- @tfield druid_event on_remove_item
-- @tfield DruidEvent on_remove_item @{DruidEvent}
--- On item add or remove callback(self, index)
-- @tfield druid_event on_change_items
-- @tfield DruidEvent on_change_items @{DruidEvent}
--- On grid clear callback(self)
-- @tfield druid_event on_clear
-- @tfield DruidEvent on_clear @{DruidEvent}
--- On update item positions callback(self)
-- @tfield druid_event on_update_positions
-- @tfield DruidEvent on_update_positions @{DruidEvent}
--- Parent gui node
-- @tfield node parent
@@ -64,7 +64,7 @@ local AVAILABLE_PIVOTS = {
--- Component init function
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node parent The gui node parent, where items will be placed
function DynamicGrid.init(self, parent)
self.parent = self:get_node(parent)
@@ -95,7 +95,7 @@ end
--- Return pos for grid node index
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam number index The grid element index
-- @tparam node node The node to be placed
-- @tparam[opt] number origin_index Index of nearby node
@@ -136,11 +136,11 @@ end
--- Add new node to the grid
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node node Gui node
-- @tparam[opt] number index The node position. By default add as last node
-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT
-- @tparam[opt=false] boolean is_instance If true, update node positions instantly
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
function DynamicGrid.add(self, node, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
local delta = shift_policy -- -1 or 1 or 0
@@ -179,11 +179,11 @@ end
--- Remove the item from the grid. Note that gui node will be not deleted
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam number index The grid node index to remove
-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT
-- @tparam[opt=false] boolean is_instance If true, update node positions instantly
-- @treturn Node The deleted gui node from grid
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
-- @treturn node The deleted gui node from grid
function DynamicGrid.remove(self, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
local delta = shift_policy -- -1 or 1 or 0
@@ -216,7 +216,7 @@ end
--- Return grid content size
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam vector3 border
-- @treturn vector3 The grid content size
function DynamicGrid.get_size(self, border)
@@ -229,7 +229,7 @@ end
--- Return DynamicGrid offset, where DynamicGrid content starts.
-- @tparam DynamicGrid self The DynamicGrid instance
-- @tparam DynamicGrid self @{DynamicGrid} The DynamicGrid instance
-- @treturn vector3 The DynamicGrid offset
function DynamicGrid.get_offset(self)
local size = self:get_size()
@@ -244,7 +244,7 @@ end
--- Return grid content borders
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn vector3 The grid content borders
function DynamicGrid.get_borders(self)
return self.border
@@ -252,7 +252,7 @@ end
--- Return grid index by node
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node node The gui node in the grid
-- @treturn number The node index
function DynamicGrid.get_index_by_node(self, node)
@@ -267,7 +267,7 @@ end
--- Return array of all node positions
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn vector3[] All grid node positions
function DynamicGrid.get_all_pos(self)
local result = {}
@@ -281,7 +281,7 @@ end
--- Change set position function for grid nodes. It will call on
-- update poses on grid elements. Default: gui.set_position
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam function callback Function on node set position
-- @treturn druid.dynamic_grid Current grid instance
function DynamicGrid.set_position_function(self, callback)
@@ -292,7 +292,7 @@ end
--- Clear grid nodes array. GUI nodes will be not deleted!
-- If you want to delete GUI nodes, use dynamic_grid.nodes array before grid:clear
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn druid.dynamic_grid Current grid instance
function DynamicGrid.clear(self)
self.nodes = {}
@@ -319,7 +319,7 @@ end
--- Update grid inner state
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function DynamicGrid._update(self, is_instant)
@@ -330,7 +330,7 @@ end
--- Update first and last indexes of grid nodes
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @local
function DynamicGrid._update_indexes(self)
self.first_index = nil
@@ -346,7 +346,7 @@ end
--- Update grid content borders, recalculate min and max values
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @local
function DynamicGrid._update_borders(self)
if not self.first_index then
@@ -375,7 +375,7 @@ end
--- Update grid nodes position
-- @tparam DynamicGrid self
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function DynamicGrid._update_pos(self, is_instant)
@@ -410,7 +410,6 @@ function DynamicGrid._get_next_node_pos(self, origin_node_index, new_node, place
end
function DynamicGrid._get_node_size(self, node)
return vmath.mul_per_elem(gui.get_size(node), gui.get_scale(node))
end

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid input text component.
-- Carry on user text input
@@ -8,28 +8,28 @@
-- @alias druid.input
--- On input field select callback(self, button_node)
-- @tfield druid_event on_input_select
-- @tfield DruidEvent on_input_select @{DruidEvent}
--- On input field unselect callback(self, input_text)
-- @tfield druid_event on_input_unselect
-- @tfield DruidEvent on_input_unselect @{DruidEvent}
--- On input field text change callback(self, input_text)
-- @tfield druid_event on_input_text
-- @tfield DruidEvent on_input_text @{DruidEvent}
--- On input field text change to empty string callback(self, input_text)
-- @tfield druid_event on_input_empty
-- @tfield DruidEvent on_input_empty @{DruidEvent}
--- On input field text change to max length string callback(self, input_text)
-- @tfield druid_event on_input_full
-- @tfield DruidEvent on_input_full @{DruidEvent}
--- On trying user input with not allowed character callback(self, params, button_instance)
-- @tfield druid_event on_input_wrong
-- @tfield DruidEvent on_input_wrong @{DruidEvent}
--- Text component
-- @tfield druid.text text
-- @tfield Text text @{Text}
--- Button component
-- @tfield druid.button button
-- @tfield Button button @{Button}
--- Is current input selected now
-- @tfield bool is_selected
@@ -110,8 +110,10 @@ function Input.on_style_change(self, style)
end
--- Component init function
-- @tparam Input self @{Input}
-- @tparam node click_node Button node to enabled input component
-- @tparam node|druid.text text_node Text node what will be changed on user input. You can pass text component instead of text node name
-- @tparam node|Text text_node Text node what will be changed on user input. You can pass text component instead of text node name @{Text}
-- @tparam[opt] number keyboard_type Gui keyboard type for input field
function Input.init(self, click_node, text_node, keyboard_type)
self.druid = self:get_druid(self)
@@ -227,7 +229,7 @@ end
--- Set text for input field
-- @tparam Input self
-- @tparam Input self @{Input}
-- @tparam string input_text The string to apply for input field
function Input.set_text(self, input_text)
-- Case when update with marked text
@@ -274,7 +276,7 @@ end
--- Select input field. It will show the keyboard and trigger on_select events
-- @tparam Input self
-- @tparam Input self @{Input}
function Input.select(self)
gui.reset_keyboard()
self.marked_value = ""
@@ -297,7 +299,7 @@ end
--- Remove selection from input. It will hide the keyboard and trigger on_unselect events
-- @tparam Input self
-- @tparam Input self @{Input}
function Input.unselect(self)
gui.reset_keyboard()
self.marked_value = ""
@@ -315,7 +317,7 @@ end
--- Return current input field text
-- @tparam Input self
-- @tparam Input self @{Input}
-- @treturn string The current input field text
function Input.get_text(self)
return self.value .. self.marked_value
@@ -324,7 +326,7 @@ end
--- Set maximum length for input field.
-- Pass nil to make input field unliminted (by default)
-- @tparam Input self
-- @tparam Input self @{Input}
-- @tparam number max_length Maximum length for input text field
-- @treturn druid.input Current input instance
function Input.set_max_length(self, max_length)
@@ -336,7 +338,7 @@ end
--- Set allowed charaters for input field.
-- See: https://defold.com/ref/stable/string/
-- ex: [%a%d] for alpha and numeric
-- @tparam Input self
-- @tparam Input self @{Input}
-- @tparam string characters Regulax exp. for validate user input
-- @treturn druid.input Current input instance
function Input.set_allowed_characters(self, characters)
@@ -346,7 +348,7 @@ end
--- Reset current input selection and return previous value
-- @tparam Input self
-- @tparam Input self @{Input}
function Input.reset_changes(self)
self:set_text(self.previous_value)
self:unselect()

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle all GUI texts
-- Good working with localization system
@@ -7,10 +7,10 @@
-- @alias druid.lang_text
--- On change text callback
-- @tfield druid_event on_change
-- @tfield DruidEvent on_change @{DruidEvent}
--- The text component
-- @tfield Text text
-- @tfield Text text @{Text}
---
@@ -22,7 +22,7 @@ local LangText = component.create("lang_text")
--- Component init function
-- @tparam LangText self
-- @tparam LangText self @{LangText}
-- @tparam node node The text node
-- @tparam string locale_id Default locale id or text from node as default
-- @tparam bool no_adjust If true, will not correct text size
@@ -48,7 +48,7 @@ end
--- Setup raw text to lang_text component
-- @tparam LangText self
-- @tparam LangText self @{LangText}
-- @tparam string text Text for text node
-- @treturn LangText Current instance
function LangText.set_to(self, text)
@@ -61,9 +61,15 @@ end
--- Translate the text by locale_id
-- @tparam LangText self
-- @tparam LangText self @{LangText}
-- @tparam string locale_id Locale id
-- @tparam string ... Locale arguments to pass in text function
-- @tparam[opt] string a Optional param to string.format
-- @tparam[opt] string b Optional param to string.format
-- @tparam[opt] string c Optional param to string.format
-- @tparam[opt] string d Optional param to string.format
-- @tparam[opt] string e Optional param to string.format
-- @tparam[opt] string f Optional param to string.format
-- @tparam[opt] string g Optional param to string.format
-- @treturn LangText Current instance
function LangText.translate(self, locale_id, a, b, c, d, e, f, g)
self.last_locale_args = { a, b, c, d, e, f, g }
@@ -75,8 +81,14 @@ end
--- Format string with new text params on localized text
-- @tparam LangText self
-- @tparam string ... Locale arguments to pass in text function
-- @tparam LangText self @{LangText}
-- @tparam[opt] string a Optional param to string.format
-- @tparam[opt] string b Optional param to string.format
-- @tparam[opt] string c Optional param to string.format
-- @tparam[opt] string d Optional param to string.format
-- @tparam[opt] string e Optional param to string.format
-- @tparam[opt] string f Optional param to string.format
-- @tparam[opt] string g Optional param to string.format
-- @treturn LangText Current instance
function LangText.format(self, a, b, c, d, e, f, g)
self.last_locale_args = { a, b, c, d, e, f, g }

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Basic progress bar component.
-- For correct progress bar init it should be in max size from gui
@@ -7,7 +7,7 @@
-- @alias druid.progress
--- On progress bar change callback(self, new_value)
-- @tfield druid_event on_change
-- @tfield DruidEvent on_change @{DruidEvent}
--- Progress bar fill node
-- @tfield node node
@@ -93,7 +93,7 @@ end
--- Component init function
-- @tparam Progress self
-- @tparam Progress self @{Progress}
-- @tparam string|node node Progress bar fill node or node name
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
-- @tparam[opt=1] number init_value Initial value of progress bar
@@ -146,21 +146,21 @@ end
--- Fill a progress bar and stop progress animation
-- @tparam Progress self
-- @tparam Progress self @{Progress}
function Progress.fill(self)
set_bar_to(self, 1, true)
end
--- Empty a progress bar
-- @tparam Progress self
-- @tparam Progress self @{Progress}
function Progress.empty(self)
set_bar_to(self, 0, true)
end
--- Instant fill progress bar to value
-- @tparam Progress self
-- @tparam Progress self @{Progress}
-- @tparam number to Progress bar value, from 0 to 1
function Progress.set_to(self, to)
set_bar_to(self, to)
@@ -168,14 +168,14 @@ end
--- Return current progress bar value
-- @tparam Progress self
-- @tparam Progress self @{Progress}
function Progress.get(self)
return self.last_value
end
--- Set points on progress bar to fire the callback
-- @tparam Progress self
-- @tparam Progress self @{Progress}
-- @tparam number[] steps Array of progress bar values
-- @tparam function callback Callback on intersect step value
-- @usage progress:set_steps({0, 0.3, 0.6, 1}, function(self, step) end)
@@ -186,7 +186,7 @@ end
--- Start animation of a progress bar
-- @tparam Progress self
-- @tparam Progress self @{Progress}
-- @tparam number to value between 0..1
-- @tparam[opt] function callback Callback on animation ends
function Progress.to(self, to, callback)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Radio group module
-- @module RadioGroup
@@ -6,7 +6,7 @@
-- @alias druid.radio_group
--- On any checkbox click
-- @tfield druid_event on_radio_click
-- @tfield DruidEvent on_radio_click @{DruidEvent}
--- Array of checkbox components
-- @tfield Checkbox[] checkboxes
@@ -29,7 +29,7 @@ end
--- Component init function
-- @tparam RadioGroup self
-- @tparam RadioGroup self @{RadioGroup}
-- @tparam node[] nodes Array of gui node
-- @tparam function callback Radio callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
@@ -51,7 +51,7 @@ end
--- Set radio group state
-- @tparam RadioGroup self
-- @tparam RadioGroup self @{RadioGroup}
-- @tparam number index Index in radio group
-- @tparam boolean is_instant If is instant state change
function RadioGroup.set_state(self, index, is_instant)
@@ -60,7 +60,7 @@ end
--- Return radio group state
-- @tparam RadioGroup self
-- @tparam RadioGroup self @{RadioGroup}
-- @treturn number Index in radio group
function RadioGroup.get_state(self)
local result = -1

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid slider component
-- @module Slider
@@ -6,7 +6,7 @@
-- @alias druid.slider
--- On change value callback(self, value)
-- @tfield druid_event on_change_value
-- @tfield DruidEvent on_change_value @{DruidEvent}
--- Slider pin node
-- @tfield node node
@@ -55,7 +55,7 @@ end
--- Component init function
-- @tparam Slider self
-- @tparam Slider self @{Slider}
-- @tparam node node Gui pin node
-- @tparam vector3 end_pos The end position of slider
-- @tparam[opt] function callback On slider change callback
@@ -94,6 +94,17 @@ function Slider.on_input(self, action_id, action)
end
end
if not self.is_drag and self._input_node and gui.pick_node(self._input_node, action.x, action.y) then
if action.pressed and gui.screen_to_local then
self.pos = gui.screen_to_local(self.node, vmath.vector3(action.screen_x, action.screen_y, 0))
self.pos.x = helper.clamp(self.pos.x, self.start_pos.x, self.end_pos.x)
self.pos.y = helper.clamp(self.pos.y, self.start_pos.y, self.end_pos.y)
gui.set_position(self.node, self.pos)
self.is_drag = true
end
end
if self.is_drag and not action.pressed then
-- move
self.pos.x = self.pos.x + action.dx
@@ -148,7 +159,7 @@ end
--- Set value for slider
-- @tparam Slider self
-- @tparam Slider self @{Slider}
-- @tparam number value Value from 0 to 1
-- @tparam[opt] bool is_silent Don't trigger event if true
function Slider.set(self, value, is_silent)
@@ -163,11 +174,26 @@ end
--- Set slider steps. Pin node will
-- apply closest step position
-- @tparam Slider self
-- @tparam Slider self @{Slider}
-- @tparam number[] steps Array of steps
-- @usage slider:set_steps({0, 0.2, 0.6, 1})
-- @treturn Slider @{Slider}
function Slider.set_steps(self, steps)
self.steps = steps
return self
end
--- Set input zone for slider.
-- User can touch any place of node, pin instantly will
-- move at this position and node drag will start.
-- This function require the Defold version 1.3.0+
-- @tparam Slider self @{Slider}
-- @tparam input_node Node
-- @treturn Slider @{Slider}
function Slider.set_input_node(self, input_node)
self._input_node = self:get_node(input_node)
return self
end

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle GUI timers.
-- Timer updating by game delta time. If game is not focused -
@@ -8,13 +8,13 @@
-- @alias druid.timer
--- On timer tick. Fire every second callback(self, value)
-- @tfield druid_event on_tick
-- @tfield DruidEvent on_tick @{DruidEvent}
--- On timer change enabled state callback(self, is_enabled)
-- @tfield druid_event on_set_enabled
-- @tfield DruidEvent on_set_enabled @{DruidEvent}
--- On timer end callback
-- @tfield druid_event on_timer_end(self, Timer)
-- @tfield DruidEvent on_timer_end(self, Timer) @{DruidEvent}
--- Trigger node
-- @tfield node node
@@ -39,7 +39,7 @@ local Timer = component.create("timer")
--- Component init function
-- @tparam Timer self
-- @tparam Timer self @{Timer}
-- @tparam node node Gui text node
-- @tparam number seconds_from Start timer value in seconds
-- @tparam[opt=0] number seconds_to End timer value in seconds
@@ -94,7 +94,7 @@ end
--- Set text to text field
-- @tparam Timer self
-- @tparam Timer self @{Timer}
-- @tparam number set_to Value in seconds
function Timer.set_to(self, set_to)
self.last_value = set_to
@@ -103,7 +103,7 @@ end
--- Called when update
-- @tparam Timer self
-- @tparam Timer self @{Timer}
-- @tparam bool is_on Timer enable state
function Timer.set_state(self, is_on)
self.is_on = is_on
@@ -113,7 +113,7 @@ end
--- Set time interval
-- @tparam Timer self
-- @tparam Timer self @{Timer}
-- @tparam number from Start time in seconds
-- @tparam number to Target time in seconds
function Timer.set_interval(self, from, to)

View File

@@ -1,7 +1,8 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Druid helper module for gui layouts
-- @module helper
--- Druid helper module for gui layouts
-- @module Helper
-- @alias druid.helper
local const = require("druid.const")
@@ -172,7 +173,6 @@ function M.is_enabled(node)
end
--- Return closest non inverted clipping parent node for node
-- @function helper.get_closest_stencil_node
-- @tparam node node Gui node
@@ -208,7 +208,7 @@ end
--- Check if device is mobile (Android or iOS)
-- @function helper..is_mobile
-- @function helper.is_mobile
function M.is_mobile()
return const.CURRENT_SYSTEM_NAME == const.OS.IOS or
const.CURRENT_SYSTEM_NAME == const.OS.ANDROID

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid inner module to acquire/release input
-- @module helper.input

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid module with utils on string formats
-- @local

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
local M = {}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
local const = require("druid.const")
local settings = require("druid.system.settings")

View File

@@ -0,0 +1,137 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 147.0
y: 49.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/button_blue"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 10.0
z: 15.0
w: 10.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 5.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 175.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.5
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,137 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 147.0
y: 49.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/button_green"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 10.0
z: 15.0
w: 10.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 5.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 175.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.5
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,137 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 147.0
y: 49.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/button_red"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 10.0
z: 15.0
w: 10.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 5.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 175.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.5
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,137 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 147.0
y: 49.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/button_yellow"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 10.0
z: 15.0
w: 10.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 5.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 175.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.5
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,181 @@
script: ""
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 50.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
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: 38.0
y: 36.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/check_back_square"
id: "back"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 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: 21.0
y: 20.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/checkmark"
id: "checkmark"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,137 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 180.0
y: 45.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/progress_back"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 20.0
y: 10.0
z: 20.0
w: 10.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 3.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 220.0
y: 45.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: "Input"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.75
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,181 @@
script: ""
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 4.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/slider_back"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 10.0
y: 0.0
z: 10.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 240.0
y: 45.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: "input_zone"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
x: -100.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.7
y: 0.7
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.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/slider_move"
id: "pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -1,3 +1,3 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
return {}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
local M = {}

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Instance of Druid. Make one instance per gui_script with next code:
--
@@ -140,7 +140,6 @@ local function check_sort_input_stack(self, components)
end
--- Check whitelists and blacklists for input components
local function can_use_input_component(self, component)
local can_by_whitelist = true
@@ -195,6 +194,7 @@ end
-- @tparam DruidInstance self
-- @tparam table context Druid context. Usually it is self of script
-- @tparam table style Druid style module
-- @local
function DruidInstance.initialize(self, context, style)
self._context = context
self._style = style or settings.default_style
@@ -391,6 +391,7 @@ end
--- Druid on focus lost interest function.
-- This one called by on_window_callback by global window listener
-- @tparam DruidInstance self
-- @local
function DruidInstance.on_focus_lost(self)
local components = self.components_interest[base_component.ON_FOCUS_LOST]
for i = 1, #components do
@@ -402,6 +403,7 @@ end
--- Druid on focus gained interest function.
-- This one called by on_window_callback by global window listener
-- @tparam DruidInstance self
-- @local
function DruidInstance.on_focus_gained(self)
local components = self.components_interest[base_component.ON_FOCUS_GAINED]
for i = 1, #components do
@@ -414,7 +416,7 @@ end
-- This one called by global gruid.on_language_change, but can be
-- call manualy to update all translations
-- @tparam DruidInstance self
-- @function druid.on_language_change
-- @local
function DruidInstance.on_language_change(self)
local components = self.components_interest[base_component.ON_LANGUAGE_CHANGE]
for i = 1, #components do
@@ -428,7 +430,6 @@ end
-- component will be not processed on input step
-- @tparam DruidInstance self
-- @tparam[opt=nil] table|Component whitelist_components The array of component to whitelist
-- @function druid.set_whitelist
function DruidInstance.set_whitelist(self, whitelist_components)
if whitelist_components and whitelist_components.isInstanceOf then
whitelist_components = { whitelist_components }
@@ -451,7 +452,6 @@ end
-- component will be not processed on input step
-- @tparam DruidInstance self
-- @tparam[opt=nil] table|Component blacklist_components The array of component to blacklist
-- @function druid.set_blacklist
function DruidInstance.set_blacklist(self, blacklist_components)
if blacklist_components and blacklist_components.isInstanceOf then
blacklist_components = { blacklist_components }
@@ -647,9 +647,9 @@ end
--- Create data list basic component
-- @function druid:new_data_list
-- @tparam druid.scroll druid_scroll The Scroll instance for Data List component
-- @tparam druid.grid druid_grid The Grid instance for Data List component
-- @tparam DruidInstance self
-- @tparam Scroll druid_scroll The Scroll instance for Data List component
-- @tparam Grid druid_grid The Grid instance for Data List component
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
-- @treturn DataList data_list component
function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid settings file
-- @module settings

View File

@@ -0,0 +1,26 @@
local component = require("druid.component")
---@class component_name : druid.base_component
local Component = component.create("component_name")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
function Component:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.button = self.druid:new_button(SCHEME.BUTTON, function() end)
end
function Component:on_remove()
end
return Component

View File

@@ -1,15 +1,28 @@
-- Copyright (c) 2021 Maxim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid component template
-- @module druid.component
-- @local
local component = require("druid.component")
local Component = component.create("my_component_name")
---@class component_name : druid.base_component
local Component = component.create("component_name")
-- Scheme of component gui nodes
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
-- Component constructor
function Component:init(...)
function Component:init(template, nodes)
-- If your component is gui template, pass the template name and set it
self:set_template(template)
-- If your component is cloned my gui.clone_tree, pass nodes to component and set it
self:set_nodes(nodes)
-- self:get_node will auto process component template and nodes
self.root = self:get_node(SCHEME.ROOT)
-- Use inner druid instance to create components inside this component
self.druid = self:get_druid()
end

View File

@@ -0,0 +1,31 @@
--- For component interest functions
--- see https://github.com/Insality/druid/blob/develop/docs_md/02-creating_custom_components.md
--- Require this component in you gui file:
--- local {COMPONENT_NAME} = require("{COMPONENT_PATH}")
--- And create this component via:
--- self.{COMPONENT_TYPE} = self.druid:new({COMPONENT_NAME}, template, nodes)
local component = require("druid.component")
---@class {COMPONENT_TYPE}: druid.base_component{COMPONENT_ANNOTATIONS}
local {COMPONENT_NAME} = component.create("{COMPONENT_TYPE}")
local SCHEME = {
{SCHEME_LIST}
}
{COMPONENT_FUNCTIONS}
---@param template string
---@param nodes table<hash, node>
function {COMPONENT_NAME}:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid(){COMPONENT_DEFINE}
end
function {COMPONENT_NAME}:on_remove()
end
return {COMPONENT_NAME}

View File

@@ -0,0 +1,130 @@
# @license MIT, Insality 2021
# @source https://github.com/Insality/druid
import os
import sys
import deftree
current_filepath = os.path.abspath(os.path.dirname(__file__))
TEMPLATE_FILE = open(current_filepath + "/component.lua_template", "r")
component_annotations = ""
component_functions = ""
component_define = ""
def to_camel_case(snake_str):
components = snake_str.split('_')
return ''.join(x.title() for x in components[0:])
def get_id(node_name):
return node_name.upper().replace("/", "_")
def process_component(node_name, component_name):
global component_annotations
global component_functions
global component_define
if node_name.startswith("button"):
component_annotations += "\n---@field {0} druid.button".format(node_name)
component_functions += "\nfunction {1}:_on_{0}()\n\tprint(\"Click on {0}\")\nend\n\n".format(node_name, component_name)
component_define += "\n\tself.{0} = self.druid:new_button(SCHEME.{1}, self._on_{0})".format(node_name, get_id(node_name))
if node_name.startswith("text"):
component_annotations += "\n---@field {0} druid.text".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_text(SCHEME.{1})".format(node_name, get_id(node_name))
if node_name.startswith("lang_text"):
component_annotations += "\n---@field {0} druid.text".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_lang_text(SCHEME.{1}, \"lang_id\")".format(node_name, get_id(node_name))
if node_name.startswith("grid") or node_name.startswith("static_grid"):
component_annotations += "\n---@field {0} druid.static_grid".format(node_name)
component_define += "\n--TODO: Replace prefab_name with grid element prefab"
component_define += "\n\tself.{0} = self.druid:new_static_grid(SCHEME.{1}, \"prefab_name\", 1)".format(node_name, get_id(node_name))
if node_name.startswith("dynamic_grid"):
component_annotations += "\n---@field {0} druid.dynamic_grid".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_dynamic_grid(SCHEME.{1})".format(node_name, get_id(node_name))
if node_name.startswith("scroll_view"):
field_name = node_name.replace("_view", "")
content_name = node_name.replace("_view", "_content")
component_annotations += "\n---@field {0} druid.scroll".format(field_name)
component_define += "\n\tself.{0} = self.druid:new_scroll(SCHEME.{1}, SCHEME.{2})".format(field_name, get_id(node_name), get_id(content_name))
if node_name.startswith("blocker"):
component_annotations += "\n---@field {0} druid.blocker".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_blocker(SCHEME.{1})".format(node_name, get_id(node_name))
if node_name.startswith("slider"):
component_annotations += "\n---@field {0} druid.slider".format(node_name)
component_define += "\n--TODO: Replace slider end position. It should be only vertical or horizontal"
component_define += "\n\tself.{0} = self.druid:new_slider(SCHEME.{1}, vmath.vector3(100, 0, 0), self._on_{0}_change)".format(node_name, get_id(node_name))
component_functions += "\nfunction {1}:_on_{0}_change(value)\n\tprint(\"Slider change:\", value)\nend\n\n".format(node_name, component_name)
if node_name.startswith("progress"):
component_annotations += "\n---@field {0} druid.progress".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_progress(SCHEME.{1}, \"x\")".format(node_name, get_id(node_name))
if node_name.startswith("timer"):
component_annotations += "\n---@field {0} druid.timer".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_timer(SCHEME.{1}, 59, 0, self._on_{0}_end)".format(node_name, get_id(node_name))
component_functions += "\nfunction {1}:_on_{0}_end()\n\tprint(\"Timer {0} trigger\")\nend\n\n".format(node_name, component_name)
def main():
global component_annotations
global component_functions
global component_define
filename = sys.argv[1]
print("Create Druid component from gui file", filename)
tree = deftree.parse(filename)
root = tree.get_root()
output_directory = os.path.dirname(filename)
output_filename = os.path.splitext(os.path.basename(filename))[0]
output_full_path = os.path.join(output_directory, output_filename + ".lua")
is_already_exists = os.path.exists(output_full_path)
if is_already_exists:
print("Error: The file is already exists")
print("File:", output_full_path)
return
component_require_path = os.path.join(output_directory, output_filename).replace("/", ".").replace("..", "")
component_name = to_camel_case(output_filename)
component_type = output_filename
scheme_list = []
# Gather nodes from GUI scene
for node in root.iter_elements("nodes"):
node_name = node.get_attribute("id").value
scheme_list.append("\t" + get_id(node_name) + " = \"" + node_name + "\"")
is_template = node.get_attribute("template")
is_in_template = "/" in node_name
if not is_template and not is_in_template:
process_component(node_name, component_name)
if len(component_define) > 2:
component_define = "\n" + component_define
filedata = TEMPLATE_FILE.read()
filedata = filedata.replace("{COMPONENT_NAME}", component_name)
filedata = filedata.replace("{COMPONENT_TYPE}", component_type)
filedata = filedata.replace("{COMPONENT_PATH}", component_require_path)
filedata = filedata.replace("{COMPONENT_DEFINE}", component_define)
filedata = filedata.replace("{COMPONENT_FUNCTIONS}", component_functions)
filedata = filedata.replace("{COMPONENT_ANNOTATIONS}", component_annotations)
filedata = filedata.replace("{SCHEME_LIST}", ",\n".join(scheme_list))
output_file = open(output_full_path, "w")
output_file.write(filedata)
output_file.close()
print("Success: The file is created")
print("File:", output_full_path)
main()

View File

@@ -0,0 +1,15 @@
#!/bin/bash
# @license MIT, Insality 2022
# @source https://github.com/Insality/druid
echo "Run bash for $1"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
is_defree_installed=$(pip3 list --disable-pip-version-check | grep -E "deftree")
if [ -z "$is_defree_installed" ]; then
echo "The python deftree is not installed. Please install it via"
echo "pip3 install deftree"
exit 0
fi
python3 $DIR/create_druid_component.py $@

View File

@@ -68,6 +68,36 @@ function M.get_commands()
}
}
end
},
{
label = "Create Druid Component",
locations = {"Edit"},
query = {
selection = {type = "resource", cardinality = "one"}
},
active = function(opts)
local path = editor.get(opts.selection, "path")
return ends_with(path, ".gui")
end,
run = function(opts)
local file = opts.selection
print("Run script for", editor.get(file, "path"))
return {
{
action = "shell",
command = {
"bash",
"./editor_scripts/create_druid_component.sh",
"." .. editor.get(file, "path")
}
}
}
end
}
}
end

View File

@@ -5,4 +5,11 @@
echo "Run bash for $1"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
/usr/local/bin/python3.7 $DIR/setup_layers.py $@
is_defree_installed=$(pip3 list --disable-pip-version-check | grep -E "deftree")
if [ -z "$is_defree_installed" ]; then
echo "The python deftree is not installed. Please install it via"
echo "pip3 install deftree"
exit 0
fi
python3 $DIR/setup_layers.py $@

View File

@@ -2,10 +2,6 @@ images {
image: "/example/assets/images/back/back_blue.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
images {
image: "/example/assets/images/back/back_gray.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
images {
image: "/example/assets/images/back/back_green.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
@@ -34,14 +30,6 @@ images {
image: "/example/assets/images/progress/progress_back.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
images {
image: "/example/assets/images/progress/progress_fill_green.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
images {
image: "/example/assets/images/progress/progress_fill_red.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
images {
image: "/example/assets/images/progress/progress_fill_yellow.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF

View File

@@ -1247,3 +1247,192 @@ embedded_instances {
z: 1.0
}
}
embedded_instances {
id: "custom_rich_input"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"custom_rich_input\"\n"
" type: PROPERTY_TYPE_HASH\n"
" }\n"
" properties {\n"
" id: \"popup\"\n"
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/custom/rich_input/rich_input.collection\\\"\\n"
"load_dynamically: false\\n"
"\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
embedded_instances {
id: "custom_pin_knob"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"custom_pin_knob\"\n"
" type: PROPERTY_TYPE_HASH\n"
" }\n"
" properties {\n"
" id: \"popup\"\n"
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/custom/pin_knob/pin_knob.collection\\\"\\n"
"load_dynamically: false\\n"
"\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
embedded_instances {
id: "system_inner_templates"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"system_inner_templates\"\n"
" type: PROPERTY_TYPE_HASH\n"
" }\n"
" properties {\n"
" id: \"popup\"\n"
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/system/inner_templates/inner_templates.collection\\\"\\n"
"load_dynamically: false\\n"
"\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}

View File

@@ -66,6 +66,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -121,6 +122,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -176,6 +178,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -231,6 +234,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -286,6 +290,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -341,6 +346,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -396,6 +402,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -459,6 +466,7 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
nodes {
position {
@@ -514,6 +522,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -569,6 +578,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -632,6 +642,7 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
nodes {
position {
@@ -687,6 +698,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -721,7 +733,7 @@ nodes {
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/back_gray"
texture: "kenney/progress_back"
id: "panel_top"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
@@ -742,6 +754,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -782,6 +795,7 @@ nodes {
alpha: 1.0
template: "/example/templates/button.gui"
template_node_child: false
custom_type: 0
}
nodes {
position {
@@ -839,6 +853,7 @@ nodes {
overridden_fields: 20
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -907,6 +922,7 @@ nodes {
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
nodes {
position {
@@ -947,6 +963,7 @@ nodes {
alpha: 1.0
template: "/example/templates/button.gui"
template_node_child: false
custom_type: 0
}
nodes {
position {
@@ -1004,6 +1021,7 @@ nodes {
overridden_fields: 20
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -1072,6 +1090,7 @@ nodes {
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
nodes {
position {
@@ -1112,6 +1131,7 @@ nodes {
alpha: 1.0
template: "/example/templates/button.gui"
template_node_child: false
custom_type: 0
}
nodes {
position {
@@ -1169,6 +1189,7 @@ nodes {
overridden_fields: 20
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -1237,6 +1258,7 @@ nodes {
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
nodes {
position {
@@ -1300,6 +1322,7 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
}
layers {
name: "image"

View File

@@ -3,6 +3,13 @@ local druid = require("druid.druid")
local monarch = require("monarch.monarch")
local default_style = require("druid.styles.default.style")
local cache_path = sys.get_save_file("druid", "cache")
local function save_cache(self)
sys.save(cache_path, self.cache)
end
local function back_to_lobby(self)
if gui.set_enabled(self.button_menu.node) then
@@ -15,8 +22,10 @@ local function back_to_lobby(self)
gui.set_enabled(self.button_code.node, false)
gui.set_enabled(self.button_api.node, true)
self.text_header:set_to("Druid")
self.cache.last_scene = nil
save_cache(self)
end
@@ -30,6 +39,9 @@ local function show_scene(self, scene_name, text_header)
gui.set_enabled(self.button_api.node, false)
self.text_header:set_to(text_header)
self.cache.last_scene = scene_name
save_cache(self)
end
@@ -92,7 +104,7 @@ local function get_button_disabled(self, text)
local prefab = gui.get_node("prefab_button")
local nodes = gui.clone_tree(prefab)
local root = nodes["prefab_button"]
gui.play_flipbook(nodes["icon_button"], "back_gray")
gui.play_flipbook(nodes["icon_button"], "progress_back")
gui.set_enabled(root, true)
gui.set_text(nodes["text_button_lobby"], text)
@@ -144,14 +156,18 @@ local function init_lobby(self)
self.lobby_grid:add(get_button_disabled(self, "Add/remove elements", "data_list_add_remove_nodes"))
self.lobby_grid:add(get_button(self, "Navigate over elements", "data_list_navigate", "/data_list/navigate/navigate.gui_script"))
self.lobby_grid:add(get_title(self, "Custom components"))
self.lobby_grid:add(get_button(self, "Rich Input", "custom_rich_input", "/custom/rich_input/rich_input.gui_script"))
self.lobby_grid:add(get_button(self, "Pin Knob", "custom_pin_knob", "/custom/pin_knob/pin_knob.gui_script"))
self.lobby_grid:add(get_title(self, "System"))
self.lobby_grid:add(get_button_disabled(self, "Styles"))
self.lobby_grid:add(get_button(self, "Whitelist / Blacklist", "system_whitelist_blacklist", "/system/whitelist_blacklist/whitelist_blacklist.gui_script"))
self.lobby_grid:add(get_button_disabled(self, "Custom components"))
self.lobby_grid:add(get_button_disabled(self, "Component interests"))
self.lobby_grid:add(get_button_disabled(self, "Nested Druids"))
self.lobby_grid:add(get_button(self, "Message input", "system_message_input", "/system/message_input/message_input.gui_script"))
self.lobby_grid:add(get_button_disabled(self, "Input priority"))
self.lobby_grid:add(get_button(self, "Inner templates", "system_inner_templates", "/system/inner_templates/inner_templates.gui_script"))
end
@@ -159,10 +175,37 @@ local function check_url(self)
if not html5 then
return
end
local example_arg = html5.run("new URLSearchParams(window.location.search).get('example')")
if example_arg and self.scene_names[example_arg] then
print("Start example: ", example_arg)
show_scene(self, example_arg, self.scene_names[example_arg] or "unknown")
return true
end
end
local function check_cache(self)
local scroll_position = self.cache.scroll_position
if scroll_position then
self.lobby_scroll:scroll_to_percent(vmath.vector3(0, scroll_position, 0), true)
end
local last_scene = self.cache.last_scene
if last_scene then
show_scene(self, last_scene, self.scene_names[last_scene] or "unknown")
return true
end
end
local function check_loading(self)
if check_url(self) then
return
end
if check_cache(self) then
return
end
end
@@ -174,12 +217,13 @@ function init(self)
window.set_listener(on_window_callback)
druid.set_default_style(default_style)
self.druid = druid.new(self)
self.cache = sys.load(cache_path) or {}
init_top_panel(self)
init_lobby(self)
self.current_script_url = ""
timer.delay(0, false, check_url)
timer.delay(0, false, check_loading)
end
@@ -188,6 +232,14 @@ function update(self, dt)
end
function final(self)
self.cache.scroll_position = self.lobby_scroll:get_percent().y
save_cache(self)
self.druid:final()
end
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end

View File

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

View File

@@ -0,0 +1,677 @@
script: "/example/examples/custom/pin_knob/pin_knob.gui_script"
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 300.0
y: 415.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: 830.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 370.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 700.0
y: 60.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: "Rich Input custom component"
font: "game"
id: "text_hint_horizontal"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: -100.0
y: 230.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "pin_knob1"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/pin_knob/pin_knob.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "pin_knob1/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
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: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.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/slider_move"
id: "pin_knob1/pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "pin_knob1/notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1/pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: -100.0
y: 154.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 120.0
y: 60.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: "50"
font: "game"
id: "text_value1"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 100.0
y: 230.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "pin_knob2"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/pin_knob/pin_knob.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "pin_knob2/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
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: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.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/slider_move"
id: "pin_knob2/pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "pin_knob2/notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2/pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 100.0
y: 154.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 120.0
y: 60.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: "50"
font: "game"
id: "text_value2"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
layers {
name: "image"
}
layers {
name: "text"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,49 @@
local druid = require("druid.druid")
local pin_knob = require("druid.custom.pin_knob.pin_knob")
local function on_pin_change1(self, value)
self.text1:set_to(math.ceil(value))
end
local function on_pin_change2(self, value)
self.text2:set_to(math.ceil(value))
end
function init(self)
self.druid = druid.new(self)
self.text1 = self.druid:new_text("text_value1", 0)
---@type druid.pin_knob
self.pin_knob = self.druid:new(pin_knob, on_pin_change1, "pin_knob1")
self.pin_knob:set_angle(-10, -270, 270)
self.text2 = self.druid:new_text("text_value2", 0)
---@type druid.pin_knob
self.pin_knob2 = self.druid:new(pin_knob, on_pin_change2, "pin_knob2")
self.pin_knob2:set_angle(0, -90, 90)
self.pin_knob2:set_friction(0.15)
end
function final(self)
self.druid:final()
end
function update(self, dt)
self.druid:update(dt)
end
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end

View File

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

View File

@@ -0,0 +1,535 @@
script: "/example/examples/custom/rich_input/rich_input.gui_script"
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 300.0
y: 415.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: 830.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 370.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 700.0
y: 60.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: "Rich Input custom component"
font: "game"
id: "text_hint_horizontal"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 0.0
y: 230.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "rich_input"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/rich_input/rich_input.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "rich_input/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 190.0
y: 45.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/progress_back"
id: "rich_input/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.5
y: 0.5
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.9490196
y: 0.9490196
z: 0.9490196
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Placeholder"
font: "game"
id: "rich_input/placeholder_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.4
y: 0.4
z: 0.4
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: true
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: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 60.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: "User input"
font: "game"
id: "rich_input/input_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 67.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "rich_input/cursor_node"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input/button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 2.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: 20.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.2
y: 0.2
z: 0.2
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "|"
font: "game"
id: "rich_input/cursor_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/cursor_node"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
}
layers {
name: "image"
}
layers {
name: "text"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,32 @@
local druid = require("druid.druid")
local rich_input = require("druid.custom.rich_input.rich_input")
function init(self)
self.druid = druid.new(self)
---@type druid.rich_input
self.rich_input = self.druid:new(rich_input, "rich_input")
self.rich_input:set_placeholder("Enter text here")
end
function final(self)
self.druid:final()
end
function update(self, dt)
self.druid:update(dt)
end
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end

View File

@@ -66,6 +66,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -121,6 +122,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -176,6 +178,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -239,6 +242,63 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 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: 300.0
y: 45.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: "slider_input"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "slider_back_simple"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
nodes {
position {
@@ -294,6 +354,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -349,6 +410,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -404,6 +466,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -459,6 +522,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -514,6 +578,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -569,6 +634,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -624,6 +690,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -679,6 +746,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -734,6 +802,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -789,6 +858,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -844,6 +914,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -899,6 +970,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -954,6 +1026,7 @@ nodes {
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -1009,6 +1082,7 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
}
nodes {
position {
@@ -1072,6 +1146,63 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 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: 300.0
y: 45.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: "slider_notched_input"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "slider_back_notched"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
}
layers {
name: "image"

View File

@@ -9,6 +9,7 @@ function init(self)
end)
slider:set(0.2)
slider:set_input_node("slider_input")
local slider_notched = self.druid:new_slider("slider_notched_pin", vmath.vector3(95, 0, 0), function(_, value)
gui.set_text(gui.get_node("slider_notched_text"), math.ceil(value * 100) .. "%")
@@ -16,6 +17,7 @@ function init(self)
slider_notched:set_steps({0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1})
slider_notched:set(0.2)
slider_notched:set_input_node("slider_notched_input")
end

View File

@@ -0,0 +1,190 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
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: 49.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/button_blue"
id: "button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 0.0
z: 15.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: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 230.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Some text"
font: "game"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,25 @@
local component = require("druid.component")
---@class inner_button : druid.base_component
local InnerButton = component.create("inner_button")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
TEXT = "text",
}
function InnerButton:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
local value = math.random(0, 99)
self.button = self.druid:new_button(SCHEME.BUTTON, function() print(value) end)
self.text = self.druid:new_text(SCHEME.TEXT, value)
end
return InnerButton

View File

@@ -0,0 +1,762 @@
script: ""
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.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: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
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: 250.0
y: 270.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/back_red"
id: "background"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 15.0
z: 15.0
w: 15.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: 80.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "inner_button_1"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/examples/system/inner_templates/inner_button.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "inner_button_1/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_1"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
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: 49.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/button_blue"
id: "inner_button_1/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_1/root"
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 0.0
z: 15.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 230.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Some text"
font: "game"
id: "inner_button_1/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "inner_button_1/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "inner_button_2"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/examples/system/inner_templates/inner_button.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "inner_button_2/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_2"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
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: 49.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/button_blue"
id: "inner_button_2/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_2/root"
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 0.0
z: 15.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 230.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Some text"
font: "game"
id: "inner_button_2/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "inner_button_2/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 0.0
y: -80.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "inner_button_prefab"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/examples/system/inner_templates/inner_button.gui"
template_node_child: false
}
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: 1.0
y: 1.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: "inner_button_prefab/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_prefab"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
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: 49.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/button_blue"
id: "inner_button_prefab/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "inner_button_prefab/root"
layer: ""
inherit_alpha: true
slice9 {
x: 15.0
y: 0.0
z: 15.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 230.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Some text"
font: "game"
id: "inner_button_prefab/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "inner_button_prefab/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,39 @@
local component = require("druid.component")
local InnerButton = require("example.examples.system.inner_templates.inner_button")
---@class inner_panel : druid.base_component
local InnerPanel = component.create("inner_panel")
local SCHEME = {
ROOT = "root",
BACKGROUND = "background",
INNER_BUTTON_1 = "inner_button_1",
INNER_BUTTON_2 = "inner_button_2",
INNER_BUTTON_PREFAB = "inner_button_prefab",
INNER_BUTTON_PREFAB_ROOT = "inner_button_prefab/root",
}
function InnerPanel:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.button1 = self.druid:new(InnerButton, SCHEME.INNER_BUTTON_1, nodes)
self.button2 = self.druid:new(InnerButton, SCHEME.INNER_BUTTON_2, nodes)
local prefab = self:get_node(SCHEME.INNER_BUTTON_PREFAB_ROOT)
local button_nodes = gui.clone_tree(prefab)
self.button3 = self.druid:new(InnerButton, SCHEME.INNER_BUTTON_PREFAB, button_nodes)
gui.set_enabled(prefab, false)
end
function InnerPanel:on_remove()
end
return InnerPanel

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
local druid = require("druid.druid")
local InnerPanel = require("example.examples.system.inner_templates.inner_panel")
function init(self)
self.druid = druid.new(self)
local root = gui.get_node("inner_panel/root")
local nodes = gui.clone_tree(root)
self.inner_panel_2 = self.druid:new(InnerPanel, "inner_panel", nodes)
gui.set_position(self.inner_panel_2.root, vmath.vector3(125, 150, 0))
local nodes3 = gui.clone_tree(root)
self.inner_panel_3 = self.druid:new(InnerPanel, "inner_panel", nodes3)
gui.set_position(self.inner_panel_3.root, vmath.vector3(125, -150, 0))
self.inner_panel = self.druid:new(InnerPanel, "inner_panel")
end
function final(self)
self.druid:final()
end
function update(self, dt)
self.druid:update(dt)
end
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end

View File

@@ -28,6 +28,7 @@ use_accelerometer = 0
[druid]
no_auto_input = 0
stencil_check = 0
no_auto_template = 0
input_text = text
input_touch = touch
input_marked_text = marked_text

View File

@@ -1,4 +1,4 @@
#!/bin/bash
use_latest_bob=false
enable_incremental_version=true
bob_sha="187:581c6439ae93755a8a6bcf58732c39c724fa193c"
bob_sha="3.0:0e77ba11ac957ee01878bbde2e6ac0c9fae6dc01"