This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -0,0 +1,240 @@
--[[
]]
local CoreGui = Game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")
local GuiService = game:GetService("GuiService")
local UserInputService = game:GetService("UserInputService")
local ThumbnailLoader = require(Modules:FindFirstChild('ThumbnailLoader'))
local Utility = require(Modules:FindFirstChild('Utility'))
local function CreateImageSlider(size, position)
local this = {}
local items = {}
local maxItems = 0
local currentItemIndex = 1
local padding = 0
local focusSize = 450
local itemSize = 300
local dataTable = nil
local lastSelectedObject = nil
local newSelectedObjectCn = nil
this.OnNewFocusItem = Utility.Signal()
local imageObjectToLoaderMap = {}
this.Container = Utility.Create'ScrollingFrame'
{
Name = "ImageSliderContainer";
Size = size;
Position = position;
BackgroundTransparency = 1;
ClipsDescendants = false;
ScrollingEnabled = false;
Selectable = false;
ScrollBarThickness = 0;
}
local function loadNewImage(item, dataIndex)
if imageObjectToLoaderMap[item] then
imageObjectToLoaderMap[item]:Cancel()
imageObjectToLoaderMap[item] = nil
end
local iconId = dataTable[dataIndex].IconId
local thumbLoader = ThumbnailLoader:Create(item, iconId,
ThumbnailLoader.Sizes.Medium, ThumbnailLoader.AssetType.Icon)
imageObjectToLoaderMap[item] = thumbLoader
spawn(function()
thumbLoader:LoadAsync()
imageObjectToLoaderMap[item] = nil
end)
end
local MAX_LEFT = 2
local MAX_RIGHT = 6
-- TODO: Figure out left/right better
local function recalcPositionAndSize(tweenTime, isRight, newSelectedObject)
local smIconYPos = (focusSize - itemSize) / 2
local startPosition = 0
if currentItemIndex == 1 then
startPosition = 0
elseif currentItemIndex == 2 then
startPosition = -1
elseif maxItems == #items then
startPosition = 1 - currentItemIndex
elseif maxItems - currentItemIndex < MAX_RIGHT then
startPosition = maxItems - currentItemIndex - MAX_RIGHT - MAX_LEFT
else
startPosition = -MAX_LEFT
end
-- put front at back
if maxItems > #items then
if isRight == true and startPosition == -MAX_LEFT and currentItemIndex > 3 then
local front = items[1]
local back = items[#items]
front.Position = UDim2.new(0, back.Position.X.Offset + back.Size.X.Offset + padding, 0, smIconYPos)
this:RemoveFromFront()
this:AddItemToBack(front)
if dataTable and dataTable[currentItemIndex + MAX_RIGHT] then
loadNewImage(front, currentItemIndex + MAX_RIGHT)
end
-- put back in front
elseif isRight == false and currentItemIndex < maxItems - MAX_RIGHT and startPosition == -MAX_LEFT then
local back = items[#items]
local front = items[1]
back.Position = UDim2.new(0, front.Position.X.Offset - padding - itemSize, 0, smIconYPos)
this:RemoveFromBack()
this:AddToFront(back)
if dataTable and dataTable[currentItemIndex - MAX_LEFT] then
loadNewImage(back, currentItemIndex - MAX_LEFT)
end
end
end
local currentXPosition = itemSize * startPosition + padding * startPosition
for i = 1, #items do
if items[i] == newSelectedObject then
if tweenTime == 0 then
items[i].Size = UDim2.new(0, focusSize, 0, focusSize)
items[i].Position = UDim2.new(0, currentXPosition, 0, 0)
else
items[i]:TweenSizeAndPosition(UDim2.new(0, focusSize, 0, focusSize), UDim2.new(0, currentXPosition, 0, 0),
Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, tweenTime, true)
end
currentXPosition = currentXPosition + focusSize + padding
else
if tweenTime == 0 then
items[i].Size = UDim2.new(0, itemSize, 0, itemSize)
items[i].Position = UDim2.new(0, currentXPosition, 0, smIconYPos)
else
items[i]:TweenSizeAndPosition(UDim2.new(0, itemSize, 0, itemSize), UDim2.new(0, currentXPosition, 0, smIconYPos),
Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, tweenTime, true)
end
currentXPosition = currentXPosition + itemSize + padding
end
end
end
--[[ Events ]]--
newSelectedObjectCn = GuiService.Changed:connect(function(property)
if property == 'SelectedCoreObject' then
local selectedObject = GuiService.SelectedCoreObject
if selectedObject and selectedObject ~= lastSelectedObject and selectedObject:IsDescendantOf(this.Container) then
local isRight = nil
if lastSelectedObject then
-- slide left
if lastSelectedObject.AbsolutePosition.x < selectedObject.AbsolutePosition.x then
currentItemIndex = currentItemIndex + 1
isRight = true
-- slide right
else
currentItemIndex = currentItemIndex - 1
isRight = false
end
end
recalcPositionAndSize(lastSelectedObject and 0.25 or 0, isRight, selectedObject)
lastSelectedObject = selectedObject
this.OnNewFocusItem:fire(currentItemIndex, isRight, selectedObject)
end
end
end)
--[[ Public API ]]--
function this:SetPosition(position)
self.Container.Position = position
end
function this:SetSize(size)
self.Container.Size = size
end
function this:SetParent(parent)
self.Container.Parent = parent
end
function this:SetFocusPosition(index)
if index > 0 and index < #items + 1 then
currentItemIndex = index
recalcPositionAndSize(0, nil, items[currentItemIndex])
end
end
function this:SetDataTable(tbl)
dataTable = tbl
end
function this:SetMaxItems(value)
local index = nil
-- we're near the end, so we need to update image content
if currentItemIndex > maxItems - MAX_RIGHT then
-- find the current selected index in relation to image pool
for i = 1, #items do
if lastSelectedObject and items[i] == GuiService.SelectedCoreObject then
index = i
break
end
end
-- TODO: Still might be a visual bug in some cases
if index then
-- replace images from front of pool
for i = 1, index - 3 do
if dataTable[currentItemIndex + i] then
local item = items[1]
loadNewImage(item, currentItemIndex + (maxItems - currentItemIndex) + i)
print("NEW IMAGE:", currentItemIndex, ":", maxItems, ":", i, ":", currentItemIndex + (maxItems - currentItemIndex) + i)
self:RemoveFromFront()
self:AddItemToBack(item)
end
end
end
end
maxItems = value
recalcPositionAndSize(0)
end
function this:SetPadding(newPadding)
padding = newPadding
end
function this:AddToFront(newItem)
table.insert(items, 1, newItem)
newItem.Parent = this.Container
end
function this:AddItemToBack(newItem)
if this and this.Container then
items[#items + 1] = newItem
newItem.Parent = this.Container
end
end
function this:AddItem(newItem)
self:AddItemToBack(newItem)
end
function this:RemoveFromFront()
table.remove(items, 1)
end
function this:RemoveFromBack()
table.remove(items)
end
function this:Destroy()
if newSelectedObjectCn then
newSelectedObjectCn:disconnect()
newSelectedObjectCn = nil
end
this.Container:Destroy()
this.OnNewFocus = nil
this = nil
end
return this
end
return CreateImageSlider