Skip to content

Commit

Permalink
Combine Music/Sound event into single Audio event
Browse files Browse the repository at this point in the history
  • Loading branch information
salianifo committed Nov 25, 2024
1 parent 7e38e1d commit 3c2bd78
Show file tree
Hide file tree
Showing 15 changed files with 967 additions and 346 deletions.
41 changes: 41 additions & 0 deletions addons/dialogic/Core/DialogicResourceUtil.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@tool
class_name DialogicResourceUtil

static var channel_cache := {}
static var label_cache := {}
static var event_cache: Array[DialogicEvent] = []

Expand All @@ -11,6 +12,7 @@ static func update() -> void:
update_directory('.dch')
update_directory('.dtl')
update_label_cache()
update_channel_cache()


#region RESOURCE DIRECTORIES
Expand Down Expand Up @@ -139,6 +141,45 @@ static func update_label_cache() -> void:

#endregion

#region CHANNEL CACHE
################################################################################
# The channel cache is only for the editor so we don't have to scan all timelines
# whenever we want to suggest channels. This has no use in game and is not always perfect.

static func get_channel_cache() -> Dictionary:
if not channel_cache.is_empty():
return channel_cache

channel_cache = DialogicUtil.get_editor_setting('channel_ref', {})
return channel_cache


static func get_channel_list() -> Array:
if channel_cache.is_empty():
return []

var cached_names := []
for timeline in channel_cache:
for name in channel_cache[timeline]:
if not cached_names.has(name):
cached_names.append(name)
return cached_names


static func set_channel_cache(cache:Dictionary) -> void:
channel_cache = cache


static func update_channel_cache() -> void:
var cache := get_channel_cache()
var timelines := get_timeline_directory().values()
for timeline in cache:
if !timeline in timelines:
cache.erase(timeline)
set_channel_cache(cache)

#endregion

#region EVENT CACHE
################################################################################

Expand Down
87 changes: 87 additions & 0 deletions addons/dialogic/Core/DialogicUtil.gd
Original file line number Diff line number Diff line change
Expand Up @@ -682,3 +682,90 @@ static func get_portrait_position_suggestions(search_text := "") -> Dictionary:
suggestions.erase(search_text)

return suggestions


static func get_channel_suggestions(search_text:String, is_sync := false, event: DialogicAudioEvent = null) -> Dictionary:
if is_sync and event and event.channel_name.is_empty():
return {}

var suggestions := {}
var channel_defaults := DialogicUtil.get_channel_defaults()
var cached_names := DialogicResourceUtil.get_channel_list()

for i in channel_defaults.keys():
if not cached_names.has(i):
cached_names.append(i)

cached_names.sort()

for i in cached_names:
if i.is_empty():
if is_sync:
suggestions['(No Sync)'] = {
'value': i,
'editor_icon': ["GuiRadioUnchecked", "EditorIcons"],
}
else:
suggestions['(One-Shot SFX)'] = {
'value': i,
'editor_icon': ["GuiRadioUnchecked", "EditorIcons"],
'tooltip': "Used for one shot sounds effects. Plays each sound in its own AudioStreamPlayer."
}

elif is_sync and event and event.channel_name == i:
continue

elif i in channel_defaults.keys():
suggestions[i] = {
'value': i,
'editor_icon': ["Favorites", "EditorIcons"],
}

if not is_sync:
suggestions[i]['tooltip'] = 'This channel has default settings.'

else:
suggestions[i] = {
'value': i,
'editor_icon': ["AudioStream", "EditorIcons"],
}

return suggestions


static func get_channel_defaults() -> Dictionary:
return ProjectSettings.get_setting('dialogic/audio/channel_defaults', {
"": {
'volume': 0.0,
'audio_bus': '',
'fade_length': 0.0,
'loop': false,
},
"music": {
'volume': 0.0,
'audio_bus': '',
'fade_length': 0.0,
'loop': true,
}})


static var channel_name_regex := RegEx.create_from_string(r'(?<dash_only>^-$)|(?<invalid>[^\w-]{1})')
static func validate_channel_name(text: String) -> Dictionary:
var result := {}
var matches := channel_name_regex.search_all(text)
var invalid_chars := []

for regex_match in matches:
if regex_match.get_string('dash_only'):
result['error_tooltip'] = "Channel name cannot be '-'."
result['valid_text'] = ''
else:
var invalid_char = regex_match.get_string('invalid')
if not invalid_char in invalid_chars:
invalid_chars.append(invalid_char)

