seeding-planets/addons/dialogic/Modules/Audio/settings_audio.gd

242 lines
7.2 KiB
GDScript

@tool
extends DialogicSettingsPage
## Settings page that contains settings for the audio subsystem
const TYPE_SOUND_AUDIO_BUS := "dialogic/audio/type_sound_bus"
const CHANNEL_DEFAULTS := "dialogic/audio/channel_defaults"
var channel_defaults := {}
var _revalidate_channel_names := false
func _ready() -> void:
%TypeSoundBus.item_selected.connect(_on_type_sound_bus_item_selected)
$Panel.add_theme_stylebox_override('panel', get_theme_stylebox("Background", "EditorStyles"))
func _refresh() -> void:
%TypeSoundBus.clear()
var idx := 0
for i in range(AudioServer.bus_count):
%TypeSoundBus.add_item(AudioServer.get_bus_name(i))
if AudioServer.get_bus_name(i) == ProjectSettings.get_setting(TYPE_SOUND_AUDIO_BUS, ""):
idx = i
%TypeSoundBus.select(idx)
load_channel_defaults(DialogicUtil.get_audio_channel_defaults())
func _about_to_close() -> void:
save_channel_defaults()
## TYPE SOUND AUDIO BUS
func _on_type_sound_bus_item_selected(index:int) -> void:
ProjectSettings.set_setting(TYPE_SOUND_AUDIO_BUS, %TypeSoundBus.get_item_text(index))
ProjectSettings.save()
#region AUDIO CHANNELS
################################################################################
func load_channel_defaults(dictionary:Dictionary) -> void:
channel_defaults.clear()
for i in %AudioChannelDefaults.get_children():
i.queue_free()
var column_names := [
"Channel Name",
"Volume",
"Audio Bus",
"Fade",
"Loop",
""
]
for column in column_names:
var label := Label.new()
label.text = column
label.theme_type_variation = 'DialogicHintText2'
%AudioChannelDefaults.add_child(label)
var channel_names := dictionary.keys()
channel_names.sort()
for channel_name in channel_names:
add_channel_defaults(
channel_name,
dictionary[channel_name].volume,
dictionary[channel_name].audio_bus,
dictionary[channel_name].fade_length,
dictionary[channel_name].loop)
await get_tree().process_frame
_revalidate_channel_names = true
revalidate_channel_names.call_deferred()
func save_channel_defaults() -> void:
var dictionary := {}
for i in channel_defaults:
if is_instance_valid(channel_defaults[i].channel_name):
var channel_name := ""
if not channel_defaults[i].channel_name is Label:
if channel_defaults[i].channel_name.current_value.is_empty():
continue
channel_name = channel_defaults[i].channel_name.current_value
#channel_name = DialogicUtil.channel_name_regex.sub(channel_name, '', true)
if channel_name.is_empty():
dictionary[channel_name] = {
'volume': channel_defaults[i].volume.get_value(),
'audio_bus': channel_defaults[i].audio_bus.current_value,
'fade_length': 0.0,
'loop': false,
}
else:
dictionary[channel_name] = {
'volume': channel_defaults[i].volume.get_value(),
'audio_bus': channel_defaults[i].audio_bus.current_value,
'fade_length': channel_defaults[i].fade_length.get_value(),
'loop': channel_defaults[i].loop.button_pressed,
}
ProjectSettings.set_setting(CHANNEL_DEFAULTS, dictionary)
ProjectSettings.save()
func _on_add_channel_defaults_pressed() -> void:
var added_node := add_channel_defaults('new_channel_name', 0.0, '', 0.0, true)
if added_node:
added_node.take_autofocus()
_revalidate_channel_names = true
revalidate_channel_names.call_deferred()
func add_channel_defaults(channel_name: String, volume: float, audio_bus: String, fade_length: float, loop: bool) -> Control:
var info := {}
for i in %AudioChannelDefaultRow.get_children():
var x := i.duplicate()
%AudioChannelDefaults.add_child(x)
info[i.name] = x
if channel_name.is_empty():
var channel_label := Label.new()
channel_label.text = &"One-Shot SFX"
channel_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
%AudioChannelDefaults.add_child(channel_label)
%AudioChannelDefaults.move_child(channel_label, info.channel_name.get_index())
info.channel_name.queue_free()
info.channel_name = channel_label
var HintTooltip := preload("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn")
var fade_hint := HintTooltip.instantiate()
fade_hint.hint_text = "Fading is disabled for this channel."
%AudioChannelDefaults.add_child(fade_hint)
%AudioChannelDefaults.move_child(fade_hint, info.fade_length.get_index())
info.fade_length.queue_free()
info.fade_length = fade_hint
var loop_hint := HintTooltip.instantiate()
loop_hint.hint_text = "Looping is disabled for this channel."
%AudioChannelDefaults.add_child(loop_hint)
%AudioChannelDefaults.move_child(loop_hint, info.loop.get_index())
info.loop.queue_free()
info.loop = loop_hint
info.delete.disabled = true
else:
info.channel_name.suggestions_func = get_audio_channel_suggestions
info.channel_name.validation_func = validate_channel_names.bind(info.channel_name)
info.channel_name.set_value(channel_name)
info.fade_length.set_value(fade_length)
info.loop.set_pressed_no_signal(loop)
info.audio_bus.suggestions_func = DialogicUtil.get_audio_bus_suggestions
info.audio_bus.set_value(audio_bus)
info.delete.icon = get_theme_icon(&"Remove", &"EditorIcons")
channel_defaults[len(channel_defaults)] = info
return info['channel_name']
func _on_remove_channel_defaults_pressed(index: int) -> void:
for key in channel_defaults[index]:
channel_defaults[index][key].queue_free()
channel_defaults.erase(index)
func get_audio_channel_suggestions(search_text:String) -> Dictionary:
var suggestions := DialogicUtil.get_audio_channel_suggestions(search_text)
for i in channel_defaults.values():
if i.channel_name is DialogicVisualEditorField:
suggestions.erase(i.channel_name.current_value)
for key in suggestions.keys():
suggestions[key].erase('tooltip')
suggestions[key]['editor_icon'] = ["AudioStreamPlayer", "EditorIcons"]
return suggestions
func revalidate_channel_names() -> void:
_revalidate_channel_names = false
for i in channel_defaults:
if (is_instance_valid(channel_defaults[i].channel_name)
and not channel_defaults[i].channel_name is Label):
channel_defaults[i].channel_name.validate()
func validate_channel_names(search_text: String, field_node: Control) -> Dictionary:
var channel_cache = {}
var result := {}
var tooltips := []
if search_text.is_empty():
result['error_tooltip'] = 'Must not be empty.'
return result
if field_node:
channel_cache[search_text] = [field_node]
if field_node.current_value != search_text:
_revalidate_channel_names = true
revalidate_channel_names.call_deferred()
# Collect all channel names entered
for i in channel_defaults:
if (is_instance_valid(channel_defaults[i].channel_name)
and not channel_defaults[i].channel_name is Label
and channel_defaults[i].channel_name != field_node):
var text := channel_defaults[i].channel_name.current_value as String
if not channel_cache.has(text):
channel_cache[text] = []
channel_cache[text].append(channel_defaults[i].channel_name)
# Check for duplicate names
if channel_cache.has(search_text) and channel_cache[search_text].size() > 1:
tooltips.append("Duplicate channel name.")
# Check for invalid characters
result = DialogicUtil.validate_audio_channel_name(search_text)
if result:
tooltips.append(result.error_tooltip)
result.error_tooltip = "\n".join(tooltips)
elif not tooltips.is_empty():
result['error_tooltip'] = "\n".join(tooltips)
return result
#endregion