mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 13:17:49 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
--[[
|
||||
// CarouselController.lua
|
||||
|
||||
// Controls how the data is updated for a carousel view
|
||||
]]
|
||||
local CoreGui = Game:GetService("CoreGui")
|
||||
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
||||
local Modules = GuiRoot:FindFirstChild("Modules")
|
||||
|
||||
local ContextActionService = game:GetService('ContextActionService')
|
||||
local GuiService = game:GetService('GuiService')
|
||||
|
||||
local EventHub = require(Modules:FindFirstChild('EventHub'))
|
||||
local GlobalSettings = require(Modules:FindFirstChild('GlobalSettings'))
|
||||
local SoundManager = require(Modules:FindFirstChild('SoundManager'))
|
||||
local ThumbnailLoader = require(Modules:FindFirstChild('ThumbnailLoader'))
|
||||
local Utility = require(Modules:FindFirstChild('Utility'))
|
||||
|
||||
local function createCarouselController(view)
|
||||
local this = {}
|
||||
|
||||
local PAGE_SIZE = 25
|
||||
local MAX_PAGES = 2
|
||||
local LOAD_BUFFER = 10
|
||||
local LOAD_AMOUNT = 100
|
||||
|
||||
local sortCollection = nil
|
||||
local sortDataObject = nil -- TODO: Remove when caching is finished
|
||||
local sortData = nil
|
||||
local currentFocusData = nil
|
||||
local sortDataIndex = 1
|
||||
local guiServiceChangedCn = nil
|
||||
|
||||
local pages = {}
|
||||
local firstIndex = 0
|
||||
local lastIndex = 0
|
||||
local isLoading = false
|
||||
|
||||
-- Events
|
||||
this.NewItemSelected = Utility.Signal()
|
||||
|
||||
local function getNewItem(data)
|
||||
local item = Utility.Create'ImageButton'
|
||||
{
|
||||
Name = "CarouselViewImage";
|
||||
BackgroundColor3 = GlobalSettings.ModalBackgroundColor;
|
||||
SoundManager:CreateSound('MoveSelection');
|
||||
}
|
||||
spawn(function()
|
||||
local loader = ThumbnailLoader:Create(item, data.IconId, ThumbnailLoader.Sizes.Medium, ThumbnailLoader.AssetType.Icon)
|
||||
loader:LoadAsync(true, false, nil)
|
||||
end)
|
||||
|
||||
return item
|
||||
end
|
||||
|
||||
-- TODO: Remove this when caching is finished. Doing it this way is going to leave the old
|
||||
-- data issues in place with the carousel
|
||||
local function setInternalData(page)
|
||||
if not page then
|
||||
return {}
|
||||
end
|
||||
|
||||
local newData = {}
|
||||
|
||||
local placeIds = page:GetPagePlaceIds()
|
||||
local names = page:GetPagePlaceNames()
|
||||
local voteData = page:GetPageVoteData()
|
||||
local iconIds = page:GetPageIconIds()
|
||||
local creatorNames = page:GetCreatorNames()
|
||||
local creatorUserIds = page:GetPageCreatorUserIds()
|
||||
|
||||
for i = 1, #page.Data do
|
||||
local gameEntry = {
|
||||
Title = names[i];
|
||||
PlaceId = placeIds[i];
|
||||
IconId = iconIds[i];
|
||||
VoteData = voteData[i];
|
||||
CreatorName = creatorNames[i];
|
||||
CreatorUserId = creatorUserIds[i];
|
||||
-- Description and IsFavorites needs to be queried for each game when needed
|
||||
Description = nil;
|
||||
IsFavorited = nil;
|
||||
GameData = nil;
|
||||
}
|
||||
table.insert(newData, gameEntry)
|
||||
end
|
||||
|
||||
return newData
|
||||
end
|
||||
|
||||
local function createPage(startIndex)
|
||||
local page = {}
|
||||
local items = {}
|
||||
|
||||
for i = 1, PAGE_SIZE do
|
||||
local dataIndex = startIndex + (i - 1)
|
||||
if sortData[dataIndex] then
|
||||
local item = getNewItem(sortData[dataIndex])
|
||||
item.MouseButton1Click:connect(function()
|
||||
local currentData = sortData[dataIndex]
|
||||
if currentData then
|
||||
EventHub:dispatchEvent(EventHub.Notifications["OpenGameDetail"], currentData.PlaceId, currentData.Title, currentData.IconId, currentData.GameData)
|
||||
end
|
||||
end)
|
||||
table.insert(items, item)
|
||||
end
|
||||
end
|
||||
|
||||
function page:GetCount()
|
||||
return #items
|
||||
end
|
||||
|
||||
function page:GetItems()
|
||||
return items
|
||||
end
|
||||
|
||||
function page:Destroy()
|
||||
for i,item in pairs(items) do
|
||||
items[i] = nil
|
||||
item:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
return page
|
||||
end
|
||||
|
||||
local previousFocusItem = nil
|
||||
local function onViewFocusChanged(newFocusItem)
|
||||
local offset = 0
|
||||
if previousFocusItem then
|
||||
offset = view:GetItemIndex(newFocusItem) - view:GetItemIndex(previousFocusItem)
|
||||
end
|
||||
|
||||
local visibleItemCount = view:GetVisibleCount()
|
||||
local itemCount = view:GetCount()
|
||||
|
||||
if offset > 0 then
|
||||
-- scrolled right
|
||||
local firstVisibleItemIndex = view:GetFirstVisibleItemIndex()
|
||||
if not isLoading and firstVisibleItemIndex + visibleItemCount + LOAD_BUFFER >= itemCount then
|
||||
isLoading = true
|
||||
local page = createPage(lastIndex + 1)
|
||||
if page:GetCount() > 0 then
|
||||
local items = page:GetItems()
|
||||
view:InsertCollectionBack(items)
|
||||
table.insert(pages, page)
|
||||
lastIndex = lastIndex + page:GetCount()
|
||||
-- remove front page
|
||||
if view:GetCount() > PAGE_SIZE * MAX_PAGES then
|
||||
local firstPage = table.remove(pages, 1)
|
||||
firstIndex = firstIndex + firstPage:GetCount()
|
||||
view:RemoveAmountFromFront(firstPage:GetCount())
|
||||
firstPage:Destroy()
|
||||
end
|
||||
end
|
||||
isLoading = false
|
||||
end
|
||||
elseif offset < 0 then
|
||||
-- scrolled left
|
||||
local lastVisibleItemIndex = view:GetLastVisibleItemIndex()
|
||||
if not isLoading and lastVisibleItemIndex - visibleItemCount - LOAD_BUFFER < 0 then
|
||||
isLoading = true
|
||||
local page = createPage(firstIndex - PAGE_SIZE)
|
||||
if page:GetCount() > 0 then
|
||||
local items = page:GetItems()
|
||||
view:InsertCollectionFront(items)
|
||||
table.insert(pages, 1, page)
|
||||
firstIndex = firstIndex - page:GetCount()
|
||||
if view:GetCount() > PAGE_SIZE * MAX_PAGES then
|
||||
local lastPage = table.remove(pages)
|
||||
lastIndex = lastIndex - lastPage:GetCount()
|
||||
view:RemoveAmountFromBack(lastPage:GetCount())
|
||||
lastPage:Destroy()
|
||||
end
|
||||
end
|
||||
isLoading = false
|
||||
end
|
||||
end
|
||||
|
||||
sortDataIndex = sortDataIndex + offset
|
||||
previousFocusItem = newFocusItem
|
||||
view:ChangeFocus(newFocusItem)
|
||||
currentFocusData = sortData[sortDataIndex]
|
||||
this.NewItemSelected:fire(currentFocusData)
|
||||
end
|
||||
|
||||
--[[ Public API ]]--
|
||||
function this:GetCurrentFocusGameData()
|
||||
return currentFocusData
|
||||
end
|
||||
|
||||
function this:InitializeAsync(gameCollection)
|
||||
view:RemoveAllItems()
|
||||
firstIndex = 1
|
||||
lastIndex = 1
|
||||
currentFocusData = nil
|
||||
pages = {}
|
||||
sortData = {}
|
||||
|
||||
sortCollection = gameCollection
|
||||
|
||||
local page = gameCollection:GetSortAsync(0, LOAD_AMOUNT)
|
||||
sortData = setInternalData(page)
|
||||
|
||||
local firstPage = createPage(firstIndex)
|
||||
if firstPage:GetCount() > 0 then
|
||||
local items = firstPage:GetItems()
|
||||
view:InsertCollectionBack(items)
|
||||
table.insert(pages, firstPage)
|
||||
lastIndex = firstPage:GetCount()
|
||||
|
||||
local frontViewItem = view:GetFront()
|
||||
if frontViewItem then
|
||||
previousFocusItem = frontViewItem
|
||||
sortDataIndex = 1
|
||||
currentFocusData = sortData[sortDataIndex]
|
||||
view:SetFocus(frontViewItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function this:Connect()
|
||||
guiServiceChangedCn = Utility.DisconnectEvent(guiServiceChangedCn)
|
||||
guiServiceChangedCn = GuiService.Changed:connect(function(property)
|
||||
if property ~= 'SelectedCoreObject' then
|
||||
return
|
||||
end
|
||||
local newSelection = GuiService.SelectedCoreObject
|
||||
if newSelection and view:ContainsItem(newSelection) then
|
||||
onViewFocusChanged(newSelection)
|
||||
end
|
||||
end)
|
||||
|
||||
local seenRightBumper = false
|
||||
local function onBumperRight(actionName, inputState, inputObject)
|
||||
if inputState == Enum.UserInputState.Begin then
|
||||
seenRightBumper = true
|
||||
elseif seenRightBumper and inputState == Enum.UserInputState.End then
|
||||
local currentSelection = GuiService.SelectedCoreObject
|
||||
if currentSelection and view:ContainsItem(currentSelection) then
|
||||
local currentFocusIndex = view:GetItemIndex(previousFocusItem)
|
||||
local shiftAmount = view:GetFullVisibleItemCount()
|
||||
local nextItem = view:GetItemAt(currentFocusIndex + shiftAmount) or view:GetBack()
|
||||
if nextItem then
|
||||
GuiService.SelectedCoreObject = nextItem
|
||||
end
|
||||
end
|
||||
seenRightBumper = false
|
||||
end
|
||||
end
|
||||
|
||||
local seenLeftBumper = false
|
||||
local function onBumperLeft(actionName, inputState, inputObject)
|
||||
if inputState == Enum.UserInputState.Begin then
|
||||
seenLeftBumper = true
|
||||
elseif seenLeftBumper and inputState == Enum.UserInputState.End then
|
||||
local currentSelection = GuiService.SelectedCoreObject
|
||||
if currentSelection and view:ContainsItem(currentSelection) then
|
||||
local currentFocusIndex = view:GetItemIndex(previousFocusItem)
|
||||
local shiftAmount = view:GetFullVisibleItemCount()
|
||||
local nextItem = view:GetItemAt(currentFocusIndex - shiftAmount) or view:GetFront()
|
||||
if nextItem then
|
||||
GuiService.SelectedCoreObject = nextItem
|
||||
end
|
||||
end
|
||||
seenRightBumper = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Bumper Binds
|
||||
ContextActionService:BindCoreAction("BumperRight", onBumperRight, false, Enum.KeyCode.ButtonR1)
|
||||
ContextActionService:BindCoreAction("BumperLeft", onBumperLeft, false, Enum.KeyCode.ButtonL1)
|
||||
end
|
||||
|
||||
function this:Disconnect()
|
||||
guiServiceChangedCn = Utility.DisconnectEvent(guiServiceChangedCn)
|
||||
ContextActionService:UnbindCoreAction("BumperRight")
|
||||
ContextActionService:UnbindCoreAction("BumperLeft")
|
||||
end
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
return createCarouselController
|
||||
Reference in New Issue
Block a user