diff --git a/README.md b/README.md index 14ab3948..46405bc7 100644 --- a/README.md +++ b/README.md @@ -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: @@ -120,7 +133,7 @@ druid.on_window_callback(event) - **[Swipe](docs_md/01-components.md#swipe)** - System Druid component, handle swipe gestures on node -- **[Drag](docs_md/01-components.md#drag)** - System Druid component, handle drag input on node +- **[Drag](docs_md/01-components.md#drag)** - System Druid component, handle drag input on node **Druid** also provides the following *extended* components: @@ -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) diff --git a/annotations.lua b/annotations.lua index dd4c5074..ac86b6d6 100644 --- a/annotations.lua +++ b/annotations.lua @@ -10,16 +10,9 @@ local druid = {} ---@return druid_instance Druid instance function druid.new(context, style) end ---- Druid on language change. ----@param self druid_instance -function druid.on_language_change(self) end - --- Callback on global language change event. function druid.on_language_change() end ---- Callback on global layout change event. -function druid.on_layout_change() end - --- Callback on global window event. ---@param event string Event param from window listener function druid.on_window_callback(event) end @@ -29,11 +22,6 @@ function druid.on_window_callback(event) end ---@param module table lua table with component function druid.register(name, module) end ---- Set blacklist components for input processing. ----@param self druid_instance ----@param blacklist_components table|Component The array of component to blacklist -function druid.set_blacklist(self, blacklist_components) end - --- Set new default style. ---@param style table Druid style module function druid.set_default_style(style) end @@ -46,25 +34,20 @@ function druid.set_sound_function(callback) end ---@param callback function Get localized text function function druid.set_text_function(callback) end ---- Set whitelist components for input processing. ----@param self druid_instance ----@param whitelist_components table|Component The array of component to whitelist -function druid.set_whitelist(self, whitelist_components) end - ---@class druid.back_handler : druid.base_component ----@field on_back druid_event On back handler callback(self, params) +---@field on_back druid.event On back handler callback(self, params) ---@field params any Params to back callback local druid__back_handler = {} --- Component init function ----@param self druid.back_handler +---@param self druid.back_handler @{BackHandler} ---@param callback callback On back button ---@param params any Callback argument function druid__back_handler.init(self, callback, params) end --- Input handler for component ----@param self druid.back_handler +---@param self druid.back_handler @{BackHandler} ---@param action_id string on_input action id ---@param action table on_input action function druid__back_handler.on_input(self, action_id, action) end @@ -161,17 +144,17 @@ function druid__base_component.setup_component(self, druid_instance, context, st local druid__blocker = {} --- Component init function ----@param self druid.blocker +---@param self druid.blocker @{Blocker} ---@param node node Gui node function druid__blocker.init(self, node) end --- Return blocked enabled state ----@param self druid.blocker +---@param self druid.blocker @{Blocker} ---@return bool True, if blocker is enabled function druid__blocker.is_enabled(self) end --- Set enabled blocker component state ----@param self druid.blocker +---@param self druid.blocker @{Blocker} ---@param state bool Enabled state function druid__blocker.set_enabled(self, state) end @@ -182,12 +165,12 @@ function druid__blocker.set_enabled(self, state) end ---@field hash node_id The hash of trigger node ---@field hover druid.hover Druid hover logic component ---@field node node Trigger node ----@field on_click druid_event On release button callback(self, params, button_instance) ----@field on_click_outside druid_event On click outside of button(self, params, button_instance) ----@field on_double_click druid_event On double tap button callback(self, params, button_instance, click_amount) ----@field on_hold_callback druid_event On button hold before long_click callback(self, params, button_instance, time) ----@field on_long_click druid_event On long tap button callback(self, params, button_instance, time) ----@field on_repeated_click druid_event On repeated action button callback(self, params, button_instance, click_amount) +---@field on_click druid.event On release button callback(self, params, button_instance) +---@field on_click_outside druid.event On click outside of button(self, params, button_instance) +---@field on_double_click druid.event On double tap button callback(self, params, button_instance, click_amount) +---@field on_hold_callback druid.event On button hold before long_click callback(self, params, button_instance, time) +---@field on_long_click druid.event On long tap button callback(self, params, button_instance, time) +---@field on_repeated_click druid.event On repeated action button callback(self, params, button_instance, click_amount) ---@field params any Params to click callbacks ---@field pos vector3 Initial pos of anim_node ---@field start_pos vector3 Initial pos of anim_node @@ -201,7 +184,7 @@ local druid__button = {} function druid__button.get_key_trigger(self) end --- Component init function ----@param self druid.button +---@param self druid.button @{Button} ---@param node node Gui node ---@param callback function Button callback ---@param params table Button callback params @@ -209,30 +192,31 @@ function druid__button.get_key_trigger(self) end function druid__button.init(self, node, callback, params, anim_node) end --- Return button enabled state ----@param self druid.button +---@param self druid.button @{Button} ---@return bool True, if button is enabled function druid__button.is_enabled(self) end --- Set function for additional check for button click availability +---@param self druid.button ---@param check_function function Should return true or false. If true - button can be pressed. ---@param failure_callback function Function what will be called on button click, if check function return false ---@return druid.button Current button instance -function druid__button.set_check_function(check_function, failure_callback) end +function druid__button.set_check_function(self, check_function, failure_callback) end --- Strict button click area. ----@param self druid.button +---@param self druid.button @{Button} ---@param zone node Gui node ---@return druid.button Current button instance function druid__button.set_click_zone(self, zone) end --- Set enabled button component state ----@param self druid.button +---@param self druid.button @{Button} ---@param state bool Enabled state ---@return druid.button Current button instance function druid__button.set_enabled(self, state) end --- Set key-code to trigger this button ----@param self druid.button +---@param self druid.button @{Button} ---@param key hash The action_id of the key ---@return druid.button Current button instance function druid__button.set_key_trigger(self, key) end @@ -251,20 +235,20 @@ local druid__button__style = {} ---@class druid.checkbox : druid.base_component ----@field button Button Button component from click_node +---@field button druid.button Button component from click_node ---@field click_node node Button trigger node ---@field node node Visual node ----@field on_change_state druid_event On change state callback(self, state) +---@field on_change_state druid.event On change state callback(self, state) ---@field style druid.checkbox.style Component style params. local druid__checkbox = {} --- Return checkbox state ----@param self druid.checkbox +---@param self druid.checkbox @{Checkbox} ---@return bool Checkbox state function druid__checkbox.get_state(self) end --- Component init function ----@param self druid.checkbox +---@param self druid.checkbox @{Checkbox} ---@param node node Gui node ---@param callback function Checkbox callback ---@param click_node node Trigger node, by default equals to node @@ -272,7 +256,7 @@ function druid__checkbox.get_state(self) end function druid__checkbox.init(self, node, callback, click_node, initial_state) end --- Set checkbox state ----@param self druid.checkbox +---@param self druid.checkbox @{Checkbox} ---@param state bool Checkbox state ---@param is_silent bool Don't trigger on_change_state if true ---@param is_instant bool If instant checkbox change @@ -286,76 +270,76 @@ local druid__checkbox__style = {} ---@class druid.checkbox_group : druid.base_component ---@field checkboxes table Array of checkbox components ----@field on_checkbox_click druid_event On any checkbox click callback(self, index) +---@field on_checkbox_click druid.event On any checkbox click callback(self, index) local druid__checkbox_group = {} --- Return checkbox group state ----@param self druid.checkbox_group +---@param self druid.checkbox_group @{CheckboxGroup} ---@return bool[] Array if checkboxes state function druid__checkbox_group.get_state(self) end --- Component init function ----@param self druid.checkbox_group +---@param self druid.checkbox_group @{CheckboxGroup} ---@param nodes node[] Array of gui node ---@param callback function Checkbox callback ---@param click_nodes node[] Array of trigger nodes, by default equals to nodes function druid__checkbox_group.init(self, nodes, callback, click_nodes) end --- Set checkbox group state ----@param self druid.checkbox_group +---@param self druid.checkbox_group @{CheckboxGroup} ---@param indexes bool[] Array of checkbox state ---@param is_instant boolean If instant state change function druid__checkbox_group.set_state(self, indexes, is_instant) end ---@class druid.data_list : druid.base_component ----@field grid druid.static_grid The Druid Grid component +---@field grid druid.static_grid|druid.dynamic_grid The Druid Grid component ---@field last_index number The current visual last data index ----@field on_scroll_progress_change druid_event Event triggered when scroll progress is changed; event(self, progress_value) +---@field on_scroll_progress_change druid.event Event triggered when scroll progress is changed; event(self, progress_value) ---@field scroll druid.scroll The Druid scroll component ---@field scroll_progress number The current progress of scroll posititon ---@field top_index number The current visual top data index local druid__data_list = {} --- Clear the DataList and refresh visuals ----@param self druid.data_list +---@param self druid.data_list @{DataList} function druid__data_list.clear(self) end --- Return first index from data. ----@param self druid.data_list +---@param self druid.data_list @{DataList} function druid__data_list.get_first_index(self) end --- Return index for data value ----@param self druid.data_list +---@param self druid.data_list @{DataList} ---@param data table function druid__data_list.get_index(self, data) end --- Return last index from data ----@param self druid.data_list +---@param self druid.data_list @{DataList} function druid__data_list.get_last_index(self) end --- Return amount of data ----@param self druid.data_list +---@param self druid.data_list @{DataList} function druid__data_list.get_length(self) end --- Data list constructor ----@param self druid.data_list ----@param scroll druid.scroll The Scroll instance for Data List component ----@param grid druid.grid The Grid instance for Data List component +---@param self druid.data_list @{DataList} +---@param scroll druid.scroll The @{Scroll} instance for Data List component +---@param grid druid.static_grid|druid.dynamic_grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component ---@param create_function function The create function callback(self, data, index, data_list). Function should return (node, [component]) function druid__data_list.init(self, scroll, grid, create_function) end --- Druid System on_remove function ----@param self druid.data_list +---@param self druid.data_list @{DataList} function druid__data_list.on_remove(self) end --- Instant scroll to element with passed index ----@param self druid.data_list +---@param self druid.data_list @{DataList} ---@param index number function druid__data_list.scroll_to_index(self, index) end --- Set new data set for DataList component ----@param self druid.data_list +---@param self druid.data_list @{DataList} ---@param data table The new data array ---@return druid.data_list Current DataList instance function druid__data_list.set_data(self, data) end @@ -366,11 +350,11 @@ function druid__data_list.set_data(self, data) end ---@field can_y bool Is drag component process horizontal. ---@field is_drag bool Is component now dragging ---@field is_touch bool Is component now touching ----@field on_drag druid_event on drag progress callback(self, dx, dy) ----@field on_drag_end druid_event Event on drag end callback(self) ----@field on_drag_start druid_event Event on drag start callback(self) ----@field on_touch_end druid_event Event on touch end callback(self) ----@field on_touch_start druid_event Event on touch start callback(self) +---@field on_drag druid.event on drag progress callback(self, dx, dy) +---@field on_drag_end druid.event Event on drag end callback(self) +---@field on_drag_start druid.event Event on drag start callback(self) +---@field on_touch_end druid.event Event on touch end callback(self) +---@field on_touch_start druid.event Event on touch start callback(self) ---@field style druid.drag.style Component style params. ---@field touch_start_pos vector3 Touch start position ---@field x number Current touch x position @@ -378,13 +362,13 @@ function druid__data_list.set_data(self, data) end local druid__drag = {} --- Drag component constructor ----@param self druid.drag +---@param self druid.drag @{Drag} ---@param node node GUI node to detect dragging ---@param on_drag_callback function Callback for on_drag_event(self, dx, dy) function druid__drag.init(self, node, on_drag_callback) end --- Strict drag click area. ----@param self druid.drag +---@param self druid.drag @{Drag} ---@param node node Gui node function druid__drag.set_click_zone(self, node) end @@ -400,11 +384,11 @@ local druid__drag__style = {} ---@field last_index number The last index of node in grid ---@field node_size vector3 Item size ---@field nodes node[] List of all grid elements. ----@field on_add_item druid_event On item add callback(self, node, index) ----@field on_change_items druid_event On item add or remove callback(self, index) ----@field on_clear druid_event On grid clear callback(self) ----@field on_remove_item druid_event On item remove callback(self, index) ----@field on_update_positions druid_event On update item positions callback(self) +---@field on_add_item druid.event On item add callback(self, node, index) +---@field on_change_items druid.event On item add or remove callback(self, index) +---@field on_clear druid.event On grid clear callback(self) +---@field on_remove_item druid.event On item remove callback(self, index) +---@field on_update_positions druid.event On update item positions callback(self) ---@field parent node Parent gui node local druid__dynamic_grid = {} @@ -415,41 +399,41 @@ local druid__dynamic_grid = {} function druid__dynamic_grid._get_side_vector(self, side, is_forward) end --- Add new node to the grid ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param node node Gui node ---@param index number The node position. By default add as last node ---@param shift_policy number How shift nodes, if required. See const.SHIFT ----@param is_instance boolean If true, update node positions instantly -function druid__dynamic_grid.add(self, node, index, shift_policy, is_instance) end +---@param is_instant boolean If true, update node positions instantly +function druid__dynamic_grid.add(self, node, index, shift_policy, is_instant) end --- Clear grid nodes array. ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@return druid.dynamic_grid Current grid instance function druid__dynamic_grid.clear(self) end --- Return array of all node positions ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@return vector3[] All grid node positions function druid__dynamic_grid.get_all_pos(self) end --- Return grid content borders ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@return vector3 The grid content borders function druid__dynamic_grid.get_borders(self) end --- Return grid index by node ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param node node The gui node in the grid ---@return number The node index function druid__dynamic_grid.get_index_by_node(self, node) end --- Return DynamicGrid offset, where DynamicGrid content starts. ----@param self druid.dynamic_grid The DynamicGrid instance +---@param self druid.dynamic_grid @{DynamicGrid} The DynamicGrid instance ---@return vector3 The DynamicGrid offset function druid__dynamic_grid.get_offset(self) end --- Return pos for grid node index ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param index number The grid element index ---@param node node The node to be placed ---@param origin_index number Index of nearby node @@ -457,64 +441,99 @@ function druid__dynamic_grid.get_offset(self) end function druid__dynamic_grid.get_pos(self, index, node, origin_index) end --- Return grid content size ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param border vector3 ---@return vector3 The grid content size function druid__dynamic_grid.get_size(self, border) end --- Component init function ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param parent node The gui node parent, where items will be placed function druid__dynamic_grid.init(self, parent) end --- Remove the item from the grid. ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param index number The grid node index to remove ---@param shift_policy number How shift nodes, if required. See const.SHIFT ----@param is_instance boolean If true, update node positions instantly ----@return Node The deleted gui node from grid -function druid__dynamic_grid.remove(self, index, shift_policy, is_instance) end +---@param is_instant boolean If true, update node positions instantly +---@return node The deleted gui node from grid +function druid__dynamic_grid.remove(self, index, shift_policy, is_instant) end --- Change set position function for grid nodes. ----@param self druid.dynamic_grid +---@param self druid.dynamic_grid @{DynamicGrid} ---@param callback function Function on node set position ---@return druid.dynamic_grid Current grid instance function druid__dynamic_grid.set_position_function(self, callback) end +---@class druid.event +local druid__event = {} + +--- Clear the all event handlers +---@param self druid.event @{DruidEvent} +function druid__event.clear(self) end + +--- Event constructur +---@param self druid.event @{DruidEvent} +---@param initial_callback function Subscribe the callback on new event, if callback exist +function druid__event.initialize(self, initial_callback) end + +--- Return true, if event have at lease one handler +---@param self druid.event @{DruidEvent} +---@return bool True if event have handlers +function druid__event.is_exist(self) end + +--- Subscribe callback on event +---@param self druid.event @{DruidEvent} +---@param callback function Callback itself +---@param context table Additional context as first param to callback call +function druid__event.subscribe(self, callback, context) end + +--- Trigger the event and call all subscribed callbacks +---@param self druid.event @{DruidEvent} +---@param ... any All event params +function druid__event.trigger(self, ...) end + +--- Unsubscribe callback on event +---@param self druid.event @{DruidEvent} +---@param callback function Callback itself +---@param context table Additional context as first param to callback call +function druid__event.unsubscribe(self, callback, context) end + + ---@class druid.hover : druid.base_component ----@field on_hover druid_event On hover callback(self, state) ----@field on_mouse_hover druid_event On mouse hover callback(self, state) +---@field on_hover druid.event On hover callback(self, state) +---@field on_mouse_hover druid.event On mouse hover callback(self, state) local druid__hover = {} --- Component init function ----@param self druid.hover +---@param self druid.hover @{Hover} ---@param node node Gui node ---@param on_hover_callback function Hover callback function druid__hover.init(self, node, on_hover_callback) end --- Return current hover enabled state ----@param self druid.hover +---@param self druid.hover @{Hover} ---@return bool The hover enabled state function druid__hover.is_enabled(self) end --- Strict hover click area. ----@param self druid.hover +---@param self druid.hover @{Hover} ---@param zone node Gui node function druid__hover.set_click_zone(self, zone) end --- Set enable state of hover component. ----@param self druid.hover +---@param self druid.hover @{Hover} ---@param state bool The hover enabled state function druid__hover.set_enabled(self, state) end --- Set hover state ----@param self druid.hover +---@param self druid.hover @{Hover} ---@param state bool The hover state function druid__hover.set_hover(self, state) end --- Set mouse hover state ----@param self druid.hover +---@param self druid.hover @{Hover} ---@param state bool The mouse hover state function druid__hover.set_mouse_hover(self, state) end @@ -526,48 +545,55 @@ function druid__hover.set_mouse_hover(self, state) end ---@field is_selected bool Is current input selected now ---@field keyboard_type number Gui keyboard type for input field ---@field max_length number Max length for input text ----@field on_input_empty druid_event On input field text change to empty string callback(self, input_text) ----@field on_input_full druid_event On input field text change to max length string callback(self, input_text) ----@field on_input_select druid_event On input field select callback(self, button_node) ----@field on_input_text druid_event On input field text change callback(self, input_text) ----@field on_input_unselect druid_event On input field unselect callback(self, input_text) ----@field on_input_wrong druid_event On trying user input with not allowed character callback(self, params, button_instance) +---@field on_input_empty druid.event On input field text change to empty string callback(self, input_text) +---@field on_input_full druid.event On input field text change to max length string callback(self, input_text) +---@field on_input_select druid.event On input field select callback(self, button_node) +---@field on_input_text druid.event On input field text change callback(self, input_text) +---@field on_input_unselect druid.event On input field unselect callback(self, input_text) +---@field on_input_wrong druid.event On trying user input with not allowed character callback(self, params, button_instance) ---@field style druid.input.style Component style params. ---@field text druid.text Text component local druid__input = {} --- Return current input field text ----@param self druid.input +---@param self druid.input @{Input} ---@return string The current input field text function druid__input.get_text(self) end +--- Component init function +---@param self druid.input @{Input} +---@param click_node node Button node to enabled input component +---@param text_node node|druid.text Text node what will be changed on user input. You can pass text component instead of text node name @{Text} +---@param keyboard_type number Gui keyboard type for input field +function druid__input.init(self, click_node, text_node, keyboard_type) end + --- Reset current input selection and return previous value ----@param self druid.input +---@param self druid.input @{Input} function druid__input.reset_changes(self) end --- Select input field. ----@param self druid.input +---@param self druid.input @{Input} function druid__input.select(self) end --- Set allowed charaters for input field. ----@param self druid.input +---@param self druid.input @{Input} ---@param characters string Regulax exp. for validate user input ---@return druid.input Current input instance function druid__input.set_allowed_characters(self, characters) end --- Set maximum length for input field. ----@param self druid.input +---@param self druid.input @{Input} ---@param max_length number Maximum length for input text field ---@return druid.input Current input instance function druid__input.set_max_length(self, max_length) end --- Set text for input field ----@param self druid.input +---@param self druid.input @{Input} ---@param input_text string The string to apply for input field function druid__input.set_text(self, input_text) end --- Remove selection from input. ----@param self druid.input +---@param self druid.input @{Input} function druid__input.unselect(self) end @@ -583,42 +609,54 @@ local druid__input__style = {} ---@class druid.lang_text : druid.base_component ----@field on_change druid_event On change text callback ----@field text Text The text component +---@field on_change druid.event On change text callback +---@field text druid.text The text component local druid__lang_text = {} --- Format string with new text params on localized text ----@param self druid.lang_text ----@param ... string Locale arguments to pass in text function +---@param self druid.lang_text @{LangText} +---@param a string Optional param to string.format +---@param b string Optional param to string.format +---@param c string Optional param to string.format +---@param d string Optional param to string.format +---@param e string Optional param to string.format +---@param f string Optional param to string.format +---@param g string Optional param to string.format ---@return druid.lang_text Current instance -function druid__lang_text.format(self, ...) end +function druid__lang_text.format(self, a, b, c, d, e, f, g) end --- Component init function ----@param self druid.lang_text +---@param self druid.lang_text @{LangText} ---@param node node The text node ---@param locale_id string Default locale id or text from node as default ---@param no_adjust bool If true, will not correct text size function druid__lang_text.init(self, node, locale_id, no_adjust) end --- Setup raw text to lang_text component ----@param self druid.lang_text +---@param self druid.lang_text @{LangText} ---@param text string Text for text node ---@return druid.lang_text Current instance function druid__lang_text.set_to(self, text) end --- Translate the text by locale_id ----@param self druid.lang_text +---@param self druid.lang_text @{LangText} ---@param locale_id string Locale id ----@param ... string Locale arguments to pass in text function +---@param a string Optional param to string.format +---@param b string Optional param to string.format +---@param c string Optional param to string.format +---@param d string Optional param to string.format +---@param e string Optional param to string.format +---@param f string Optional param to string.format +---@param g string Optional param to string.format ---@return druid.lang_text Current instance -function druid__lang_text.translate(self, locale_id, ...) end +function druid__lang_text.translate(self, locale_id, a, b, c, d, e, f, g) end ---@class druid.progress : druid.base_component ---@field key string The progress bar direction ---@field max_size number Maximum size of progress bar ---@field node node Progress bar fill node ----@field on_change druid_event On progress bar change callback(self, new_value) +---@field on_change druid.event On progress bar change callback(self, new_value) ---@field scale vector3 Current progress bar scale ---@field size vector3 Current progress bar size ---@field slice vector4 Progress bar slice9 settings @@ -626,37 +664,37 @@ function druid__lang_text.translate(self, locale_id, ...) end local druid__progress = {} --- Empty a progress bar ----@param self druid.progress +---@param self druid.progress @{Progress} function druid__progress.empty(self) end --- Fill a progress bar and stop progress animation ----@param self druid.progress +---@param self druid.progress @{Progress} function druid__progress.fill(self) end --- Return current progress bar value ----@param self druid.progress +---@param self druid.progress @{Progress} function druid__progress.get(self) end --- Component init function ----@param self druid.progress +---@param self druid.progress @{Progress} ---@param node string|node Progress bar fill node or node name ---@param key string Progress bar direction: const.SIDE.X or const.SIDE.Y ---@param init_value number Initial value of progress bar function druid__progress.init(self, node, key, init_value) end --- Set points on progress bar to fire the callback ----@param self druid.progress +---@param self druid.progress @{Progress} ---@param steps number[] Array of progress bar values ---@param callback function Callback on intersect step value function druid__progress.set_steps(self, steps, callback) end --- Instant fill progress bar to value ----@param self druid.progress +---@param self druid.progress @{Progress} ---@param to number Progress bar value, from 0 to 1 function druid__progress.set_to(self, to) end --- Start animation of a progress bar ----@param self druid.progress +---@param self druid.progress @{Progress} ---@param to number value between 0..1 ---@param callback function Callback on animation ends function druid__progress.to(self, to, callback) end @@ -670,39 +708,58 @@ local druid__progress__style = {} ---@class druid.radio_group : druid.base_component ---@field checkboxes Checkbox[] Array of checkbox components ----@field on_radio_click druid_event On any checkbox click +---@field on_radio_click druid.event On any checkbox click local druid__radio_group = {} --- Return radio group state ----@param self druid.radio_group +---@param self druid.radio_group @{RadioGroup} ---@return number Index in radio group function druid__radio_group.get_state(self) end --- Component init function ----@param self druid.radio_group +---@param self druid.radio_group @{RadioGroup} ---@param nodes node[] Array of gui node ---@param callback function Radio callback ---@param click_nodes node[] Array of trigger nodes, by default equals to nodes function druid__radio_group.init(self, nodes, callback, click_nodes) end --- Set radio group state ----@param self druid.radio_group +---@param self druid.radio_group @{RadioGroup} ---@param index number Index in radio group ---@param is_instant boolean If is instant state change function druid__radio_group.set_state(self, index, is_instant) end +---@class druid.rich_input : druid.input +---@field cursor node On input field text change to empty string callback(self, input_text) +---@field druid druid_instance On input field select callback(self, button_node) +---@field input druid.input On input field text change callback(self, input_text) +---@field placeholder druid.text On input field text change to max length string callback(self, input_text) +local druid__rich_input = {} + +--- Component init function +---@param self druid.rich_input @{RichInput} +---@param template string The template string name +---@param nodes table Nodes table from gui.clone_tree +function druid__rich_input.init(self, template, nodes) end + +--- Set placeholder text +---@param self druid.rich_input @{RichInput} +---@param placeholder_text string The placeholder text +function druid__rich_input.set_placeholder(self, placeholder_text) end + + ---@class druid.scroll : druid.base_component ---@field available_pos vector4 Available position for content node: (min_x, max_y, max_x, min_y) ---@field available_size vector3 Size of available positions: (width, height, 0) ---@field content_node node Scroll content node ----@field drag Drag Drag Druid component +---@field drag druid.drag Drag Druid component ---@field inertion vector3 Current inert speed ---@field is_animate bool Flag, if scroll now animating by gui.animate ---@field is_inert bool Flag, if scroll now moving by inertion ----@field on_point_scroll druid_event On scroll_to_index function callback(self, index, point) ----@field on_scroll druid_event On scroll move callback(self, position) ----@field on_scroll_to druid_event On scroll_to function callback(self, target, is_instant) +---@field on_point_scroll druid.event On scroll_to_index function callback(self, index, point) +---@field on_scroll druid.event On scroll move callback(self, position) +---@field on_scroll_to druid.event On scroll_to function callback(self, target, is_instant) ---@field position vector3 Current scroll posisition ---@field selected number Current index of points of interests ---@field style druid.scroll.style Component style params. @@ -710,57 +767,53 @@ function druid__radio_group.set_state(self, index, is_instant) end ---@field view_node node Scroll view node local druid__scroll = {} ---- Cancel animation on other animation or input touch ----@param self unknown -function druid__scroll._cancel_animate(self) end - --- Bind the grid component (Static or Dynamic) to recalculate scroll size on grid changes ----@param self druid.scroll ----@param grid StaticGrid|DynamicGrid Druid grid component +---@param self druid.scroll @{Scroll} +---@param grid druid.static_grid|druid.dynamic_grid Druid grid component ---@return druid.scroll Current scroll instance function druid__scroll.bind_grid(self, grid) end --- Return current scroll progress status. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@return vector3 New vector with scroll progress values function druid__scroll.get_percent(self) end --- Return vector of scroll size with width and height. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@return vector3 Available scroll size function druid__scroll.get_scroll_size(self) end --- Scroll constructor ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param view_node node GUI view scroll node ---@param content_node node GUI content scroll node function druid__scroll.init(self, view_node, content_node) end --- Return if scroll have inertion. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@return bool If scroll have inertion function druid__scroll.is_inert(self) end --- Check node if it visible now on scroll. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param node node The node to check ---@return boolean True if node in visible scroll area function druid__scroll.is_node_in_view(self, node) end --- Start scroll to target point. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param point vector3 Target point ---@param is_instant bool Instant scroll flag function druid__scroll.scroll_to(self, point, is_instant) end --- Scroll to item in scroll by point index. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param index number Point index ---@param skip_cb bool If true, skip the point callback function druid__scroll.scroll_to_index(self, index, skip_cb) end --- Start scroll to target scroll percent ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param percent vector3 target percent ---@param is_instant bool instant scroll flag function druid__scroll.scroll_to_percent(self, percent, is_instant) end @@ -771,38 +824,38 @@ function druid__scroll.scroll_to_percent(self, percent, is_instant) end function druid__scroll.set_click_zone(self, node) end --- Set extra size for scroll stretching. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param stretch_size number Size in pixels of additional scroll area ---@return druid.scroll Current scroll instance function druid__scroll.set_extra_stretch_size(self, stretch_size) end --- Lock or unlock horizontal scroll ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param state bool True, if horizontal scroll is enabled ---@return druid.scroll Current scroll instance function druid__scroll.set_horizontal_scroll(self, state) end --- Enable or disable scroll inert. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param state bool Inert scroll state ---@return druid.scroll Current scroll instance function druid__scroll.set_inert(self, state) end --- Set points of interest. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param points table Array of vector3 points ---@return druid.scroll Current scroll instance function druid__scroll.set_points(self, points) end --- Set scroll content size. ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param size vector3 The new size for content node ---@param offset vector3 Offset value to set, where content is starts ---@return druid.scroll Current scroll instance function druid__scroll.set_size(self, size, offset) end --- Lock or unlock vertical scroll ----@param self druid.scroll +---@param self druid.scroll @{Scroll} ---@param state bool True, if vertical scroll is enabled ---@return druid.scroll Current scroll instance function druid__scroll.set_vertical_scroll(self, state) end @@ -829,7 +882,7 @@ local druid__scroll__style = {} ---@field end_pos vector3 End pin node position ---@field is_drag bool Current drag state ---@field node node Slider pin node ----@field on_change_value druid_event On change value callback(self, value) +---@field on_change_value druid.event On change value callback(self, value) ---@field pos vector3 Current pin node position ---@field start_pos vector3 Start pin node position ---@field target_pos vector3 Targer pin node position @@ -837,20 +890,20 @@ local druid__scroll__style = {} local druid__slider = {} --- Component init function ----@param self druid.slider +---@param self druid.slider @{Slider} ---@param node node Gui pin node ---@param end_pos vector3 The end position of slider ---@param callback function On slider change callback function druid__slider.init(self, node, end_pos, callback) end --- Set value for slider ----@param self druid.slider +---@param self druid.slider @{Slider} ---@param value number Value from 0 to 1 ---@param is_silent bool Don't trigger event if true function druid__slider.set(self, value, is_silent) end --- Set slider steps. ----@param self druid.slider +---@param self druid.slider @{Slider} ---@param steps number[] Array of steps function druid__slider.set_steps(self, steps) end @@ -862,88 +915,94 @@ function druid__slider.set_steps(self, steps) end ---@field last_index number The last index of node in grid ---@field node_size vector3 Item size ---@field nodes node[] List of all grid nodes ----@field on_add_item druid_event On item add callback(self, node, index) ----@field on_change_items druid_event On item add or remove callback(self, index) ----@field on_clear druid_event On grid clear callback(self) ----@field on_remove_item druid_event On item remove callback(self, index) ----@field on_update_positions druid_event On update item positions callback(self) +---@field on_add_item druid.event On item add callback(self, node, index) +---@field on_change_items druid.event On item add, remove or change in_row callback(self, index|nil) +---@field on_clear druid.event On grid clear callback(self) +---@field on_remove_item druid.event On item remove callback(self, index) +---@field on_update_positions druid.event On update item positions callback(self) ---@field parent node Parent gui node ---@field style druid.static_grid.style Component style params. local druid__static_grid = {} --- Add new item to the grid ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param item node Gui node ---@param index number The item position. By default add as last item ---@param shift_policy number How shift nodes, if required. See const.SHIFT ----@param is_instance boolean If true, update node positions instantly -function druid__static_grid.add(self, item, index, shift_policy, is_instance) end +---@param is_instant boolean If true, update node positions instantly +function druid__static_grid.add(self, item, index, shift_policy, is_instant) end --- Clear grid nodes array. ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@return druid.static_grid Current grid instance function druid__static_grid.clear(self) end --- Return array of all node positions ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@return vector3[] All grid node positions function druid__static_grid.get_all_pos(self) end --- Return grid content borders ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@return vector3 The grid content borders function druid__static_grid.get_borders(self) end --- Return index for grid pos ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param pos vector3 The node position in the grid ---@return number The node index function druid__static_grid.get_index(self, pos) end --- Return grid index by node ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param node node The gui node in the grid ---@return number The node index function druid__static_grid.get_index_by_node(self, node) end --- Return StaticGrid offset, where StaticGrid content starts. ----@param self druid.static_grid The StaticGrid instance +---@param self druid.static_grid @{StaticGrid} The StaticGrid instance ---@return vector3 The StaticGrid offset function druid__static_grid.get_offset(self) end --- Return pos for grid node index ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param index number The grid element index ---@return vector3 Node position function druid__static_grid.get_pos(self, index) end --- Return grid content size ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@return vector3 The grid content size function druid__static_grid.get_size(self) end --- Component init function ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param parent node The gui node parent, where items will be placed ---@param element node Element prefab. Need to get it size ---@param in_row number How many nodes in row can be placed function druid__static_grid.init(self, parent, element, in_row) end --- Remove the item from the grid. ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param index number The grid node index to remove ---@param shift_policy number How shift nodes, if required. See const.SHIFT ----@param is_instance boolean If true, update node positions instantly +---@param is_instant boolean If true, update node positions instantly ---@return Node The deleted gui node from grid -function druid__static_grid.remove(self, index, shift_policy, is_instance) end +function druid__static_grid.remove(self, index, shift_policy, is_instant) end --- Set grid anchor. ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param anchor vector3 Anchor function druid__static_grid.set_anchor(self, anchor) end +--- Set new in_row elements for grid +---@param self druid.static_grid @{StaticGrid} +---@param in_row number The new in_row value +---@return druid.static_grid Current grid instance +function druid__static_grid.set_in_row(self, in_row) end + --- Change set position function for grid nodes. ----@param self druid.static_grid +---@param self druid.static_grid @{StaticGrid} ---@param callback function Function on node set position ---@return druid.static_grid Current grid instance function druid__static_grid.set_position_function(self, callback) end @@ -958,18 +1017,18 @@ local druid__static_grid__style = {} ---@class druid.swipe : druid.base_component ---@field click_zone node Restriction zone ---@field node node Swipe node ----@field on_swipe druid_event Trigger on swipe event(self, swipe_side, dist, delta_time +---@field on_swipe druid.event Trigger on swipe event(self, swipe_side, dist, delta_time ---@field style druid.swipe.style Component style params. local druid__swipe = {} --- Component init function ----@param self druid.swipe +---@param self druid.swipe @{Swipe} ---@param node node Gui node ---@param on_swipe_callback function Swipe callback for on_swipe_end event function druid__swipe.init(self, node, on_swipe_callback) end --- Strict swipe click area. ----@param self druid.swipe +---@param self druid.swipe @{Swipe} ---@param zone node Gui node function druid__swipe.set_click_zone(self, zone) end @@ -986,9 +1045,9 @@ local druid__swipe__style = {} ---@field color vector3 Current text color ---@field node node Text node ---@field node_id hash The node id of text node ----@field on_set_pivot druid_event On change pivot callback(self, pivot) ----@field on_set_text druid_event On set text callback(self, text) ----@field on_update_text_scale druid_event On adjust text size callback(self, new_scale) +---@field on_set_pivot druid.event On change pivot callback(self, pivot) +---@field on_set_text druid.event On set text callback(self, text) +---@field on_update_text_scale druid.event On adjust text size callback(self, new_scale) ---@field pos vector3 Current text position ---@field scale vector3 Current text node scale ---@field start_scale vector3 Initial text node scale @@ -1004,61 +1063,61 @@ local druid__text = {} function druid__text.get_text_adjust(self, adjust_type) end --- Calculate text width with font with respect to trailing space ----@param self druid.text +---@param self druid.text @{Text} ---@param text string function druid__text.get_text_width(self, text) end --- Component init function ----@param self druid.text +---@param self druid.text @{Text} ---@param node node Gui text node ---@param value string Initial text. Default value is node text from GUI scene. ---@param adjust_type int Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference function druid__text.init(self, node, value, adjust_type) end --- Return true, if text with line break ----@param self druid.text +---@param self druid.text @{Text} ---@return bool Is text node with line break function druid__text.is_multiline(self) end --- Set alpha ----@param self druid.text +---@param self druid.text @{Text} ---@param alpha number Alpha for node ---@return druid.text Current text instance function druid__text.set_alpha(self, alpha) end --- Set color ----@param self druid.text +---@param self druid.text @{Text} ---@param color vector4 Color for node ---@return druid.text Current text instance function druid__text.set_color(self, color) end --- Set minimal scale for DOWNSCALE_LIMITED or SCALE_THEN_SCROLL adjust types ----@param self druid.text +---@param self druid.text @{Text} ---@param minimal_scale number If pass nil - not use minimal scale ---@return druid.text Current text instance function druid__text.set_minimal_scale(self, minimal_scale) end --- Set text pivot. ----@param self druid.text +---@param self druid.text @{Text} ---@param pivot gui.pivot Gui pivot constant ---@return druid.text Current text instance function druid__text.set_pivot(self, pivot) end --- Set scale ----@param self druid.text +---@param self druid.text @{Text} ---@param scale vector3 Scale for node ---@return druid.text Current text instance function druid__text.set_scale(self, scale) end --- Set text adjust, refresh the current text visuals, if needed ----@param self druid.text +---@param self druid.text @{Text} ---@param adjust_type number See const.TEXT_ADJUST. If pass nil - use current adjust type ---@param minimal_scale number If pass nil - not use minimal scale ---@return druid.text Current text instance function druid__text.set_text_adjust(self, adjust_type, minimal_scale) end --- Set text to text field ----@param self druid.text +---@param self druid.text @{Text} ---@param set_to string Text for node ---@return druid.text Current text instance function druid__text.set_to(self, set_to) end @@ -1073,15 +1132,15 @@ local druid__text__style = {} ---@class druid.timer : druid.base_component ---@field from number Initial timer value ---@field node node Trigger node ----@field on_set_enabled druid_event On timer change enabled state callback(self, is_enabled) ----@field on_tick druid_event On timer tick. ----@field on_timer_end druid_event On timer end callback +---@field on_set_enabled druid.event On timer change enabled state callback(self, is_enabled) +---@field on_tick druid.event On timer tick. +---@field on_timer_end druid.event On timer end callback ---@field target number Target timer value ---@field value number Current timer value local druid__timer = {} --- Component init function ----@param self druid.timer +---@param self druid.timer @{Timer} ---@param node node Gui text node ---@param seconds_from number Start timer value in seconds ---@param seconds_to number End timer value in seconds @@ -1089,18 +1148,18 @@ local druid__timer = {} function druid__timer.init(self, node, seconds_from, seconds_to, callback) end --- Set time interval ----@param self druid.timer +---@param self druid.timer @{Timer} ---@param from number Start time in seconds ---@param to number Target time in seconds function druid__timer.set_interval(self, from, to) end --- Called when update ----@param self druid.timer +---@param self druid.timer @{Timer} ---@param is_on bool Timer enable state function druid__timer.set_state(self, is_on) end --- Set text to text field ----@param self druid.timer +---@param self druid.timer @{Timer} ---@param set_to number Value in seconds function druid__timer.set_to(self, set_to) end @@ -1110,47 +1169,12 @@ function druid__timer.set_to(self, set_to) end local druid_const = {} ----@class druid_event -local druid_event = {} - ---- Clear the all event handlers ----@param self druid_event -function druid_event.clear(self) end - ---- Event constructur ----@param self druid_event ----@param initial_callback function Subscribe the callback on new event, if callback exist -function druid_event.initialize(self, initial_callback) end - ---- Return true, if event have at lease one handler ----@param self druid_event ----@return bool True if event have handlers -function druid_event.is_exist(self) end - ---- Subscribe callback on event ----@param self druid_event ----@param callback function Callback itself ----@param context table Additional context as first param to callback call -function druid_event.subscribe(self, callback, context) end - ---- Trigger the event and call all subscribed callbacks ----@param self druid_event ----@param ... any All event params -function druid_event.trigger(self, ...) end - ---- Unsubscribe callback on event ----@param self druid_event ----@param callback function Callback itself ----@param context table Additional context as first param to callback call -function druid_event.unsubscribe(self, callback, context) end - - ---@class druid_instance local druid_instance = {} --- Create data list basic component ---@param druid_scroll druid.scroll The Scroll instance for Data List component ----@param druid_grid druid.grid The Grid instance for Data List component +---@param druid_grid Grid The Grid instance for Data List component ---@param create_function function The create function callback(self, data, index, data_list). Function should return (node, [component]) ---@return druid.data_list data_list component function druid_instance.druid:new_data_list(druid_scroll, druid_grid, create_function) end @@ -1332,9 +1356,9 @@ function druid_instance.on_focus_lost(self) end ---@return bool The boolean value is input was consumed function druid_instance.on_input(self, action_id, action) end ---- Druid on layout change function. +--- Druid on language change. ---@param self druid_instance -function druid_instance.on_layout_change(self) end +function druid_instance.on_language_change(self) end --- Druid on_message function ---@param self druid_instance @@ -1348,6 +1372,16 @@ function druid_instance.on_message(self, message_id, message, sender) end ---@param component Component Component instance function druid_instance.remove(self, component) end +--- Set blacklist components for input processing. +---@param self druid_instance +---@param blacklist_components table|Component The array of component to blacklist +function druid_instance.set_blacklist(self, blacklist_components) end + +--- Set whitelist components for input processing. +---@param self druid_instance +---@param whitelist_components table|Component The array of component to whitelist +function druid_instance.set_whitelist(self, whitelist_components) end + --- Druid update function ---@param self druid_instance ---@param dt number Delta time diff --git a/config.ld b/config.ld index 7448c16d..daa7b5cd 100644 --- a/config.ld +++ b/config.ld @@ -4,13 +4,14 @@ 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={} use_markdown_titles=true -no_space_before_args=true \ No newline at end of file +no_space_before_args=true diff --git a/druid.code-workspace b/druid.code-workspace new file mode 100644 index 00000000..dab8d24e --- /dev/null +++ b/druid.code-workspace @@ -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 + } + } +} diff --git a/druid/base/back_handler.lua b/druid/base/back_handler.lua index e0af15cf..a97c7d87 100644 --- a/druid/base/back_handler.lua +++ b/druid/base/back_handler.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/base/blocker.lua b/druid/base/blocker.lua index d6aee61c..2097142b 100644 --- a/druid/base/blocker.lua +++ b/druid/base/blocker.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/base/button.lua b/druid/base/button.lua index 14f647bb..61c4db25 100755 --- a/druid/base/button.lua +++ b/druid/base/button.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/base/drag.lua b/druid/base/drag.lua index 18cf4f95..b51c1af4 100644 --- a/druid/base/drag.lua +++ b/druid/base/drag.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/base/hover.lua b/druid/base/hover.lua index e1b56f07..05aa0ac0 100644 --- a/druid/base/hover.lua +++ b/druid/base/hover.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 8134c465..865d65e5 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/base/static_grid.lua b/druid/base/static_grid.lua index ed674077..c32d4c0b 100644 --- a/druid/base/static_grid.lua +++ b/druid/base/static_grid.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 node item Gui node +-- @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 diff --git a/druid/base/swipe.lua b/druid/base/swipe.lua index f4fbbcdb..4a7e1727 100644 --- a/druid/base/swipe.lua +++ b/druid/base/swipe.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/base/text.lua b/druid/base/text.lua index c53df2d8..cbca90e7 100755 --- a/druid/base/text.lua +++ b/druid/base/text.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/component.lua b/druid/component.lua index b18e1a0a..7602b3f9 100644 --- a/druid/component.lua +++ b/druid/component.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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,9 +245,9 @@ 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 +-- @treturn BaseComponent BaseComponent itself function BaseComponent.set_input_enabled(self, state) self._meta.input_enabled = 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 = {} diff --git a/druid/const.lua b/druid/const.lua index c04896c0..c40fc582 100755 --- a/druid/const.lua +++ b/druid/const.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid constants -- @local diff --git a/druid/custom/pin_knob/pin_knob.gui b/druid/custom/pin_knob/pin_knob.gui new file mode 100644 index 00000000..63974606 --- /dev/null +++ b/druid/custom/pin_knob/pin_knob.gui @@ -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 diff --git a/druid/custom/pin_knob/pin_knob.lua b/druid/custom/pin_knob/pin_knob.lua new file mode 100644 index 00000000..7cb58585 --- /dev/null +++ b/druid/custom/pin_knob/pin_knob.lua @@ -0,0 +1,123 @@ +-- Copyright (c) 2022 Maksim Tuprikov . 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 diff --git a/druid/custom/rich_input/rich_input.gui b/druid/custom/rich_input/rich_input.gui new file mode 100644 index 00000000..b511cec5 --- /dev/null +++ b/druid/custom/rich_input/rich_input.gui @@ -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 diff --git a/druid/custom/rich_input/rich_input.lua b/druid/custom/rich_input/rich_input.lua new file mode 100644 index 00000000..feae3920 --- /dev/null +++ b/druid/custom/rich_input/rich_input.lua @@ -0,0 +1,95 @@ +-- Copyright (c) 2022 Maksim Tuprikov . 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 diff --git a/druid/druid.lua b/druid/druid.lua index a8204c3a..ed5303fc 100644 --- a/druid/druid.lua +++ b/druid/druid.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid UI Library. -- Powerful Defold component based UI library. Use standart diff --git a/druid/event.lua b/druid/event.lua index 0a3373a1..2500a2ca 100644 --- a/druid/event.lua +++ b/druid/event.lua @@ -1,8 +1,8 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/extended/checkbox.lua b/druid/extended/checkbox.lua index 6ce29a10..59919535 100755 --- a/druid/extended/checkbox.lua +++ b/druid/extended/checkbox.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/extended/checkbox_group.lua b/druid/extended/checkbox_group.lua index a9fbefe5..2ca95616 100644 --- a/druid/extended/checkbox_group.lua +++ b/druid/extended/checkbox_group.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 = {} diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua index 2f9f736c..b216cbb5 100644 --- a/druid/extended/data_list.lua +++ b/druid/extended/data_list.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua index f22b564c..05937152 100644 --- a/druid/extended/dynamic_grid.lua +++ b/druid/extended/dynamic_grid.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 node node Gui node +-- @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 diff --git a/druid/extended/input.lua b/druid/extended/input.lua index e1cc2faa..6a60a40f 100755 --- a/druid/extended/input.lua +++ b/druid/extended/input.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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() diff --git a/druid/extended/lang_text.lua b/druid/extended/lang_text.lua index b8018903..f30b48a7 100755 --- a/druid/extended/lang_text.lua +++ b/druid/extended/lang_text.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 } diff --git a/druid/extended/progress.lua b/druid/extended/progress.lua index e1ddaf09..1ebe6e78 100644 --- a/druid/extended/progress.lua +++ b/druid/extended/progress.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/extended/radio_group.lua b/druid/extended/radio_group.lua index 7ff0a4d9..fef1d007 100644 --- a/druid/extended/radio_group.lua +++ b/druid/extended/radio_group.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/extended/slider.lua b/druid/extended/slider.lua index b5a3198a..11f2a625 100644 --- a/druid/extended/slider.lua +++ b/druid/extended/slider.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/extended/timer.lua b/druid/extended/timer.lua index 307e7c01..21ac56bc 100644 --- a/druid/extended/timer.lua +++ b/druid/extended/timer.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/helper.lua b/druid/helper.lua index 38e2b361..c3ffe747 100644 --- a/druid/helper.lua +++ b/druid/helper.lua @@ -1,7 +1,8 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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 diff --git a/druid/helper/druid_input.lua b/druid/helper/druid_input.lua index 3d9f710a..deb64f14 100644 --- a/druid/helper/druid_input.lua +++ b/druid/helper/druid_input.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid inner module to acquire/release input -- @module helper.input diff --git a/druid/helper/formats.lua b/druid/helper/formats.lua index 44ba2f65..9d00cf4a 100644 --- a/druid/helper/formats.lua +++ b/druid/helper/formats.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid module with utils on string formats -- @local diff --git a/druid/styles/default/anims.lua b/druid/styles/default/anims.lua index 7c07b395..6f13a308 100644 --- a/druid/styles/default/anims.lua +++ b/druid/styles/default/anims.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license local M = {} diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua index 25886363..bd18a784 100644 --- a/druid/styles/default/style.lua +++ b/druid/styles/default/style.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license local const = require("druid.const") local settings = require("druid.system.settings") diff --git a/druid/styles/default/templates/druid_button_blue.gui b/druid/styles/default/templates/druid_button_blue.gui new file mode 100644 index 00000000..ee5a4d8b --- /dev/null +++ b/druid/styles/default/templates/druid_button_blue.gui @@ -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 diff --git a/druid/styles/default/templates/druid_button_green.gui b/druid/styles/default/templates/druid_button_green.gui new file mode 100644 index 00000000..c47e8f03 --- /dev/null +++ b/druid/styles/default/templates/druid_button_green.gui @@ -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 diff --git a/druid/styles/default/templates/druid_button_red.gui b/druid/styles/default/templates/druid_button_red.gui new file mode 100644 index 00000000..31bd89b4 --- /dev/null +++ b/druid/styles/default/templates/druid_button_red.gui @@ -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 diff --git a/druid/styles/default/templates/druid_button_yellow.gui b/druid/styles/default/templates/druid_button_yellow.gui new file mode 100644 index 00000000..6d1ca819 --- /dev/null +++ b/druid/styles/default/templates/druid_button_yellow.gui @@ -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 diff --git a/druid/styles/default/templates/druid_checkbox.gui b/druid/styles/default/templates/druid_checkbox.gui new file mode 100644 index 00000000..a78ed62e --- /dev/null +++ b/druid/styles/default/templates/druid_checkbox.gui @@ -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 diff --git a/druid/styles/default/templates/druid_input.gui b/druid/styles/default/templates/druid_input.gui new file mode 100644 index 00000000..71dbf6b8 --- /dev/null +++ b/druid/styles/default/templates/druid_input.gui @@ -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 diff --git a/druid/styles/default/templates/druid_slider.gui b/druid/styles/default/templates/druid_slider.gui new file mode 100644 index 00000000..f6b9c41e --- /dev/null +++ b/druid/styles/default/templates/druid_slider.gui @@ -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 diff --git a/druid/styles/empty/style.lua b/druid/styles/empty/style.lua index fa863e01..2eec3eeb 100644 --- a/druid/styles/empty/style.lua +++ b/druid/styles/empty/style.lua @@ -1,3 +1,3 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license return {} diff --git a/druid/styles/sprites/style.lua b/druid/styles/sprites/style.lua index 932d7a15..260ff2d0 100644 --- a/druid/styles/sprites/style.lua +++ b/druid/styles/sprites/style.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license local M = {} diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index 024cfa95..dc69876f 100755 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . 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) diff --git a/druid/system/settings.lua b/druid/system/settings.lua index 1ac9763a..cc7064a0 100755 --- a/druid/system/settings.lua +++ b/druid/system/settings.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2021 Maxim Tuprikov . This code is licensed under MIT license +-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid settings file -- @module settings diff --git a/druid/templates/component.template.lua b/druid/templates/component.template.lua new file mode 100644 index 00000000..85a6f640 --- /dev/null +++ b/druid/templates/component.template.lua @@ -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 diff --git a/druid/extended/component.template.lua b/druid/templates/component_full.template.lua similarity index 64% rename from druid/extended/component.template.lua rename to druid/templates/component_full.template.lua index 2d0c8ed9..1e994d2b 100644 --- a/druid/extended/component.template.lua +++ b/druid/templates/component_full.template.lua @@ -1,15 +1,28 @@ --- Copyright (c) 2021 Maxim Tuprikov . 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 diff --git a/editor_scripts/component.lua_template b/editor_scripts/component.lua_template new file mode 100644 index 00000000..eb70a9d4 --- /dev/null +++ b/editor_scripts/component.lua_template @@ -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 +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} diff --git a/editor_scripts/create_druid_component.py b/editor_scripts/create_druid_component.py new file mode 100644 index 00000000..0b7c155c --- /dev/null +++ b/editor_scripts/create_druid_component.py @@ -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() diff --git a/editor_scripts/create_druid_component.sh b/editor_scripts/create_druid_component.sh new file mode 100644 index 00000000..56e44f16 --- /dev/null +++ b/editor_scripts/create_druid_component.sh @@ -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 $@ diff --git a/editor_scripts/gui_scheme.editor_script b/editor_scripts/gui_scheme.editor_script index fbcc0257..3619d60e 100644 --- a/editor_scripts/gui_scheme.editor_script +++ b/editor_scripts/gui_scheme.editor_script @@ -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 diff --git a/editor_scripts/setup_layers.sh b/editor_scripts/setup_layers.sh index 36c76c14..96a46171 100755 --- a/editor_scripts/setup_layers.sh +++ b/editor_scripts/setup_layers.sh @@ -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 $@ \ No newline at end of file +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 $@ diff --git a/example/assets/images/kenney.atlas b/example/assets/images/kenney.atlas index 622bf0db..31a9f7ba 100644 --- a/example/assets/images/kenney.atlas +++ b/example/assets/images/kenney.atlas @@ -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 diff --git a/example/example.collection b/example/example.collection index dfca9af1..113d549d 100644 --- a/example/example.collection +++ b/example/example.collection @@ -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 + } +} diff --git a/example/example.gui b/example/example.gui index a6be5e94..f613534e 100644 --- a/example/example.gui +++ b/example/example.gui @@ -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" diff --git a/example/example.gui_script b/example/example.gui_script index c7642bc7..1967e438 100644 --- a/example/example.gui_script +++ b/example/example.gui_script @@ -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 diff --git a/example/examples/custom/pin_knob/pin_knob.collection b/example/examples/custom/pin_knob/pin_knob.collection new file mode 100644 index 00000000..2698ebf7 --- /dev/null +++ b/example/examples/custom/pin_knob/pin_knob.collection @@ -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 + } +} diff --git a/example/examples/custom/pin_knob/pin_knob.gui b/example/examples/custom/pin_knob/pin_knob.gui new file mode 100644 index 00000000..d20d64f9 --- /dev/null +++ b/example/examples/custom/pin_knob/pin_knob.gui @@ -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 diff --git a/example/examples/custom/pin_knob/pin_knob.gui_script b/example/examples/custom/pin_knob/pin_knob.gui_script new file mode 100644 index 00000000..cd812048 --- /dev/null +++ b/example/examples/custom/pin_knob/pin_knob.gui_script @@ -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 diff --git a/example/examples/custom/rich_input/rich_input.collection b/example/examples/custom/rich_input/rich_input.collection new file mode 100644 index 00000000..c836cedf --- /dev/null +++ b/example/examples/custom/rich_input/rich_input.collection @@ -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 + } +} diff --git a/example/examples/custom/rich_input/rich_input.gui b/example/examples/custom/rich_input/rich_input.gui new file mode 100644 index 00000000..51c3ec72 --- /dev/null +++ b/example/examples/custom/rich_input/rich_input.gui @@ -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 diff --git a/example/examples/custom/rich_input/rich_input.gui_script b/example/examples/custom/rich_input/rich_input.gui_script new file mode 100644 index 00000000..73fe666f --- /dev/null +++ b/example/examples/custom/rich_input/rich_input.gui_script @@ -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 diff --git a/example/examples/general/sliders/sliders.gui b/example/examples/general/sliders/sliders.gui index 86f1ab63..2f634764 100644 --- a/example/examples/general/sliders/sliders.gui +++ b/example/examples/general/sliders/sliders.gui @@ -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" diff --git a/example/examples/general/sliders/sliders.gui_script b/example/examples/general/sliders/sliders.gui_script index 3b9aa1a4..bf196e33 100644 --- a/example/examples/general/sliders/sliders.gui_script +++ b/example/examples/general/sliders/sliders.gui_script @@ -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 diff --git a/example/examples/system/inner_templates/inner_button.gui b/example/examples/system/inner_templates/inner_button.gui new file mode 100644 index 00000000..ab6ecf66 --- /dev/null +++ b/example/examples/system/inner_templates/inner_button.gui @@ -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 diff --git a/example/examples/system/inner_templates/inner_button.lua b/example/examples/system/inner_templates/inner_button.lua new file mode 100644 index 00000000..644152c3 --- /dev/null +++ b/example/examples/system/inner_templates/inner_button.lua @@ -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 diff --git a/example/examples/system/inner_templates/inner_panel.gui b/example/examples/system/inner_templates/inner_panel.gui new file mode 100644 index 00000000..7ee8b412 --- /dev/null +++ b/example/examples/system/inner_templates/inner_panel.gui @@ -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 diff --git a/example/examples/system/inner_templates/inner_panel.lua b/example/examples/system/inner_templates/inner_panel.lua new file mode 100644 index 00000000..85895da5 --- /dev/null +++ b/example/examples/system/inner_templates/inner_panel.lua @@ -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 diff --git a/example/examples/system/inner_templates/inner_templates.collection b/example/examples/system/inner_templates/inner_templates.collection new file mode 100644 index 00000000..920c807d --- /dev/null +++ b/example/examples/system/inner_templates/inner_templates.collection @@ -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 + } +} diff --git a/example/examples/system/inner_templates/inner_templates.gui b/example/examples/system/inner_templates/inner_templates.gui new file mode 100644 index 00000000..8bbd35eb --- /dev/null +++ b/example/examples/system/inner_templates/inner_templates.gui @@ -0,0 +1,1011 @@ +script: "/example/examples/system/inner_templates/inner_templates.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 + custom_type: 0 +} +nodes { + position { + x: -125.0 + y: 150.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_panel" + parent: "root" + layer: "" + inherit_alpha: true + alpha: 1.0 + template: "/example/examples/system/inner_templates/inner_panel.gui" + template_node_child: false + 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: 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_panel/root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel" + 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 + 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: 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: "inner_panel/background" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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: true + size_mode: SIZE_MODE_MANUAL + custom_type: 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_panel/inner_button_1" + parent: "inner_panel/root" + layer: "" + inherit_alpha: true + alpha: 1.0 + template: "/example/examples/system/inner_templates/inner_button.gui" + template_node_child: true + 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: 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_panel/inner_button_1/root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + 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: 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_panel/inner_button_1/button" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + custom_type: 0 +} +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_panel/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_panel/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 + 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: 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_panel/inner_button_2" + parent: "inner_panel/root" + layer: "" + inherit_alpha: true + alpha: 1.0 + template: "/example/examples/system/inner_templates/inner_button.gui" + template_node_child: true + 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: 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_panel/inner_button_2/root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + 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: 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_panel/inner_button_2/button" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + custom_type: 0 +} +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_panel/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_panel/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 + custom_type: 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_panel/inner_button_prefab" + parent: "inner_panel/root" + layer: "" + inherit_alpha: true + alpha: 1.0 + template: "/example/examples/system/inner_templates/inner_button.gui" + template_node_child: true + 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: 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_panel/inner_button_prefab/root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + 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: 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_panel/inner_button_prefab/button" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "inner_panel/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 + custom_type: 0 +} +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_panel/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_panel/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 + custom_type: 0 +} +nodes { + position { + x: -125.0 + y: 350.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: 400.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: "Template from scene" + font: "game" + id: "text_hint_1" + 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: true + parent: "root" + 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 + custom_type: 0 +} +nodes { + position { + x: 125.0 + y: 350.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: 400.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: "Template from gui.clone_tree" + font: "game" + id: "text_hint_2" + 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: true + parent: "root" + 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 + custom_type: 0 +} +layers { + name: "image" +} +layers { + name: "text" +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT +max_nodes: 512 diff --git a/example/examples/system/inner_templates/inner_templates.gui_script b/example/examples/system/inner_templates/inner_templates.gui_script new file mode 100644 index 00000000..b8c65327 --- /dev/null +++ b/example/examples/system/inner_templates/inner_templates.gui_script @@ -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 diff --git a/game.project b/game.project index e38280c4..221b23d5 100644 --- a/game.project +++ b/game.project @@ -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 diff --git a/settings_deployer b/settings_deployer index cbc62f3d..36568b59 100644 --- a/settings_deployer +++ b/settings_deployer @@ -1,4 +1,4 @@ #!/bin/bash use_latest_bob=false enable_incremental_version=true -bob_sha="187:581c6439ae93755a8a6bcf58732c39c724fa193c" +bob_sha="3.0:0e77ba11ac957ee01878bbde2e6ac0c9fae6dc01"