DVN/dvn.gd
2025-02-27 00:02:50 -05:00

316 lines
14 KiB
GDScript

@icon("res://dvn/dvn.png")
class_name DVNScene extends Node2D
## The DVNScene Node contains all of the built in functions of DVN, excluding those affecting text.
## Every scene in the DVN engine should extend DVNScene, imagine it as a base scene.
## Completely Invisible Color, if the alpha is increased it becomes [member Color.WHITE]
const TRANS_WHITE = Color(1,1,1,0)
## Completely Invisible Color, if the alpha is increased it becomes [member Color.BLACK]
const TRANS_BLACK = Color(0,0,0,0)
## Called when [method fade_out_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
signal screen_fade_out
## Called when [method fade_in_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
signal screen_fade_in
## Called when [method fade_out_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade_out
## Called when [method fade_in_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade_in
## Called when [method fade_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
signal bgm_fade
## Called when [method delay] has counted all the way down.
signal delay_ended
## Called when the sound created by [method play_sound] has finished playing.
## [br]NOTE: Will only be called if [param async] is false!!!
signal sound_ended
## Default ballon to create with [method create_text_balloon]
@export var Balloon: PackedScene = null
## Default ballon to start with [method create_text_balloon]
@export var Dialogue: DialogueResource = null
## Set the current dialogue automation type.
## [br]see [enum DialogueAutomationTypes] for more info
@export_enum("Manual", "Auto Text", "Auto Voice") var dialogue_automation_type: int
## [param] MANUAL is the default way of handling text. The next line of dialogue is not
## drawn until the user inputs a command.
## [br][param AUTO_TEXT] Automatically skips to the next text box after the [member auto_text_delay] timer is done counting down.
## [br][param AUTO_VOICE] Automatically skips to the next text box when the voice clip is done playing.
enum DialogueAutomationTypes{MANUAL,AUTO_TEXT,AUTO_VOICE}
## The wait time until new text is drawn when [member dialogue_automation_type] is set to auto voice.
@export var auto_text_delay:float = 1.0
## Default time value for fading the screen
@export var default_screen_fade_time: float = 2.0
## Default time value for fading the BGM
@export var default_bgm_fade_time: float = 2.0
## Reference to BGM Player
@onready var bgm = %BGM
## Reference to built in Animation Player
@onready var animation_player = $DVN/AnimationPlayer
## The volume of the BGM set in the editor, used
@onready var bgm_initial_volume = bgm.get_volume_db()
## The currently active text balloon, created from [method create_text_balloon]
var current_balloon = null
#region Text Functions
## Create a text balloon starting from [param title]
func create_text_balloon(title:String):
current_balloon = Balloon.instantiate()
add_child(current_balloon)
current_balloon.start(Dialogue,title)
## Wait a certain amount of [param time] until the next dialogue line is executed
func delay(time:float = 2.0):
await get_tree().create_timer(time).timeout
emit_signal("delay_ended")
screen_fade_out.connect(on_delay_ended)
## Switch the currently selected [DVNLabel]
## [br]If [param keep_text] is true than the previously selected [DVNLabel] will stay drawn
func switch_label(label,keep_text: bool = false):
if keep_text == false:
current_balloon.dialogue_label.text = ""
current_balloon.dialogue_label = label
## Move the selected [param label] to a specified [param position]
func move_label(label:PackedScene,position:Vector2):
current_balloon.dialogue_label.position = position
## Change the [param color] of the currently selected label
func change_text_color(color:Color):
current_balloon.dialogue_label.set_modulate(color)
## Set the current dialogue automation type.
## [br]see [enum DialogueAutomationTypes] for more info
func set_dialogue_automation_type(type:int):
dialogue_automation_type = type
## Set the text speed in seconds per step
func set_text_speed(speed:float=0.02):
current_balloon.dialogue_label.seconds_per_step = speed
## Called when the dialogue reaches an END block.
func dialogue_ended():
pass
#endregion
#region Voice Functions
## Set the current voice line position. Useful if you have a lot of different branches
## and loops in dialogue.
func set_voice_line(index:int):
current_balloon.dialogue_label.current_voice_line = index
## Set if speech sounds should play at all.
func set_can_speak(truefalse:bool=true):
current_balloon.dialogue_label.can_speak = truefalse
## Set the volume of the currently selected [DVNLabel]'s talktone player in db
func set_voice_volume(volume:float = 0.0):
current_balloon.dialogue_label.talktone_player.set_volume_db(volume)
#endregion
#region Screen Fade Functions
## Fades in the screen. This is achieved by interpolating the alpha of [DVNScene]'s [ColorRect].
## [br][br][param color] determines the color to fade in from.
## [br][param time] determines the amount of time for the fade to take.
## [br][param hold_time] determines the time to wait until the screen starts fading.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_in_screen(color:Color = Color.BLACK,time:float = default_screen_fade_time,hold_time:float = 0,async:bool = false):
%FadeColor.color = color
%FadeColor.color.a = 1.0
await get_tree().create_timer(hold_time).timeout
var tween = get_tree().create_tween()
tween.tween_property(%FadeColor, "color:a", 0.0, time).set_trans(Tween.TRANS_LINEAR)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("screen_fade_in")
screen_fade_out.connect(on_screen_fade_in)
## Fades out the screen. This is achieved by interpolating the alpha of [DVNScene]'s [ColorRect].
## [br][br][param color] determines the color to fade to.
## [br][param time] determines the amount of time for the fade to take.
## [br][param hold_time] determines the extra time to hold the faded color, until the fading is considered "finished".
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_out_screen(color:Color = Color.BLACK,time:float = default_screen_fade_time,hold_time:float = 0,async:bool = false):
%FadeColor.color = color
%FadeColor.color.a = 0.0
var tween = get_tree().create_tween()
tween.tween_property(%FadeColor, "color:a", 1.0, time).set_trans(Tween.TRANS_LINEAR)
if !async:
await get_tree().create_timer(time).timeout
await get_tree().create_timer(hold_time).timeout
emit_signal("screen_fade_in")
screen_fade_out.connect(on_screen_fade_in)
#endregion
#region BGM Fade Functions
## Fades out BGM. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_out_bgm(time:float = default_bgm_fade_time,async:bool = false):
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", -80, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade_out")
bgm_fade_in.connect(on_bgm_fade_in)
## Fades in BGM. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_in_bgm(time:float = default_bgm_fade_time,async:bool = false):
bgm.set_volume_db(-80)
bgm.play()
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", bgm_initial_volume, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade_in")
bgm_fade_in.connect(on_bgm_fade_in)
## Fades the BGM from its current value to [param end_volume]. This is achieved by interpolating the volume of [DVNScene]'s BGM [AudioStreamPlayer].
## [br][br][param time] determines the amount of time for the fade to take.
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
func fade_bgm(end_volume:float = 0.0,time:float = default_bgm_fade_time,async:bool = false):
var tween = get_tree().create_tween()
tween.tween_property(bgm, "volume_db", end_volume, time)
if !async:
await get_tree().create_timer(time).timeout
emit_signal("bgm_fade")
bgm_fade.connect(on_bgm_fade)
## Change BGM to [param stream]
func change_bgm(stream:AudioStream):
bgm.stream = stream
## Pause/Resume BGM
func pause_bgm(pause:bool = true):
bgm.set_stream_paused(pause)
## STOP BGM.
func stop_bgm():
bgm.stop()
## Play the BGM.
##[br]Different from setting [method pause_bgm] to false as this will start the stream from the beginning
func play_bgm():
bgm.play()
## Set the BGM Volume in db.
## [br]Does not fade, volume change is abrupt.
func set_bgm_volume(volume:float = 0.0):
bgm.set_volume_db(volume)
## Skip to a spot in the BGM. see [method AudioStreamPlayer.seek]
func seek_bgm(to_position:float = 0.0):
bgm.seek(to_position)
#endregion
#region SFX Functions
## Play a sound effect. Achieved by creating an [AudioStreamPlayer] and freeing it when it's done playing.
## [br][br]The specific [param sound] can be changed, along with its [param volume] and [param pitch].
## [br]if [param async] is true, the fade will be performed alongside other actions, otherwise, other actions won't be performed until the fading is finished.
## [br][br]The Sound effect will play from the SFX audio bus.
func play_sound(sound:AudioStream,volume:float,pitch:float,async:bool = true):
var sfx = load("res://dvn/sound_player/sound.tscn").instantiate()
sfx.stream = sound
sfx.set_volume_db(volume)
sfx.pitch_scale = pitch
add_child(sfx)
sfx.play()
if !async:
await get_tree().create_timer(sound.get_length()).timeout
emit_signal("sound_ended")
sound_ended.connect(on_sound_ended)
#endregion
#region Animation Functions
## Sets an [AnimationPlayer]'s [param speed].
## [br] by default this affects the [DVNScene]'s built in [AnimationPlayer]
## [br][br] see [method AnimationPlayer.set_speed_scale]
func set_animation_speed(speed:float = 1.0,player:Node = animation_player):
animation_player.set_speed_scale(1.0)
## Play an anim on your [AnimationPlayer].
## [br] by default this affects the [DVNScene]'s built in [AnimationPlayer]
## [br][br] see [method AnimationPlayer.play]
func play_animtion(animation:String,player = animation_player):
player.play(animation)
#endregion
#region Scene Functions
## Go to the next [param scene] from a node's path. [param example: "res://dvn/dvn.tscn"]
## [br]can be used to change the current scene to anything, but you generally want
## to use it to move to the next specific "scene" or "level"
func change_scene(scene:String):
get_tree().change_scene_to_file(scene)
## Ends the scene with a screen and BGM fade out. When the screen and BGM are done fading, the scene switches to [param next_scene]
## [br][param screen_fade_time] and [param bgm_fade_time] can be adjusted, though by default they are set to [member default_screen_fade_time] and [member default_bgm_fade_time]
## [br]You can set the default fade times in [DVNScene]'s exports.
## [br]Ideally this is the kind of function you can use to smoothly end a scene in one line.
func end_scene(next_scene:String,screen_fade_time:float = default_screen_fade_time,bgm_fade_time:float = default_bgm_fade_time):
#Determine whether to end on bgm fade or screen fade
var wait_time = 0.0
if bgm_fade_time > screen_fade_time:
wait_time = bgm_fade_time
else:
wait_time = screen_fade_time
#fade bgm and screen
fade_out_bgm(bgm_fade_time)
fade_out_screen(%FadeColor.color,screen_fade_time)
await get_tree().create_timer(wait_time).timeout #wait for bgm and screen to finish fading
change_scene(next_scene)
#endregion
#region Signals
## Called when [method delay] has counted all the way down.
func on_delay_ended():
pass
## Called when [method fade_out_sceen] has finished fading the screen and [param hold_time] has counted all the way down.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_screen_fade_out():
pass
## Called when [method fade_in_sceen] has finished fading the screen.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_screen_fade_in():
pass
## Called when the sound created by [method play_sound] has finished playing.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_sound_ended():
pass
## Called when [method fade_out_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade_out():
pass
## Called when [method fade_in_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade_in():
pass
## Called when [method fade_bgm] has finished fading.
## [br]NOTE: Will only be called if [param async] is false!!!
func on_bgm_fade():
pass
## Called when... when... when something happens. make good use of that [param anim_name]!!!
func _on_animation_player_animation_finished(anim_name: StringName) -> void:
pass # Replace with function body.
#endregion