Interesting puzzle with Instantiating menu items for audio

Godot Version

extends Control
@onready var audio_bus_node = preload("res://ScreenUI&Menus/branch_system/audio_bus.tscn")
@onready var action_list = $PanelContainer/ScrollContainer/VBoxContainer/ActionList as VBoxContainer

var audio_bus_name = ["Master", "Music", "Sfx"]
var bus_index=0

func _ready():
	_create_action_list()
	get_bus_name_by_index()
	on_volume_change()

func _create_action_list()->void:
	for item in action_list.get_children():
		item.queue_free()
	for audio_name in audio_bus_name:
		var node=audio_bus_node.instantiate()
		var audio_name_label=node.find_child("Bus Label")
		var volume_slider=node.find_child("Volume Slider")
		var audio_number_label=node.find_child("Volume Label")

		node.set_name(audio_name)
		bus_index=AudioServer.get_bus_index(str(audio_name))
		print(bus_index) #prints 0,1,2 (functional)
		audio_name_label.text = audio_name+" Volume"
		volume_slider.value=db_to_linear(AudioServer.get_bus_volume_db(bus_index)) #its working!
		audio_number_label.text = str(volume_slider.value*100)+ "%"
		action_list.add_child(node)

func get_bus_name_by_index()->void:
	var indices=[]
	for audio_name in audio_bus_name:
		bus_index=AudioServer.get_bus_index(str(audio_name))
		indices.append(bus_index)
		print (bus_index) #adding indicies to it prints 0,1,2.. I dont think this makes a difference

func on_volume_change()->void:
	for audio_name in action_list.get_children():
		var node= audio_name
		var volume_slider=node.find_child("Volume Slider")
##problem here (it is sending out all three when I want it to only send out the signal for a specific volume slider)
		volume_slider.value_changed.connect(set_volume)
		print(volume_slider) #checks the slider
		print(set_volume) #checks the value

func set_volume(value:float)->void:
	for audio in action_list.get_children():
		print(audio)
		AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))
		print(value)

Question

I was messing about with code and after getting my hokeys set I started working on Audio. I was trying to do it in a similar way to my hotkeys but quickly learned that the Audio Bus doesnt quite operate the same way. It almost works (incomplete at this moment as I keep adding/deleting things). My Hsliders do recognize the 3 nodes that are made and they do change value, but the problem is that it doesnt matter which slider I mode as it changes the value of all 3 nodes at the same time. its like no matter which Hslider I use they all send the same uniform signal and don;t have a unique ID(but my print says they do?). I am gonna change the code so the Hslider script (and related scripts) are on the nodes themselves that are instantiated. This will solve the problem I believe but I was curious about other peoples inputs.

If the audio_bus_nodes are always in the same order, you can modify the code like this:

func on_volume_change() -> void:
	for i in action_list.get_child_count():
		var node = action_list.get_child(i)
		var volume_slider = node.find_child("Volume Slider")
		volume_slider.value_changed.connect(set_volume.bind(i))

func set_volume(value: float, index: int) -> void:
	AudioServer.set_bus_volume_db(index, linear_to_db(value))

If the number or order of audio_bus_nodes can change, then bus_index should be a member of the audio_bus_node.

You never change the bus_index variable in the set_volume() method so it’s always using the last bus you pass in _create_action_list()

You can make it less error prone by Callable.bind()ing the bus index when connecting the signal.

extends Control
@onready var audio_bus_node = preload("res://ScreenUI&Menus/branch_system/audio_bus.tscn")
@onready var action_list = $PanelContainer/ScrollContainer/VBoxContainer/ActionList as VBoxContainer

var audio_bus_name = ["Master", "Music", "Sfx"]


func _ready():
	_create_action_list()


func _create_action_list()->void:
	for item in action_list.get_children():
		item.queue_free()
	for audio_name in audio_bus_name:
		var node=audio_bus_node.instantiate()
		var audio_name_label=node.find_child("Bus Label")
		var volume_slider=node.find_child("Volume Slider")
		var audio_number_label=node.find_child("Volume Label")

		var bus_index=AudioServer.get_bus_index(str(audio_name))
		node.set_name(audio_name)
		
		audio_name_label.text = audio_name+" Volume"
		
		volume_slider.value=db_to_linear(AudioServer.get_bus_volume_db(bus_index)) #its working!
		volume_slider.value_changed.connect(set_volume.bind(bus_index))
		
		audio_number_label.text = str(volume_slider.value*100)+ "%"
		action_list.add_child(node)
		
		
func set_volume(value:float, bus_index:int) -> void:
	AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))

I tried both methods and it seems the H.Slider was still giving values in all 3 nodes no matter what I tried. I just went with the good old fashion divide and conquer route. I planned on it when all else fails, but this is what the code looks like.


extends Control

@onready var audio_bus_node = preload("res://ScreenUI&Menus/branch_system/audio_bus.tscn")
@onready var action_list = $PanelContainer/ScrollContainer/VBoxContainer/ActionList as VBoxContainer

var audio_bus_name = ["Master", "Music", "Sfx"]
var bus_index=0

func _ready():
	_create_action_list()

func _create_action_list()->void:
	for item in action_list.get_children():
		item.queue_free()
	for audio_name in audio_bus_name:
		var node=audio_bus_node.instantiate()
		var audio_name_label=node.find_child("Bus Label")
		var volume_slider=node.find_child("Volume Slider")
		var audio_number_label=node.find_child("Volume Label")

		node.set_name(audio_name)
		bus_index=AudioServer.get_bus_index(str(audio_name))
		audio_name_label.text = audio_name+" Volume"
		volume_slider.value=db_to_linear(AudioServer.get_bus_volume_db(bus_index)) #its working!
		audio_number_label.text = str(volume_slider.value*100)+ "%"
		action_list.add_child(node)

The part above creates the Audio nodes and labels everything for me
The part below takes the name and matches it to the index number
I think this is what both of you were trying to tell me to do but technically my problem wasnt the index, it was the Hslider(volume_slider) that changed the value of all 3 volumes at the same time. The new nodes that are generated from the above code all 3 seperate children running all thier own scripts so the H.sliders(volume_slider) are individual (no longer all sending a signal through the same connection).


extends Control

@onready var audio_bus_name_label = $"HBoxContainer/Bus Label" as Label
@onready var volume_slider = $"HBoxContainer/Volume Slider" as HSlider
@onready var audio_number_label = $"HBoxContainer/Volume Label" as Label

var audio_bus_name = ["Master", "Music", "Sfx"]
var bus_index=0

func _ready():
	volume_slider.value_changed.connect(on_volume_change)
	_set_audio_bus_name()

func _set_audio_bus_name()->void:
	audio_bus_name=name

func set_slider_value()->void:
	volume_slider.value=db_to_linear(AudioServer.get_bus_volume_db(bus_index))
	_set_audio_number_label_text()

func on_volume_change(value:float)->void:
	AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))
	_set_audio_number_label_text()
	print(value)

func _set_audio_number_label_text()->void:
	audio_number_label.text=str(int(volume_slider.value*100))+ "%"

This works for me, I am curious on thoughts on how to fix the H.slider(volume_slider) problem. The bind didnt seem to care as all 3 sliders values changed no matter which one I moved.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.