diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua index 91b14c3..2dc0fbc 100644 --- a/druid/extended/dynamic_grid.lua +++ b/druid/extended/dynamic_grid.lua @@ -220,6 +220,14 @@ function DynamicGrid.get_size(self, border) end +function DynamicGrid.get_size_for(self, count) + return vmath.vector3( + self.border.z - self.border.x, + self.border.y - self.border.w, + 0) +end + + --- Return grid content borders -- @tparam DynamicGrid self -- @treturn vector3 The grid content borders diff --git a/druid/extended/infinity_list.lua b/druid/extended/infinity_list.lua index 43f7a36..190000a 100644 --- a/druid/extended/infinity_list.lua +++ b/druid/extended/infinity_list.lua @@ -15,17 +15,13 @@ function M:init(data_list, scroll, grid, create_function) self.data = data_list self.top_index = 1 + self.last_index = 1 self.create_function = create_function self.nodes = {} self.components = {} - self.elements_view_count = vmath.vector3( - math.min(math.ceil(self.view_size.x / self.prefab_size.x), self.grid.in_row), - math.ceil(self.view_size.y / self.prefab_size.y), - 0) - self:_refresh() self.scroll.on_scroll:subscribe(function() self._check_elements(self) end) end @@ -85,7 +81,7 @@ function M:_refresh() end -function M:_check_elements() +function M:_check_elements_old() local pos = gui.get_position(self.scroll.content_node) pos.y = -pos.y @@ -108,6 +104,74 @@ function M:_check_elements() end +function M:_check_elements() + local top_index = self.top_index + self.last_index = self.top_index + + for index, node in pairs(self.nodes) do + if self.scroll:is_node_in_view(node) then + top_index = index + break + end + end + + -- make items from (top_index upside + local is_top_outside = false + local cur_index = top_index - 1 + while not is_top_outside do + if not self.data[cur_index] then + break + end + + if not self.nodes[cur_index] then + self:_add_at(cur_index) + end + + if not self.scroll:is_node_in_view(self.nodes[cur_index]) then + is_top_outside = true + + -- remove nexts: + local remove_index = cur_index - 1 + while self.nodes[remove_index] do + self:_remove_at(remove_index) + remove_index = remove_index - 1 + end + end + + cur_index = cur_index - 1 + end + + -- make items from [top_index downsize + local is_bot_outside = false + cur_index = top_index + while not is_bot_outside do + if not self.data[cur_index] then + break + end + + if not self.nodes[cur_index] then + self:_add_at(cur_index) + end + if not self.scroll:is_node_in_view(self.nodes[cur_index]) then + is_bot_outside = true + + -- remove nexts: + local remove_index = cur_index + 1 + while self.nodes[remove_index] do + self:_remove_at(remove_index) + remove_index = remove_index + 1 + end + else + self.last_index = cur_index + end + + cur_index = cur_index + 1 + end + + self.top_index = top_index +end + + function M:_recalc_scroll_size() local element_size = self.grid:get_size_for(#self.data) self.scroll:set_size(element_size) diff --git a/example/gui/main/main.gui b/example/gui/main/main.gui index fd0159f..7e191c3 100644 --- a/example/gui/main/main.gui +++ b/example/gui/main/main.gui @@ -9832,7 +9832,7 @@ nodes { w: 1.0 } size { - x: 400.0 + x: 500.0 y: 400.0 z: 0.0 w: 1.0 @@ -9887,15 +9887,15 @@ nodes { w: 1.0 } size { - x: 400.0 + x: 500.0 y: 400.0 z: 0.0 w: 1.0 } color { - x: 1.0 - y: 1.0 - z: 1.0 + x: 0.5019608 + y: 0.3019608 + z: 0.5019608 w: 1.0 } type: TYPE_BOX @@ -11216,9 +11216,9 @@ nodes { w: 1.0 } color { - x: 1.0 - y: 1.0 - z: 1.0 + x: 0.8 + y: 0.4 + z: 0.2 w: 1.0 } type: TYPE_BOX @@ -11638,8 +11638,8 @@ nodes { w: 1.0 } size { - x: 1.0 - y: 1.0 + x: 600.0 + y: 900.0 z: 0.0 w: 1.0 } @@ -11671,12 +11671,12 @@ nodes { clipping_inverted: false alpha: 1.0 template_node_child: false - size_mode: SIZE_MODE_AUTO + size_mode: SIZE_MODE_MANUAL } nodes { position { x: 0.0 - y: 280.0 + y: 450.0 z: 0.0 w: 1.0 } @@ -11693,7 +11693,125 @@ nodes { w: 1.0 } size { - x: 300.0 + x: 600.0 + y: 2000.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: "infinity_page_content" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_N + adjust_mode: ADJUST_MODE_FIT + parent: "infinity_page" + 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: -128.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: 400.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_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Infinity scroll:" + font: "game" + id: "infinity_header" + 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: "infinity_page_content" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 0.0 + shadow_alpha: 0.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 +} +nodes { + position { + x: 0.0 + y: -644.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: 400.0 y: 250.0 z: 0.0 w: 1.0 @@ -11712,7 +11830,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_N adjust_mode: ADJUST_MODE_FIT - parent: "infinity_page" + parent: "infinity_page_content" layer: "" inherit_alpha: true slice9 { @@ -11786,7 +11904,7 @@ nodes { nodes { position { x: 0.0 - y: 240.0 + y: -684.0 z: 0.0 w: 1.0 } @@ -11822,7 +11940,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT - parent: "infinity_page" + parent: "infinity_page_content" layer: "" inherit_alpha: true slice9 { @@ -11904,7 +12022,7 @@ nodes { nodes { position { x: 0.0 - y: 320.0 + y: -968.0 z: 0.0 w: 1.0 } @@ -11922,69 +12040,6 @@ nodes { } size { x: 400.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_TEXT - blend_mode: BLEND_MODE_ALPHA - text: "Infinity scroll:" - font: "game" - id: "infinity_header" - 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: "infinity_page" - layer: "" - inherit_alpha: true - alpha: 1.0 - outline_alpha: 0.0 - shadow_alpha: 0.0 - template_node_child: false - text_leading: 1.0 - text_tracking: 0.0 -} -nodes { - position { - x: 0.0 - y: -44.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: 270.0 y: 250.0 z: 0.0 w: 1.0 @@ -12003,7 +12058,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_N adjust_mode: ADJUST_MODE_FIT - parent: "infinity_page" + parent: "infinity_page_content" layer: "" inherit_alpha: true slice9 { @@ -12077,7 +12132,7 @@ nodes { nodes { position { x: 0.0 - y: -106.0 + y: -1030.0 z: 0.0 w: 1.0 } @@ -12113,7 +12168,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT - parent: "infinity_page" + parent: "infinity_page_content" layer: "" inherit_alpha: true slice9 { @@ -12192,6 +12247,234 @@ nodes { text_leading: 1.0 text_tracking: 0.0 } +nodes { + position { + x: 0.0 + y: -176.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: 400.0 + y: 400.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.8 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "infinity_scroll_stencil_dynamic" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_N + adjust_mode: ADJUST_MODE_FIT + parent: "infinity_page_content" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_STENCIL + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL +} +nodes { + position { + x: 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: 400.0 + y: 400.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.8 + y: 1.0 + z: 0.8 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/empty" + id: "infinity_scroll_content_dynamic" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_N + adjust_mode: ADJUST_MODE_FIT + parent: "infinity_scroll_stencil_dynamic" + 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: -216.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: 60.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: "infinity_prefab_dynamic" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "infinity_page_content" + layer: "" + inherit_alpha: true + slice9 { + x: 20.0 + y: 0.0 + z: 20.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.75 + y: 0.75 + z: 1.0 + w: 1.0 + } + size { + x: 380.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_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Dynamic element 1" + font: "game" + id: "infinity_text_dynamic" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 0.3019608 + y: 0.4 + z: 0.8 + 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: "infinity_prefab_dynamic" + 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 diff --git a/example/page/grid_page.lua b/example/page/grid_page.lua index 41ed7d5..8b0dc06 100644 --- a/example/page/grid_page.lua +++ b/example/page/grid_page.lua @@ -25,7 +25,6 @@ local function add_node(self, index) local prefab = gui.get_node("grid_nodes_prefab") local cloned = gui.clone_tree(prefab) gui.set_enabled(cloned["grid_nodes_prefab"], true) - gui.set_text(cloned["grid_nodes_text"], index) local button = self.druid:new_button(cloned["grid_nodes_prefab"], function(_, params, button) remove_node(self, button, true) @@ -149,7 +148,7 @@ end function M.setup_page(self) - self.grid_page_scroll = self.druid:new_scroll("grid_page", "grid_page_content") + self.druid:new_scroll("grid_page", "grid_page_content") self.grid_static_grid = self.druid:new_static_grid("grid_nodes", "grid_nodes_prefab", 5) :set_position_function(simple_animate) diff --git a/example/page/infinity_page.lua b/example/page/infinity_page.lua index a98636d..71bc250 100644 --- a/example/page/infinity_page.lua +++ b/example/page/infinity_page.lua @@ -28,6 +28,20 @@ end +local function create_infinity_instance_dynamic(self, record, index) + local instance = gui.clone_tree(self.infinity_prefab_dynamic) + gui.set_enabled(instance["infinity_prefab_dynamic"], true) + gui.set_text(instance["infinity_text_dynamic"], "Dynamic record " .. index) + + gui.set_size(instance["infinity_prefab_dynamic"], vmath.vector3(300, 60 + index * 5, 0)) + local button = self.druid:new_button(instance["infinity_prefab_dynamic"], function() + print("Dynamic click on", index) + end) + + return instance["infinity_prefab_dynamic"], button +end + + local function setup_infinity_list(self) local data = {} for i = 1, 50 do @@ -40,18 +54,25 @@ local function setup_infinity_list(self) end) -- scroll to some index - local pos = self.infinity_grid:get_pos(25) - self.infinity_scroll:scroll_to(pos, true) + -- local pos = self.infinity_grid:get_pos(25) + -- self.infinity_scroll:scroll_to(pos, true) self.infinity_list_small = self.druid:new_infinity_list(data, self.infinity_scroll_3, self.infinity_grid_3, function(record, index) -- function should return gui_node, [druid_component] return create_infinity_instance_small(self, record, index) end) + + self.infinity_list_dynamic = self.druid:new_infinity_list(data, self.infinity_scroll_dynamic, self.infinity_grid_dynamic, function(record, index) + -- function should return gui_node, [druid_component] + return create_infinity_instance_dynamic(self, record, index) + end) end function M.setup_page(self) + self.druid:new_scroll("infinity_page", "infinity_page_content") + self.infinity_scroll = self.druid:new_scroll("infinity_scroll_stencil", "infinity_scroll_content") :set_horizontal_scroll(false) self.infinity_grid = self.druid:new_static_grid("infinity_scroll_content", "infinity_prefab", 1) @@ -64,6 +85,12 @@ function M.setup_page(self) self.infinity_prefab_small = gui.get_node("infinity_prefab_small") gui.set_enabled(self.infinity_prefab_small, false) + self.infinity_scroll_dynamic = self.druid:new_scroll("infinity_scroll_stencil_dynamic", "infinity_scroll_content_dynamic") + :set_horizontal_scroll(false) + self.infinity_grid_dynamic = self.druid:new_dynamic_grid("infinity_scroll_content_dynamic", "infinity_prefab", 1) + self.infinity_prefab_dynamic = gui.get_node("infinity_prefab_dynamic") + gui.set_enabled(self.infinity_prefab_dynamic, false) + setup_infinity_list(self) end