if invalid_chars:
result['valid_text'] = channel_name_regex.sub(text, '', true)
result['error_tooltip'] = "Channel names cannot contain the following characters: " + "".join(invalid_chars)

return result
84 changes: 81 additions & 3 deletions addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ extends DialogicVisualEditorField
## SETTINGS
@export var placeholder_text := "Select Resource"
@export var empty_text := ""
enum Modes {PURE_STRING, PRETTY_PATH, IDENTIFIER}
enum Modes {PURE_STRING, PRETTY_PATH, IDENTIFIER, ANY_VALID_STRING}
@export var mode := Modes.PURE_STRING
@export var fit_text_length := true
var collapse_when_empty := false
var valid_file_drop_extension := ""
var get_suggestions_func: Callable
var validation_func: Callable

var resource_icon: Texture = null:
get:
Expand All @@ -21,8 +22,13 @@ var resource_icon: Texture = null:
%Icon.texture = new_icon

## STATE
var current_value: String
var current_value: String:
set(value):
if current_value != value:
current_value = value
current_value_updated = true
var current_selected := 0
var current_value_updated := false

## SUGGESTIONS ITEM LIST
var _v_separation := 0
Expand All @@ -38,24 +44,27 @@ var _max_height := 200 * DialogicUtil.get_editor_scale()
func _set_value(value:Variant) -> void:
if value == null or value.is_empty():
%Search.text = empty_text
update_error_tooltip('')
else:
match mode:
Modes.PRETTY_PATH:
%Search.text = DialogicUtil.pretty_name(value)
Modes.IDENTIFIER when value.begins_with("res://"):
%Search.text = DialogicResourceUtil.get_unique_identifier(value)
Modes.ANY_VALID_STRING when validation_func:
%Search.text = validation_func.call(value).get('valid_text', value)
_:
%Search.text = str(value)

%Search.visible = not collapse_when_empty or value
current_value = str(value)



func _load_display_info(info:Dictionary) -> void:
valid_file_drop_extension = info.get('file_extension', '')
collapse_when_empty = info.get('collapse_when_empty', false)
get_suggestions_func = info.get('suggestions_func', get_suggestions_func)
validation_func = info.get('validation_func', validation_func)
empty_text = info.get('empty_text', '')
placeholder_text = info.get('placeholder', 'Select Resource')
mode = info.get("mode", 0)
Expand Down Expand Up @@ -101,16 +110,60 @@ func _ready() -> void:
if resource_icon == null:
self.resource_icon = null

var error_label_style := StyleBoxFlat.new()
error_label_style.bg_color = get_theme_color('background', 'Editor')
error_label_style.border_color = get_theme_color('error_color', 'Editor')
error_label_style.set_border_width_all(1)
error_label_style.set_corner_radius_all(4)
error_label_style.set_content_margin_all(6)

%ErrorTooltip.add_theme_stylebox_override('normal', error_label_style)


func change_to_empty() -> void:
update_error_tooltip('')
value_changed.emit(property_name, "")


func validate() -> void:
if mode == Modes.ANY_VALID_STRING:
if validation_func:
var validation_result := validation_func.call(current_value)
current_value = validation_result.get('valid_text', current_value)
update_error_tooltip(validation_result.get('error_tooltip', ''))


func update_error_tooltip(text: String) -> void:
%ErrorTooltip.text = text
if text.is_empty():
%ErrorTooltip.hide()
%Search.remove_theme_color_override("font_color")
else:
%ErrorTooltip.reset_size()
%ErrorTooltip.global_position = global_position - Vector2(0, %ErrorTooltip.size.y + 4)
%ErrorTooltip.show()
%Search.add_theme_color_override("font_color", get_theme_color('error_color', 'Editor'))

#endregion


#region SEARCH & SUGGESTION POPUP
################################################################################

func _on_Search_text_entered(new_text:String) -> void:
if mode == Modes.ANY_VALID_STRING:
if validation_func:
var validation_result := validation_func.call(new_text)
new_text = validation_result.get('valid_text', new_text)
update_error_tooltip(validation_result.get('error_tooltip', ''))

set_value(new_text)

value_changed.emit(property_name, current_value)
current_value_updated = false
hide_suggestions()
return

