Advice for adding 3D objects to 2D menu

Godot Version

4.6.3

Question

Hi, I need some advice on how to change this menu I got from a tutorial into one that stays 2D but uses 3D objects in sub viewports, I also want the selected object to be able to be rotated with the mouse but that’s an extra thing.

i have screenshots of the current layout along with the code

extends Control

@export var radius_x: float = 420.0
@export var radius_y: float = 120.0
@export var center_offset: Vector2 = Vector2(0, 0)

@export var front_scale: float = 1.35
@export var back_scale: float = 0.65
@export var side_alpha: float = 0.55
@export var tween_time: float = 0.25

@onready var items_root: Control = $items
@onready var label: Label = $Label

var items: Array[Button] = []
var selected_index: int = 0
var active_tween: Tween


func _ready() -> void:
	items.assign(items_root.get_children())
	
	for i in items.size():
		var button := items [i]
		button.pivot_offset = button.size * 0.5
		button.focus_mode = Control.FOCUS_NONE
		button.pressed.connect(_on_button_pressed.bind(i))
	
	_update_carousel(false)


func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("ui_right"):
		_move_selection(1)
	elif event.is_action_pressed("ui_left"):
		_move_selection(-1)
	elif event.is_action_pressed("ui_accept"):
		_activate_selected()


func _move_selection(direction: int) -> void:
	selected_index = wrapi(selected_index + direction, 0, items.size())
	_update_carousel(true)


func _update_carousel(animated: bool) -> void:
	if active_tween:
		active_tween.kill()
		active_tween = null

	if animated:
		active_tween = create_tween()
		active_tween.set_parallel(true)

	var center := size * 0.5 + center_offset
	
	for i in items.size():
		var button := items[i]
		var offset := _get_wrapped_offset(i - selected_index)
		var angle := offset * TAU / float(items.size())
		
		var depth := cos(angle)
		var x := sin(angle) * radius_x
		var y := -depth * radius_y
		
		var depth_normalized := inverse_lerp(-1.0, 1.0, depth)
		var scale_value := (lerp(back_scale, front_scale, depth_normalized) as float)
		var alpha_value = lerp(side_alpha, 1.0, depth_normalized)
		
		var target_position := center + Vector2(x,y) - button.size * 0.5
		var target_scale := Vector2.ONE * scale_value
		var target_rotation := deg_to_rad(-sin(angle) * 8.0)
		
		button.z_index = int(depth_normalized * 100.0)
		button.disabled = i != selected_index
		
		if animated:
			active_tween.tween_property(button, "position", target_position, tween_time)\
				.set_trans(Tween.TRANS_CUBIC)\
				.set_ease(Tween.EASE_OUT)
			active_tween.tween_property(button, "scale" , target_scale, tween_time)\
				.set_trans(Tween.TRANS_CUBIC)\
				.set_ease(Tween.EASE_OUT)
			active_tween.tween_property(button, "rotation", target_rotation, tween_time)\
				.set_trans(Tween.TRANS_CUBIC)\
				.set_ease(Tween.EASE_OUT)
			active_tween.tween_property(button, "modulate:a", alpha_value, tween_time)
		else:
			button.position = target_position
			button.scale = target_scale
			button.rotation = target_rotation
			button.modulate.a = alpha_value
	
	label.text = items[selected_index].text


func _get_wrapped_offset(offset: int) -> int:
	var half := floori(items.size()) /2
	
	if offset > half:
		offset -+ items.size()
	elif offset < -half:
		offset += items.size()
	
	return offset


func _activate_selected() -> void:
	match items[selected_index].name:
		"PlayButton":
			print("Play")
		"OptionsButton":
			print("Options")
		"ExtrasButton":
			print("extras")
		"CreditsButton":
			print("Credits")
		"QuitButton":
			get_tree().quit()


func _on_button_pressed(index: int) -> void:
	selected_index = index
	_update_carousel(true)
	_activate_selected()

I ideally need to be able to add more objects to the index as I’m not sure how many objects I will end up with.

any help would greatly appreciated.

Seems like you can add more buttons to the items node, like all the others.

Are you running into any errors? What have you tried doing?

sorry for the long space between replies ,

I have tried replacing the buttons in the scene tree with sub viewport containers as i think they would need to be the ones enclosing the other nodes (node3D or Camera3D) but i get an error and two yellow warnings?

I’m not really sure if I’m going about this the right way

thanks