#Infinite-Scrolled, Touch-Based (Vertical) Carousel Menu
97 messages · Page 1 of 1 (latest)
(I'll be late to respond because I need to sleep soon)
You can use the Parallax2D class. It has methods to create infinite scrolling ui elements.
I assume since it a 2D Node, It should be fine if I put inside a control node, yes?
Also, this is WIP for the step-by-step (Roughly)
- Make a Container for the scrolling menu
- Make a separate scene for the items (which would be instantiated automically)
- the separate scene will be contained in an array
That's all that I can think of at the moment, so.... yep
still quite stuck.
Right, I've tried it with using Parallax2D, and it kinda works (was testing it using the autoscroll inside the Parallax2D),
now how can I make it touch-scrollable, and also snap when the carousel finish spinning (from swiping)?
There’s no built in method for that on Parallax2D
You’re gonna have to make your own custom class
Set the position of the items in your carousel manually to the position you want it to snap to
There are ways you can do this using by making your own grid for example
Ah, I see...
Node-wise, how should I setup my carousel? (in this case, it's a vertical carousel)
Is it like this?
Rrrright, I forgot to put the "Beginner" tag on mine 😅
So, with making the grid, do you mean making the array for the items, yes?
(If it's ok, are you online later? I plan to quickly finish this menu so if we could arrange time where we could be online together for tackling this problem, would that be okay?)
I’ll be online now for a while so I can help you out
Do you need to hold data about the items in your carousel or do you just simply want it to scroll and repeat the texture?
I need it to hold data about the item in my carousel
Also, sorry for the late reply.
First add a Parallax2D
Then under the Parallax2D add a GridContainer as a child
Next add the carousel objects as a child of the GridContainer
Set the repeat_size property of the Parallax2D to the size property of your GridContainer.
Finally set the autoscroll property of the Parallax2D
Sorry, just got back
Hmm... I'll try yours first
Is the Node Hierarchy like this?
Ok, It works with the auto scroll (for testing)
but here's the real problem
The most straightforward way to achieve what you’re trying to do is to set the positions of each child node under GridContainer manually
First go into project settings and under ‘Pointing’ you enable emulate touch from mouse
Then under your GridContainer attach a new script
Add the built in _unhandled_input function
if event.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
Viewport.get_mouse_position```
Use that to get the position of where your player is touching the screen
Then set the position of each of the child nodes manually to replicate the snap
If, for example:
I use Instantiate (For each child, containing the Map), how can I set the position on the child node?
Knowing that the GridContainer automatically sort the Item (which in my case, I need it vertically).
Alright replace the GridContainer with a control node
Because GridContainer doesnt allow you to manually set the positions of child nodes
Then implement something like this into the script attatched to your control node
@export var snap_positions: Array[Vector2] = [Vector2(28, 30), Vector2(40, 64)]
@export var snap_distance: float
@onready var child_nodes: Array[Node] = get_children()
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_released("mouse button left"):
check_snap_distance()
func check_snap_distance() -> void:
for child: Node in child_nodes:
for snap_position: Vector2 in snap_positions:
if child.position.x - snap_distance == snap_position.x:
child.position.x = snap_position.x
elif child.position.x + snap_distance == snap_position.x:
child.position.x = snap_position.x
Here when the player releases their finger from the screen, _unhandled_input is called
Then check_snap_distance is called
This function checks the position.x of each child node and if it is within snapping distance of your snap_positions
It will set the position.x of the child node to your snap_position
(Since were not inheriting from GridContainer your child nodes will not be laid out in a grid format in the editor, so youll have to manually do it)
Unless you want to implement your own custom system to lay out a grid, but its not really a straightforward process and its a bit complicated because then I would have to basically show you how to create your own customizable version of GridContainer
As in, a GridContainer+?
Yea well you can call the class whatever youd like
But that class is basically gonna have to calculate a grid and lay it out based off the number of columns
How about the VBoxContainer?
Nah the VBoxContainer also doesnt allow you to manually set the positions of its child nodes
Alright, Lemme think a bit:
Since I need to manually code for each position, that means each item will be separated by item index (as in Array), then making the gap by making the item's position based on (Item's Height + Gap Size), yes?
You could do that, but its gonna be quite complicated. Youre gonna have to calculate the rows based off the columns and the size of your Control
Then youre gonna have to set the size of each child node to match the size of your Control and set its position aswell
Another way you could do it is to use the GridContainer
But then offset the entire texture based on snap_positions
Instead of setting the positions of each child_node maually
Youre not gonna have to sorted children from your Control node
But you dont really need to have the children sorted from your Control
If you want the player to interact with the children you can just make the child nodes under your GridContainer a button or something
And have each child node's pressed() signal connect to your parent node to detect when the player interacts with the item in your carousel
should this be putted inside the item, or the control node which contain the items?
Wait first what are you going to try and do, option 1 or option 2. Are you going to set the child positions manually or use Godot's built in GridContainer.
Which one do you think it's more complicated? 
Option 1 is definitely way more complicated trust me
But it depends on what youre trying to do
Are the items in your carousal going to be the same every single time the texture is repeated?
Or are you going to try and change the item when the texture is about to repeat
I think this one? Since my carousel menu acts like a stage select
Here's my concept so far
When player finish choosing the map, they press the choose map button to select it.
@export var snap_positions: Array[Vector2] = [Vector2(28, 30), Vector2(40, 64)]
@export var snap_distance: float
@onready var child_nodes: Array[Node] = get_children()
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_released("mouse button left"):
check_snap_distance()
func check_snap_distance() -> void:
for snap_position: Vector2 in snap_positions:
if position.y - snap_distance == snap_position.y:
position.y = snap_position.y
elif position.y + snap_distance == snap_position.y:
position.y = snap_position.y
This will snap the entire grid with all its child nodes
Just set the elements in the snap_positions array to the position of each child node
Still using this Node Hierarchy btw.
Yea thats fine
Attatch this script to your GridContainer
Alrighty, attaching it at the moment.
not the size of the child, yes?
Not sure if I setting it correctly...
Note that I haven't implemented this yet.
extends GridContainer
@export var snap_distance: float = 10
var initial_positions: Array[Vector2]: set = set_initial_positions
func _ready() -> void:
initial_positions = []
func snap() -> void:
for pos: Vector2 in initial_positions:
if global_position.y - snap_distance == pos.y:
global_position.y = snap_distance
func set_initial_positions(array: Array[Vector2]) -> void:
initial_positions = array
for child: Node in get_children():
initial_positions.append(child.global_position)
This is for your GridContainer
Attatch another script to your Parallax2D
And check for when the player releases
Then call snap() from your Parallax2D and set auto_scroll to Vector2.ZERO
Replacing this one?
Yea this one is better so you dont have to manually set the snap positions
What about this one?
Should I put it inside the GridContainer?
No create a separate script for your Parallax2D node and attach it to that
Ah, got it
I've already put it now on Parallax, but it pretty much doesn't do anything
(Even when I click and drag the panel