if %Suggestions.get_item_count():
if %Suggestions.is_anything_selected():
suggestion_selected(%Suggestions.get_selected_items()[0])
Expand All @@ -128,10 +181,27 @@ func _on_Search_text_changed(new_text:String, just_update:bool = false) -> void:
else:
%Search.show()

if mode == Modes.ANY_VALID_STRING and !just_update:
if validation_func:
var validation_result := validation_func.call(new_text)
new_text = validation_result.get('valid_text', new_text)
update_error_tooltip(validation_result.get('error_tooltip', ''))

current_value = new_text

var suggestions: Dictionary = get_suggestions_func.call(new_text)

var line_length := 0
var idx := 0

if new_text and mode == Modes.ANY_VALID_STRING and not new_text in suggestions.keys():
%Suggestions.add_item(new_text, get_theme_icon('GuiScrollArrowRight', 'EditorIcons'))
%Suggestions.set_item_metadata(idx, new_text)
line_length = get_theme_font('font', 'Label').get_string_size(
new_text, HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size", 'Label')
).x + %Suggestions.fixed_icon_size.x * %Suggestions.get_icon_scale() + _icon_margin * 2 + _h_separation
idx += 1

for element in suggestions:
if new_text.is_empty() or new_text.to_lower() in element.to_lower() or new_text.to_lower() in str(suggestions[element].value).to_lower() or new_text.to_lower() in suggestions[element].get('tooltip', '').to_lower():
var curr_line_length: int = 0
Expand Down Expand Up @@ -196,10 +266,12 @@ func suggestion_selected(index: int, position := Vector2(), button_index := MOUS
else:
current_value = %Suggestions.get_item_metadata(index)

update_error_tooltip('')
hide_suggestions()

grab_focus()
value_changed.emit(property_name, current_value)
current_value_updated = false


func _input(event:InputEvent) -> void:
Expand Down Expand Up @@ -256,12 +328,17 @@ func _on_search_focus_entered() -> void:
_on_Search_text_changed("")
%Search.call_deferred('select_all')
%Focus.show()
validate()


func _on_search_focus_exited() -> void:
%Focus.hide()
if !%Suggestions.get_global_rect().has_point(get_global_mouse_position()):
hide_suggestions()
validate()
if current_value_updated:
value_changed.emit(property_name, current_value)
current_value_updated = false

#endregion

Expand All @@ -285,5 +362,6 @@ func _drop_data(position:Vector2, data:Variant) -> void:
path = DialogicResourceUtil.get_unique_identifier(path)
_set_value(path)
value_changed.emit(property_name, path)
current_value_updated = false

#endregion
10 changes: 9 additions & 1 deletion addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,17 @@ mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_g74jb")
metadata/_edit_use_anchors_ = true

[node name="ErrorTooltip" type="Label" parent="PanelContainer/Focus"]
unique_name_in_owner = true
visible = false
top_level = true
layout_mode = 0
offset_left = -2.0
offset_top = -44.5
offset_right = 11.0
offset_bottom = -9.5
[connection signal="focus_entered" from="." to="." method="_on_focus_entered"]
[connection signal="focus_entered" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_entered"]
[connection signal="focus_exited" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_exited"]
[connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_gui_input"]
[connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search/Suggestions" to="." method="_on_suggestions_gui_input"]
[connection signal="toggled" from="PanelContainer/MarginContainer/HBoxContainer/SelectButton" to="." method="_on_SelectButton_toggled"]
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extends CodeEdit
@onready var code_completion_helper: Node= find_parent('EditorsManager').get_node('CodeCompletionHelper')

var label_regex := RegEx.create_from_string('label +(?<name>[^\n]+)')
var channel_regex := RegEx.create_from_string(r'audio +(?<channel>[\w-]{2,}|[\w]+)')

func _ready() -> void:
await find_parent('EditorView').ready
Expand Down Expand Up @@ -211,6 +212,11 @@ func update_content_list() -> void:
labels.append(i.get_string('name'))
timeline_editor.editors_manager.sidebar.update_content_list(labels)

var channels: PackedStringArray = []
for i in channel_regex.search_all(text):
channels.append(i.get_string('channel'))
timeline_editor.update_channel_cache(channels)


func _on_content_item_clicked(label:String) -> void:
if label == "~ Top":
Expand Down
Loading

0 comments on commit 3c2bd78

Please sign in to comment.