Scrollingframe affecting UI

When the player picks up an item, it creates a new button and positions it to the first available top-left grid.
However, when the player scrolls down then pick up an item, the positioning of the newly created button is completely wrong.
E.g:
https://gyazo.com/7960ae7994aeed0974e7b147789a431c
and
https://gyazo.com/06aae801365b58a28171f2bc31f9b2cb

This is the current hierarchy of my inventory UI.
image
The grid frame contains all of the squares you see in the inventory.
The newly created button is the ImageButton.

These two, as well as the individual frames inside the grid, are sized and position with offset, not scale.
The scrolling frame on the other hand is scaled.

This is the code that positions the image button to a grid.

function InventoryUI:PositionToSpace(ItemFrame, FirstGrid)
	local FirstGrid = tonumber(FirstGrid.Name) + 1	-- Add one as the first child of backpack is GridUILayout
	local pos = BackpackGrid:GetChildren()[FirstGrid].AbsolutePosition - ItemFrame.AbsolutePosition
	return UDim2.fromOffset(pos.X, pos.Y)
end
1 Like

Kon’nichiwa! :bowing_woman:t2:
It might be useful to you to use the UIGridLayout (roblox.com) API.
Its use is pretty simple and straightforward and should save you some effort as it was developed specifically for this purpose.

I should mention the individual squares inside of the grid frame do use UIGridLayout, and I doubt that’s the problem.
I’d like to think the problem has to do with the fact I’m using absolute positions to calculate the position for the image button. But I have no idea how else to find the position of a frame when their being controlled by a UIGridLayout.

You can add this to a local script which should be a child of the UIGridLayout object.
It will automatically put the newest object first in the UI.

It changes the LayoutOrder of new Frame added in order to achieve the desired order you want.

local Max_Horizontal_Direction_Fill = 5

local Grid = script.Parent
Grid.FillDirectionMaxCells = Max_Horizontal_Direction_Fill
Grid.SortOrder = Enum.SortOrder.LayoutOrder
Grid.StartCorner = Enum.StartCorner.TopLeft
Grid.VerticalAlignment = Enum.VerticalAlignment.Top
Grid.HorizontalAlignment = Enum.HorizontalAlignment.Left
Grid.FillDirection = Enum.FillDirection.Horizontal

Grid.Parent.ChildAdded:Connect(function(Child)
	if Child:IsA("Frame") then
		Child.LayoutOrder = -(#Grid.Parent:GetChildren()+1)
	end
end)

Grid.Parent.ChildRemoved:Connect(function()
	for i,Child in pairs(Grid.Parent:GetChildren()) do
		if Child:IsA("Frame") then
			Child.LayoutOrder = Child.LayoutOrder+1
		end
	end
end)

Here is my example:
image

I don’t think you understand what I’m trying to do here.
I don’t want the UIGridLayout to apply to the item button, I want to position the item button on the grids, like in a grid inventory, e.g:
image

So my original code works completely fine, except, the problem seems to emerge when the scrolling frame CanvasPosition is not at 0,0 (as in it hasn’t been scrolled down).

I tried adding the CanvasPosition to my calculation of a new UDim2 in this line:

local pos = BackpackGrid:GetChildren()[FirstGrid].AbsolutePosition - ItemFrame.Parent.AbsolutePosition + Backpack.ScrollingFrame.CanvasPosition

However, this doesn’t seem to work.
Adding onto this, I think my problem might be very similar to this person’s problem,
however, his solution didn’t work for me.

This line prints the normal calculation without considering the CanvasPosition.
image
The result with scrolling frame scrolled all the way down.
image
Keep in mind, the normal position should be 72,72

This line prints out the CanvasPosition of the scrolling frame.
image
With the scrolling frame scrolled down, this is the result:
image

And so, this is the calculation I’m doing, see how I consider the offset of the scrolling frame by adding its CanvasPosition.

So naturally, this calculation
image
When including the CanvasPosition would roughly be around 72, 72 as -264 + 337 = 73.

But when I actually print out the position local pos calculated, I get this instead of 72, 72
image

I’m not exactly sure how -264 + 337 = -387. So in conclusion, this is stupid I give up.

I’m not exactly sure why I need to do this. But separating the X and Y values into different lines of calculations seems to have made it work perfectly.

function InventoryUI:PositionToSpace(ItemFrame, FirstGrid)
	local FirstGrid = tonumber(FirstGrid.Name) + 1	-- Add one as the first child of backpack is UILayout
	local X = BackpackGrid:GetChildren()[FirstGrid].AbsolutePosition.X + Backpack.ScrollingFrame.CanvasPosition.X - ItemFrame.Parent.AbsolutePosition.X
	local Y = BackpackGrid:GetChildren()[FirstGrid].AbsolutePosition.Y + Backpack.ScrollingFrame.CanvasPosition.Y - ItemFrame.Parent.AbsolutePosition.Y
	
	return UDim2.fromOffset(X, Y)
end