I am working on my own implementation, wanted to know what is a better approach.
is it a good approach to reposition out of the grid node again. I mean, while scroll down repositions top nodes again to the bottom, will it be quick enough and smooth in functionality.
or any other approach you want to suggest?
I think reposition is the best way, but my solution is delete nodes outside and re-create it again. Since Defold is static engine this is good enough too (but much easier for use)
You can create your component in any of ways, it should be ok
Besides a lot of fixes (thanks for feedback!) two components was add: StaticGrid and DynamicGrid instead of usual Grid component (it is deprecated now).
Add component:set_input_enabled for basic component class. So you can enable/disable user input for any component.
Finally implemented on_layout_changed support. Druid components now will try keep their data between layout changing! You also can use this callback in your custom components.
Also check component.template.lua what you can use for your own custom components!
#77 Grid update:
The grid component now is deprecated. Use static_grid instead. Druid will show you deprecated message, if you still using grid component
[BREAKING] Remove the grid:set_offset grid functions. To adjust the distance between nodes inside grid - setup correct node sizes
Add static_grid component
The behaviour like previous grid component
Have constant element size, so have ability to precalculate positions, indexes and size of content
By default, not shifting elements on removing element. Add is_shift flag to static_grid:remove function
This grid can spawn elements with several rows and columns
Add dynamic_grid component
Can have different element size. So have no ability to precalculate stuff like static_grid
This grid canât have gaps between elements. You will get the error, if spawn element far away from other elements
The grid can spawn elements only in row or in column
The grid node should have West, East, South or North pivot (vertical or horizontal element placement)
Able to shift nodes left or right on grid:add / grid:remove functions
Scroll update:
Add scroll:set_vertical_scroll and scroll:set_horizontal_scroll for disable scroll sides
Add scroll:bind_grid function. Now is possible to bind Druid Grid component (Static or Dynamic) to the scroll for auto refresh the scroll size on grid nodes changing
#37 Add on_layout_change support. Druid will keep and restore GUI component data between changing game layout. Override function on_layout_change in your custom components to do stuff you need.
#85 Move several components from base folder to extended. In future to use them, you have to register them manually. This is done for decrease build size by excluding unused components
Fix #88: Add component:set_input_enabled function to enable/disable input for druid component. Now you can disable input of any druid component, even complex (with other components inside)
Add component.template.lua as template for Druid custom component
Awesome work, really impressive.
I have a question about the list/grid components.
Does it reuse the nodes (similar to a recyclerview in native Android)? I mean does it support a 100K item list or do we have to keep the number of items under the max sprites/nodes allowed?
Currently no, there is no druid solution for infinity scroll
Above we talked about this. In next Druid release will be added extended component to handle scroll with huge amount of data. Current release with grids is preparing for this.
Hello,
Thanks for the quick changes and dynamic grid,
it seems there is an issue with dynamic_grid added into the scroller, if the prefab_dynamic box component has some nested box component or text component, the nested component is not visible in the scroller,
I the example project, I also tried adding grid_nodes_prefab to grid_dynamic_view however its only showing the parent box of grid_nodes_prefab and not showing inner component that is grid_nodes_dot.
is anything else I need to try?
Thanks
Itâs seems not the Druid issue, but gui node management.
In Druid Example, create function just make gui.clone of the prefab node. For your case, you should do gui.clone_tree and do your stuff with gui nodes tree
Hey! Are you tired from Druid updates? (Itâs a joke)
Finally, got a time to release component to process huge amount of data. So introducing: DataList component. It can help solve your problem with GUI nodes limit reached and helps with scroll optimization. Give feedback about it!
The next important stuff is EmmyLua docs. Iâm implemented EmmyLua doc generator from LuaDoc and Protofiles, so now you can use EmmyLua annotations inside your IDE instead of website API looking or source code scanning.
Also the Druid examples is reworked, so each example will be in separate collection. Now itâs become a much easier to learn Druid via examples. A lot of stuff in progress now, but you already can see on it!
Input priority got reworked too. Now instead of two input stacks: usual and high, Druid use simple input priority value.
And I should note here are several breaking changes, take a look in changelogs.
#43 Add DataList Druid extended component. Component used to manage huge amount of data to make stuff like infinity scroll.
This versions is first basic implementation. But it should be enough for almost all basic stuff.
Create Data List with druid:new_data_list(scroll, grid, create_function).
scroll - already created Scroll component
grid - already created StaticGrid or DynamicGrid component
create_function - your function to create node instances. This callback have next parameters: fun(self, data, index, data_list)
self - Script/Druid context
data- your element data
index - element index
data_list - current DataList component
Create function should return root node and optionaly, Druid component. Itâs required to manage create/remove lifecycle
Set data with data_list:set_data({...})
In current version there is no add/remove functions
Add EmmyLua annotations (ta-daaa). See how to use it FAQ!
Add context argument to Druid Event. You can pass this argument to forward it first in your callbacks (for example - object context)
Add SHIFT_POLICY for Static and Dynamic Grids. It mean how nodes will be shifted if you append data between nodes. There are const.SHIFT.RIGHT, const.SHIFT.LEFT and const.SHIFT.NO_SHIFT.
[BREAKING] Please check your StaticGrid:remove and DynamicGrid:remove functions
#102[BREAKING] Removed component:increase_input_priority component function. Use component:set_input_priority function instead. The bigger priority value processed first. The value 10 is default for Druid components, the 100 value is maximum priority for acquire input in drag and input components
Add constants for priorities: const.PRIORITY_INPUT, const.PRIORITY_INPUT_HIGH, const.PRIORITY_INPUT_MAX.
[BREAKING] If you use in you custom components interest: component.ON_INPUT_HIGH you should replace it with component.ON_INPUT and add const.PRIORITY_INPUT_HIGH as third param. For example: before:
local Drag = component.create("drag", { component.ON_INPUT_HIGH })
after:
local Drag = component.create("drag", { component.ON_INPUT }, const.PRIORITY_INPUT_HIGH)
Lang text now can be initialized without default locale id
Input component: rename field selected to is_selected (according to the docs)
#92 Setup repo for CI and unit tests. (Yea, successful build and tests badges!)
#86 Fix a lot of event triggers on scroll inertia moving
#101 Fix scroll to other node instead of swipe direction with scrollâs points of interest (without inert settings)
#103 Add helper.centate_nodes function. It can horizontal align several Box and Text nodes
#105 Add Input:select and Input:unselect function.
#106 Add Input.style.IS_UNSELECT_ON_RESELECT style param. If true, it will be unselect input on click on input box, not only on outside click.
#108 Add component interests const to component.lua
#116 You can pass Text component in Input component instead of text node
#117 Move each Druid example in separate collection. Itâs a lot of easier now to learn via examples, check it!
Examples in progress, so a lot of stuff are locked now, stay tuned!
#118 Druid.scroll freezes if held in one place for a long time
#123 Add scroll for Scroll component via mouse wheel or touchpad:
What would be the best way to hook in animations â specifically, Iâm looking to add some animation when items are added to a grid, e.g. like theyâre cards being dealt out.
If it requires modifying the druid code, thatâs fine, but Iâm not exactly sure where to look, as I wasnât able to find anything in the examples or documentation
Usually, for some animations like you say, I just run animations after adding elements to the grid (card appear, leaderboards, etc)
If you need animation before element deletion, I just call grid.remove in the end of this animation.
If this case is not suit for you, I need more information what you want
so, like I said above, right now Iâm trying to basically do a card-dealing animation when the elements are added to the grid. I did eventually find the on_add_item event, which seems like exactly what I want, but only the last one is being animated. Hereâs my preliminary attempt:
Yea, I got the your problem. The reason is what Grid component is manage their nodes position. So after add/update/remove any element, Grid will update all their element positions. Your callback is right, but after add element all previous position is updated.
The correct way is manage position inside the root node of added elements. You can add root node (which added to Grid component) and inside root node the position_anchor node to make animations.
Iâve add the example you can check (yea, now with deep linking!)
Hi @Insality,
I use Druid library in my project and I have some issues regarding Scroll with POIs.
The powerful scroll of grid to the edge position causes a delay by stretching.
Delay depends from scroll âpowerâ.
It seems an inertion and stretching working parallel and stretching waits until inertion routine returns the see point back into stretching area and then grid will be moved to the end position through stretching program.
Both issues can be re-produced with your default example.
Perhaps I do something wrong , but I would like to use both stretching and inertion by this scroll.
Hello! Here Iâm again with new Druid stuff for you!
The feature I want a long time to deliver for you: the different Text size adjust modes. Druid use the text node sizes to fit the text into this box.
There are new adjust modes such as Trim, Scroll, Downscale with restrictions and Downscale + Scroll. You can change default adjust mode via text style table, but by default there is no changes - itâs downscale adjust mode as before.
Iâll hope it can be useful for you for in different cases and now it will be much easy to fit all your texts for different languages!
The next features is made for add more control for availability of user input. So meet the whitelists, blacklists and custom check functions for Buttons. Now you can easily choose the more suitable way to enable/disable/restrict input for you users. Iâm sure it can be useful for you tutorials.
Another small, but cool feature on my mind is druid.stencil_check. If you did interactive elements inside the Scroll, probably you used component:set_click_zone to restrict input zone by stencil scroll view node. With this feature, Druid will do it automaticaly for you! You can enable this feature in your game.project. It will not override you existing set_click_zone calls.
Now you even able to remap default input keys! Also there are several bugfixes with Scroll, Text, Grids.
const.TEXT_ADJUST.DOWNSCALE - Change textâs scale to fit in the text node size
const.TEXT_ADJUST.TRIM - Trim the text with postfix (default - ââŚâ, override in styles) to fit in the text node size
const.TEXT_ADJUST.NO_ADJUST - No any adjust, like default Defold text node
const.TEXT_ADJUST.DOWNSCALE_LIMITED - Change textâs scale list downscale, but there is limit for textâs scale
const.TEXT_ADJUST.SCROLL - Change textâs pivot to imitate scrolling in the text box. Use with stencil node for better effect.
const.TEXT_ADJUST.SCALE_THEN_SCROLL - Combine two modes: first limited downscale, then scroll
#110 [Button] Add Button:set_check_function(check_function, failure_callback) function to add your custom click condition to button.
Button:set_enabled has more priority than this to check button availability
The check_function should return true of false. If true - button can be clicked by user
The failure_callback will be called if check_function will return false
Example with set_check_function in general:buttons example collection
#66 Add druid:set_whitelist() and druid.set_blacklist() functions. Itâs affects only on input process step, you can allow/forbid interact with list of specific components
You can pass array of components, single component or nil in these functions
#111 Add autocheck for input and stencil nodes. To enable this feature, add druid.stencil_check = 1 to your game.project file.
This feature is using for auto setup component:set_click_zone to restrict clicks outside scrolls zone for example. Now you can donât think about click zone and let Druid do it instead of you!
Add helper.get_closest_stencil_node function to get closest parent of non inverted stencil node
Add component.ON_LATE_INIT interest. Component with this will call component.on_late_init function once after component init on update step. This can be used to do something after all gui components are inited
#81 Add ability to interact with Druid input via messages:
Currently add for Button and Text component only:
Send to gui.script message: druid_const.ON_MESSAGE_INPUT. The message table params:
node_id - the name of the node with component on it
action - value from druid_const.MESSAGE_INPUT. Available values:
Implement new interest via function component:on_message_input(node_id, message)
See System: Message input example
#131 [Static Grid] Add style param: IS_DYNAMIC_NODE_POSES (default: false). Always align by content size with node anchor.
If true - Static Grid will by always align to content anchor.
If false (currently behaviour) - all poses for static grid is predefined and not depends on elementâs count (see example: static grid and static grid with dynamic poses)
#125 Now component:set_input_priority() affects on all componentâs children too
#143 Update all lang components on druid.set_text_function call
#112 Allow remap default Druid input bindings via game.project
#107 [Text] Better scale text adjust by height for multiline text nodes (but still not perfect)
#144 [Scroll] Fix some glitches with scroll Points of Interest. Remove false detection of scroll stopped.
#142 [Scroll] Add Scroll style param WHEEL_SCROLL_BY_INERTION (default - false). If true - mouse wheel will add inertion to scroll, if false - set position directly per mouse wheel event.
This fix caused because Mac trackpad seems have additional mouse wheel events for simulate inertion. If you uncomfortable with this, you can disable WHEEL_SCROLL_BY_INERTION for more controllable scroll by mouse wheel.
#132 Add example with grid add/remove with animations
I can get the timer to appear on the gui, but it remains static at the initial value - it doesnât tick down.
I have a main.collection and a main_menu.gui.
I have two scripts - main_controller.script which performs the functions of the app, and main_menu.gui.script that handles the user input. The gui script passes messages to the main_controller.script when there is user input (there are 12 gui nodes in total). Itâs a very simple project as I am pretty new to Defold.
When the app loads the timer value loads successfully in the gui node as pass as a parameter, but then it fails to change.
In this Druid update no any huge special features. Mostly the bug fixes and reworking the componentâs interest points. If you used interests in your custom components, you should remove it from component.create and all should works as before.
The component interests now setup via function declaration inside your components. The functions are still the same.
Now component.create function have next signature: create(component_name, input_priority)
Your should remove interests list from your custom components if exists
From component.create("custom", { component.ON_INPUT, component.ON_LATE_INIT }, const.PRIORITY_INPUT_HIGH) to component.create("custom", const.PRIORITY_INPUT_HIGH)
#166 [Input] Fix issue with Cyrillic symbols in range â[Đ-Ń]â
#162 [Static Grid] Add last row alignment with dynamic content poses enabled
Add style param: static_grid.IS_ALIGN_LAST_ROW, true by default. Works only if static_grid.IS_DYNAMIC_NODE_POSES enabled. See the âStatic grid with dynamic posesâ example.
#163 [Lang Text] Set default locale_id value from text node
#147 [Lang Text] Remove ... from lang_text to fixed arguments, add format function to change only string format arguments
There are some issues with .... Now Lang Text will support up to 7 string.format arguments
[Lang Text] Add more self chaining to Lang text component (set_to, translate and format functions)
#151 [Text] Fix text adjust by height
It still have not perfect fitting, but itâs good enough!
#164#150 [Scroll] Fix scroll:scroll_to_percent by Y position
#148 [Scroll] Remove scroll inertion after scroll animate or set_to functions
[Input] Add current text argument to on_input_unselect event
#152 [Checkbox] Add is_instant argument to set_state function
Add initial_state argument to Checkbox component constructor
Update Checkbox style, add is_instant param
#149 [Button] Call button style functions after actual callback
#153 System: Move Druid acquire input to late_init step
Required to solve issues, when go input acquire can be later, when gui input acquire (on init step)
#154 System: Change text adjust const to strings
#155 Fix: Add margin to total width calculation in helper.centrate_nodes
Here is the long awaited update! Finally I implemented some ideas how to make easier creating custom components. There is a bunch of improvements you can be interested in.
I wanna make a point that Druid is not only set of defined components to place buttons, scroll, etc. But mostly itâs a way how to handle all your GUI elements in general. Custom components is most powerful way to separate logic and make higher abstraction in your code.
Usually - custom components is set of GUI template and lua code for this template. Iâve added editor script, that can make a lua component file from your GUI scene (all boilerplate and usage code, also some component that can be defined right in GUI scene).
Auto layout from GUI script should be a powerful tool too! Also itâs brings some code structure and style across all your files. Auto layout works from node names. If its starts or equal to some string, it will add code to generated lua file. For example, if you have in your scene node with name âbutton_startâ, it will create the Druid button, stub function and annotations to this. Sounds good!
Also this update have some breaking changes: you should no more pass full tempalte name in inner components and the second one is renaming text:get_text_width to text:get_text_size.
The Defold 1.3.0 solves the old my issue with slider component. Now you can define input zone (not only the slider pin node) to interact with slider. Itâs because of inroduction gui.screen_to_local and gui.set_screen_position in default GUI api. If you using previuos Defold releases, this piece of logic will be ignored.
The Druid Assets repository will be closed and I move some components right in Druid repository. You can now use custom components in your game if your need. Right now itâs Rich Input (input field with cursor and placegolder) and Pin Knob (Rotating node for set value). And slowly working on adding new examples and improvements of existing ones.
You can say thanks to me via stars on GitHub !
Also you can help with testing new functions and leave feedback.
Wanna something more? Add an issues!
The headliner of current update. This editor scripts allows you to create Custom component lua script from you .gui scene file. It will create component file with the same name as GUI scene and place it nearby. Inside this generated file you will find the instructions how to start usage this (require and create code).
This code contains GUI scheme, basic component boilerplace and generated code for components, used in this GUI scene (see #159)
#159 Add auto layout custom components by node naming
The Create Druid Component script will check the node names to create Druid components stubs inside generated code
The generator will check the node name, if itâs starts from special prefix, it will create component code for you
Currently support the next components: button, text, lang_text, grid, static_grid, dynamic_grid, scroll_view, blocker, slider, progress and timer
#158[BREAKING] Auto get_node inside inner components with template/nodes
Before this update, if your component with template using another component with template, you had to pass full template name (current_template .. "/" .. inner_component_template). From this update you should pass only the inner_component_template name. Itâs will auto check the parent component template name to build full template path
If you donât want migrate code for this, this option can be disabled via druid.no_auto_template in your game.project file. By default itâs enabled now
#171 Add component:get_template() function to Druid Base Component
Now itâs able to get full component template name. This function has âprotectedâ scope, so you should use it only inside your component code.
#173 Fix GUI nodes usage inside inner templates
Now you can pass the node name instead of node itself to Druid components inside your Custom Components. Before this update Druid didnât check the nodes in parent component (usually for basic components such as button, text inside your components)
So you can use now self.druid:new_button(SCHEME.BUTTON) instead of self.druid:new_button(self:get_node(SCHEME.BUTTON)) inside your custom components
#174 Add assert to nil node on self:get_node()
Itâs required for easier debuging components, when GUI node path is wrong and your got the nil. The error with node path will appear in console.
#169 [System] Fix on_layout_change event
It was broken, now the on_layout_change event is working as expected
#165 [StaticGrid] Add static_grid:set_in_row(amount) function
#44 [Slider] Click zone on all slider node, not only pin node
Finally! Added the slider:set_input_node(node) function. Now slider can be interacted not only with slider pin node, but with any zone you will define.
It will work only from Defold 1.3.0. If you use earlier version, nothing is happened. It using new gui.screen_to_local and gui.set_screen_position functions.
#178[BREAKING][Text] Rename text:get_text_width to text:get_text_size. Now it return two numbers: width and height
#114 Add default component templates
Added templates for fast prototyping. Use GUI templates to place buttons, checkbox, input and sliders on your GUI scene. You still have to create component with druid:new functions inside gui_script.
#168 Add button to open code of current example
Inside every example added button to open code of this example on GitHub
#140 Better documentation for custom components
#172 Update documentation with links to components
#175 Remove Druid Assets repository, move to Druid library
Added folder druid/custom. It will have the complex custom components. Usually you should to use default GUI template or create your own with similar GUI scheme. Currently add RichInput and PinKnob components from druid-assets repository.
Usually to use custom component you have to require lua file first and create itâs via druid:new(Component, template_name, [nodes]). See component docs to see constructor params.
This components will be included in build only if used
#176 Keep last scene and scroll position in Druid example
Probably, itâs useful for faster debug, but anyway. The example now keep the last scene and scroll position.