I got in the zone today coding a little module to handle scrollable lists. I’m quite happy with it so figured I’d share.
All it does is scroll over a list of things, and can handle a list that either loops or has a beginning and end.
Here is how it looks with a list of three “scenarios” in my game, with a list that has a beginning and an end:
Here is the full module:
--[[
A one dimensional scrollable list. Each step in the list contains a payload - a single value or a table.
The list can either loop infinitely or go forward and back.
Example usage:
scrollable_list.new_list("test_list", {1,2,3}, false)
scrollable_list.scroll("test_list", scrollable_list.FORWARD)
print(scrollable_list.get_payload("test_list")) --2
scrollable_list.scroll("test_list", scrollable_list.FORWARD)
scrollable_list.scroll("test_list", scrollable_list.FORWARD)
print(scrollable_list.get_payload("test_list")) --3 (looping not allowed)
scrollable_list.remove_list("test_list")
--]]
local scrollable_list = {}
scrollable_list.FORWARD = hash("forward")
scrollable_list.BACK = hash("back")
scrollable_list.lists = {}
---payloads is a table of values/tables that are the purpose of the scrollable list.
function scrollable_list.new_list(id, payloads, allow_loop)
scrollable_list.lists[id] = {index = 1, length = #payloads, payloads = payloads, allow_loop = allow_loop}
end
function scrollable_list.remove_list(id)
scrollable_list.lists[id] = nil
end
function scrollable_list.wrap(id, direction)
local list = scrollable_list.lists[id]
if not list then
return false
end
local index = list.index
if direction == scrollable_list.FORWARD then
index = index + 1
if index > list.length then
if list.allow_loop then
index = 1
else
index = list.length
end
end
elseif direction == scrollable_list.BACK then
index = index - 1
if index < 1 then
if list.allow_loop then
list.index = list.length
else
index = 1
end
end
end
return index
end
function scrollable_list.scroll(id, direction)
local list = scrollable_list.lists[id]
if not list then
return false
end
list.index = scrollable_list.wrap(id, direction)
end
---returns the payload of a list, if no offset (FORWARD/BACK) specified then will return current payload
function scrollable_list.get_payload(id, offset)
local list = scrollable_list.lists[id]
if not list then
return nil
end
if not offset then
return list.payloads[list.index]
else
return list.payloads[scrollable_list.wrap(id, offset)]
end
end
---returns true if the given list can scroll in a given direction (i.e. if allow_loop is true or the list is not at either end depending on the direction)
function scrollable_list.can_scroll(id, direction)
local list = scrollable_list.lists[id]
if not list then
return nil
end
return list.allow_loop == true or ((direction == scrollable_list.BACK and list.index > 1) or (direction == scrollable_list.FORWARD and list.index < list.length))
end
return scrollable_list