initial commit.
This commit is contained in:
commit
2ae288a3d6
|
@ -0,0 +1,17 @@
|
||||||
|
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ase filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.atex filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tex filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.vs filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pdn filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.aseprite filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.scn filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.res filter=lfs diff=lfs merge=lfs -text
|
|
@ -0,0 +1,3 @@
|
||||||
|
.import
|
||||||
|
.cache
|
||||||
|
*.*.s??
|
|
@ -0,0 +1,55 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
# globals, for the game
|
||||||
|
var reading_speed = 1.0
|
||||||
|
|
||||||
|
var game_started = false setget _on_game_started_set
|
||||||
|
|
||||||
|
var current_registry
|
||||||
|
|
||||||
|
# music related
|
||||||
|
onready var music_player = get_node("music_player")
|
||||||
|
onready var sfx_player = get_node("sfx_player")
|
||||||
|
|
||||||
|
signal on_music_volume_changed(new_value)
|
||||||
|
signal on_sfx_volume_changed(new_value)
|
||||||
|
signal on_reading_speed_changed(new_value)
|
||||||
|
|
||||||
|
signal on_settings_enter()
|
||||||
|
signal on_settings_exit()
|
||||||
|
|
||||||
|
const Themes = {}
|
||||||
|
|
||||||
|
# voices for characters
|
||||||
|
const brain_voice = null
|
||||||
|
const arborator_voice = null
|
||||||
|
|
||||||
|
const Characters = {
|
||||||
|
BRAIN = {
|
||||||
|
name = "~brain~",
|
||||||
|
voice = brain_voice,
|
||||||
|
talking_speed = 1.0,
|
||||||
|
},
|
||||||
|
ARBORATOR = {
|
||||||
|
name = "arborator",
|
||||||
|
voice = arborator_voice,
|
||||||
|
talking_speed = 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _register_functions():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_game_started_set(v):
|
||||||
|
if v and not game_started:
|
||||||
|
_on_game_start()
|
||||||
|
game_started = v
|
||||||
|
|
||||||
|
func _on_game_start():
|
||||||
|
|
||||||
|
# all game state here
|
||||||
|
current_registry = {}
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
|
@ -0,0 +1,23 @@
|
||||||
|
[gd_resource type="AudioBusLayout" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
|
||||||
|
bus/0/name = "Master"
|
||||||
|
bus/0/solo = false
|
||||||
|
bus/0/mute = false
|
||||||
|
bus/0/bypass_fx = false
|
||||||
|
bus/0/volume_db = 0.0
|
||||||
|
bus/0/send = ""
|
||||||
|
bus/1/name = "Music"
|
||||||
|
bus/1/solo = false
|
||||||
|
bus/1/mute = false
|
||||||
|
bus/1/bypass_fx = false
|
||||||
|
bus/1/volume_db = 0.0
|
||||||
|
bus/1/send = "Master"
|
||||||
|
bus/2/name = "Sfx"
|
||||||
|
bus/2/solo = false
|
||||||
|
bus/2/mute = false
|
||||||
|
bus/2/bypass_fx = false
|
||||||
|
bus/2/volume_db = 0.0
|
||||||
|
bus/2/send = "Master"
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
[gd_resource type="Environment" load_steps=2 format=2]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSky" id=1]
|
||||||
|
|
||||||
|
radiance_size = 4
|
||||||
|
sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 )
|
||||||
|
sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 )
|
||||||
|
sky_curve = 0.25
|
||||||
|
sky_energy = 1.0
|
||||||
|
ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 )
|
||||||
|
ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 )
|
||||||
|
ground_curve = 0.01
|
||||||
|
ground_energy = 1.0
|
||||||
|
sun_color = Color( 1, 1, 1, 1 )
|
||||||
|
sun_latitude = 35.0
|
||||||
|
sun_longitude = 0.0
|
||||||
|
sun_angle_min = 1.0
|
||||||
|
sun_angle_max = 100.0
|
||||||
|
sun_curve = 0.05
|
||||||
|
sun_energy = 16.0
|
||||||
|
texture_size = 2
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
|
||||||
|
background_mode = 2
|
||||||
|
background_sky = SubResource( 1 )
|
||||||
|
background_sky_custom_fov = 0.0
|
||||||
|
background_color = Color( 0, 0, 0, 1 )
|
||||||
|
background_energy = 1.0
|
||||||
|
background_canvas_max_layer = 0
|
||||||
|
ambient_light_color = Color( 0, 0, 0, 1 )
|
||||||
|
ambient_light_energy = 1.0
|
||||||
|
ambient_light_sky_contribution = 1.0
|
||||||
|
fog_enabled = false
|
||||||
|
fog_color = Color( 0.5, 0.6, 0.7, 1 )
|
||||||
|
fog_sun_color = Color( 1, 0.9, 0.7, 1 )
|
||||||
|
fog_sun_amount = 0.0
|
||||||
|
fog_depth_enabled = true
|
||||||
|
fog_depth_begin = 10.0
|
||||||
|
fog_depth_curve = 1.0
|
||||||
|
fog_transmit_enabled = false
|
||||||
|
fog_transmit_curve = 1.0
|
||||||
|
fog_height_enabled = false
|
||||||
|
fog_height_min = 0.0
|
||||||
|
fog_height_max = 100.0
|
||||||
|
fog_height_curve = 1.0
|
||||||
|
tonemap_mode = 0
|
||||||
|
tonemap_exposure = 1.0
|
||||||
|
tonemap_white = 1.0
|
||||||
|
auto_exposure_enabled = false
|
||||||
|
auto_exposure_scale = 0.4
|
||||||
|
auto_exposure_min_luma = 0.05
|
||||||
|
auto_exposure_max_luma = 8.0
|
||||||
|
auto_exposure_speed = 0.5
|
||||||
|
ss_reflections_enabled = false
|
||||||
|
ss_reflections_max_steps = 64
|
||||||
|
ss_reflections_fade_in = 0.15
|
||||||
|
ss_reflections_fade_out = 2.0
|
||||||
|
ss_reflections_depth_tolerance = 0.2
|
||||||
|
ss_reflections_roughness = true
|
||||||
|
ssao_enabled = false
|
||||||
|
ssao_radius = 1.0
|
||||||
|
ssao_intensity = 1.0
|
||||||
|
ssao_radius2 = 0.0
|
||||||
|
ssao_intensity2 = 1.0
|
||||||
|
ssao_bias = 0.01
|
||||||
|
ssao_light_affect = 0.0
|
||||||
|
ssao_color = Color( 0, 0, 0, 1 )
|
||||||
|
ssao_quality = 0
|
||||||
|
ssao_blur = 3
|
||||||
|
ssao_edge_sharpness = 4.0
|
||||||
|
dof_blur_far_enabled = false
|
||||||
|
dof_blur_far_distance = 10.0
|
||||||
|
dof_blur_far_transition = 5.0
|
||||||
|
dof_blur_far_amount = 0.1
|
||||||
|
dof_blur_far_quality = 1
|
||||||
|
dof_blur_near_enabled = false
|
||||||
|
dof_blur_near_distance = 2.0
|
||||||
|
dof_blur_near_transition = 1.0
|
||||||
|
dof_blur_near_amount = 0.1
|
||||||
|
dof_blur_near_quality = 1
|
||||||
|
glow_enabled = false
|
||||||
|
glow_levels/1 = false
|
||||||
|
glow_levels/2 = false
|
||||||
|
glow_levels/3 = true
|
||||||
|
glow_levels/4 = false
|
||||||
|
glow_levels/5 = true
|
||||||
|
glow_levels/6 = false
|
||||||
|
glow_levels/7 = false
|
||||||
|
glow_intensity = 0.8
|
||||||
|
glow_strength = 1.0
|
||||||
|
glow_bloom = 0.0
|
||||||
|
glow_blend_mode = 2
|
||||||
|
glow_hdr_threshold = 1.0
|
||||||
|
glow_hdr_scale = 2.0
|
||||||
|
glow_bicubic_upscale = false
|
||||||
|
adjustment_enabled = false
|
||||||
|
adjustment_brightness = 1.0
|
||||||
|
adjustment_contrast = 1.0
|
||||||
|
adjustment_saturation = 1.0
|
||||||
|
|
|
@ -0,0 +1,450 @@
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
# load from dialog vm
|
||||||
|
const Dialog = preload("res://dialog_vm.gd")
|
||||||
|
const DialogController = preload("res://dialog_controller.gd")
|
||||||
|
|
||||||
|
# classes from there
|
||||||
|
const DialogSegment = Dialog.DialogSegment
|
||||||
|
const DialogWithSubjectSegment = Dialog.DialogWithSubjectSegment
|
||||||
|
const DialogWithSubjectExpressionSegment = Dialog.DialogWithSubjectExpressionSegment
|
||||||
|
const QuestionSegment = Dialog.QuestionSegment
|
||||||
|
const ChoiceSegment = Dialog.ChoiceSegment
|
||||||
|
const ChoiceWithJump = Dialog.ChoiceWithJump
|
||||||
|
const Choice = Dialog.Choice
|
||||||
|
|
||||||
|
const WaitSegment = Dialog.YieldCallSegment
|
||||||
|
|
||||||
|
# resources specific to this dialogy thingy
|
||||||
|
const DialogChoices = preload("res://ui/dialog_choices.tscn")
|
||||||
|
const DialogChoice = preload("res://ui/dialog_choice.tscn")
|
||||||
|
|
||||||
|
var IS_DEBUG = false
|
||||||
|
|
||||||
|
var current_dialog
|
||||||
|
var current_dialog_controller
|
||||||
|
|
||||||
|
# ui elements
|
||||||
|
onready var advance_button = get_node("top_panel/auto_btn")
|
||||||
|
onready var fastforward_button = get_node("top_panel/ffwd_btn")
|
||||||
|
|
||||||
|
onready var title_label = get_node("body_container/bottom_panel/subject_margin/subject_panel/subject_label")
|
||||||
|
onready var body_container = get_node("body_container")
|
||||||
|
onready var body_label = get_node("body_container/bottom_panel/body_margin/body_label")
|
||||||
|
|
||||||
|
# clickable regions, for accessibility
|
||||||
|
onready var top_panel = get_node("top_panel")
|
||||||
|
|
||||||
|
onready var audio_player = get_node("audio_player")
|
||||||
|
|
||||||
|
# params to set from outside
|
||||||
|
var dialog_path
|
||||||
|
|
||||||
|
# activeness
|
||||||
|
var active
|
||||||
|
|
||||||
|
# tween to fade in/out
|
||||||
|
var tween
|
||||||
|
|
||||||
|
# timer
|
||||||
|
var timer
|
||||||
|
|
||||||
|
# anim player, if any
|
||||||
|
var anim_player
|
||||||
|
|
||||||
|
# linkin in ur get_node relative to where you want
|
||||||
|
var get_node_fnc
|
||||||
|
|
||||||
|
# various main dialog related constants
|
||||||
|
|
||||||
|
# signals
|
||||||
|
signal entered_dialog
|
||||||
|
signal exited_frame
|
||||||
|
|
||||||
|
# character related signals
|
||||||
|
signal on_speaker_expression_changed(spkr, expr)
|
||||||
|
|
||||||
|
signal on_dialog_init(d)
|
||||||
|
signal on_dialog_completed(d)
|
||||||
|
|
||||||
|
# setters
|
||||||
|
func set_auto_advance(v):
|
||||||
|
current_dialog_controller.set_advance_state(v)
|
||||||
|
advance_button.pressed = v
|
||||||
|
|
||||||
|
# signals from dialog controller
|
||||||
|
func _on_printing_changed(v):
|
||||||
|
pass
|
||||||
|
# next_arrow.visible = v
|
||||||
|
|
||||||
|
func _on_reading_speed_changed(new_value):
|
||||||
|
current_dialog_controller.set_reading_speed(new_value)
|
||||||
|
|
||||||
|
func set_advance_state():
|
||||||
|
current_dialog_controller.set_advance_state(advance_button.is_pressed())
|
||||||
|
|
||||||
|
func set_fastforward_state():
|
||||||
|
var ffwd_pressed = fastforward_button.is_pressed()
|
||||||
|
current_dialog_controller.set_fastforward_state(fastforward_button.is_pressed())
|
||||||
|
advance_button.set_disabled(ffwd_pressed)
|
||||||
|
|
||||||
|
# init functions, must be called before use
|
||||||
|
func set_dialog_path(path):
|
||||||
|
dialog_path = path
|
||||||
|
|
||||||
|
func set_dialog_vm(vm):
|
||||||
|
current_dialog = vm
|
||||||
|
|
||||||
|
func set_dialog_controller(c):
|
||||||
|
current_dialog_controller = c
|
||||||
|
|
||||||
|
func set_dialog_anim_player(p):
|
||||||
|
anim_player = p
|
||||||
|
|
||||||
|
func set_get_character_function(fnc):
|
||||||
|
get_node_fnc = fnc
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
|
||||||
|
advance_button.connect("pressed", self, "set_advance_state")
|
||||||
|
fastforward_button.connect("pressed", self, "set_fastforward_state")
|
||||||
|
|
||||||
|
# clicking to advance
|
||||||
|
body_container.connect("gui_input", self, "_on_body_click")
|
||||||
|
top_panel.connect("gui_input", self, "_on_body_click")
|
||||||
|
|
||||||
|
Game.connect("on_reading_speed_changed", self, "_on_reading_speed_changed")
|
||||||
|
Game.connect("on_settings_enter", self, "_on_settings_enter")
|
||||||
|
Game.connect("on_settings_exit", self, "_on_settings_exit")
|
||||||
|
|
||||||
|
tween = Tween.new()
|
||||||
|
add_child(tween)
|
||||||
|
|
||||||
|
timer = Timer.new()
|
||||||
|
add_child(timer)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_body_click(ev):
|
||||||
|
current_dialog_controller._on_body_click(is_active(), ev)
|
||||||
|
|
||||||
|
func _register_func(r, reg_name, func_name):
|
||||||
|
if r.has(reg_name):
|
||||||
|
r[reg_name].set_instance(self)
|
||||||
|
else:
|
||||||
|
r[reg_name] = funcref(self, func_name)
|
||||||
|
|
||||||
|
func _register_functions():
|
||||||
|
var r = current_dialog.get_local_registry()
|
||||||
|
|
||||||
|
# normal functions
|
||||||
|
_register_func(r, "SET_EXPR", "_set_expr_fnc")
|
||||||
|
_register_func(r, "FLIP", "_flip_char")
|
||||||
|
_register_func(r, "HIDE", "_hide_char")
|
||||||
|
_register_func(r, "SHOW", "_show_char")
|
||||||
|
|
||||||
|
# yieldy function
|
||||||
|
_register_func(r, "WAIT", "_wait_dialog_fnc")
|
||||||
|
|
||||||
|
# anim shite, also yieldy
|
||||||
|
_register_func(r, "PLAY_ANIM", "_play_anim_fnc")
|
||||||
|
|
||||||
|
# PLAY AND WAIT; HOW ABOUT DEM APPLES
|
||||||
|
_register_func(r, "PLAY_ANIM_WITH_WAIT", "_play_wait_with_anim_fnc")
|
||||||
|
|
||||||
|
func _play_wait_with_anim_fnc(args):
|
||||||
|
if args.size() == 2:
|
||||||
|
var anim_name = args[0]
|
||||||
|
var wait_time = float(args[1])
|
||||||
|
|
||||||
|
if anim_player:
|
||||||
|
anim_player.play(anim_name)
|
||||||
|
|
||||||
|
timer.one_shot = true
|
||||||
|
timer.wait_time = wait_time
|
||||||
|
timer.start()
|
||||||
|
return [timer, "timeout"]
|
||||||
|
|
||||||
|
func _play_anim_fnc(args):
|
||||||
|
if args.size() == 1:
|
||||||
|
var anim_name = args[0]
|
||||||
|
if anim_player:
|
||||||
|
anim_player.play(anim_name)
|
||||||
|
return [anim_player, "animation_finished"]
|
||||||
|
|
||||||
|
func _wait_dialog_fnc(args):
|
||||||
|
if args.size() == 1:
|
||||||
|
var time = float(args[0])
|
||||||
|
print("Dialog: waiting for: %f seconds" % time)
|
||||||
|
timer.wait_time = time
|
||||||
|
timer.one_shot = true
|
||||||
|
timer.start()
|
||||||
|
return [timer, "timeout"]
|
||||||
|
|
||||||
|
func _set_expr_fnc(args):
|
||||||
|
if args.size() == 2:
|
||||||
|
var speaker = args[0]
|
||||||
|
var expr = args[1]
|
||||||
|
_set_speaker_expression(speaker, expr)
|
||||||
|
|
||||||
|
func _show_char(args):
|
||||||
|
var char_name = args[0]
|
||||||
|
var character = get_node_fnc.call(char_name)
|
||||||
|
_do_show_char(character)
|
||||||
|
|
||||||
|
func _do_show_char(c):
|
||||||
|
tween.interpolate_property(
|
||||||
|
c, "modulate:a", c.modulate.a, 1.0,
|
||||||
|
1.0, Tween.TRANS_QUAD,
|
||||||
|
Tween.EASE_IN_OUT
|
||||||
|
)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
func _hide_char(args):
|
||||||
|
var char_name = args[0]
|
||||||
|
var character = get_node_fnc.call(char_name)
|
||||||
|
_do_hide_char(character)
|
||||||
|
|
||||||
|
func _do_hide_char(c):
|
||||||
|
tween.interpolate_property(
|
||||||
|
c, "modulate:a", c.modulate.a, 0.0,
|
||||||
|
1.0, Tween.TRANS_QUAD,
|
||||||
|
Tween.EASE_IN_OUT
|
||||||
|
)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
func _flip_char(args):
|
||||||
|
var char_name = args[0]
|
||||||
|
var character = get_node_fnc.call(char_name)
|
||||||
|
_do_flip_char(character)
|
||||||
|
|
||||||
|
func _do_flip_char(c):
|
||||||
|
c.flip_h = !c.flip_h
|
||||||
|
|
||||||
|
func _on_settings_enter(s):
|
||||||
|
if is_active():
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
func _on_settings_exit(s):
|
||||||
|
if is_active():
|
||||||
|
visible = true
|
||||||
|
|
||||||
|
func reload_dialog():
|
||||||
|
initialize_dialog()
|
||||||
|
|
||||||
|
func get_local_registry():
|
||||||
|
return current_dialog.get_local_registry()
|
||||||
|
|
||||||
|
func initialize_dialog():
|
||||||
|
|
||||||
|
assert(dialog_path != null)
|
||||||
|
|
||||||
|
var dialog_file = File.new()
|
||||||
|
dialog_file.open(dialog_path, File.READ)
|
||||||
|
var text = dialog_file.get_as_text()
|
||||||
|
dialog_file.close()
|
||||||
|
|
||||||
|
var dialog = Dialog.dialog_from_text(text)
|
||||||
|
current_dialog = dialog
|
||||||
|
|
||||||
|
# also setup kv store for dialog variables
|
||||||
|
current_dialog.set_registry(Game.current_registry)
|
||||||
|
|
||||||
|
# set up controller too yes
|
||||||
|
current_dialog_controller = DialogController.new(dialog, audio_player)
|
||||||
|
|
||||||
|
# register functions
|
||||||
|
_register_functions()
|
||||||
|
|
||||||
|
# signals
|
||||||
|
current_dialog_controller.connect("on_update_dialog", self, "_on_update_dialog")
|
||||||
|
current_dialog_controller.connect("on_dialog_completed", self, "_on_dialog_completed")
|
||||||
|
current_dialog_controller.connect("on_printing_changed", self, "_on_printing_changed")
|
||||||
|
|
||||||
|
emit_signal("on_dialog_init", self)
|
||||||
|
|
||||||
|
func _on_dialog_completed(d):
|
||||||
|
emit_signal("on_dialog_completed", self)
|
||||||
|
exit_frame()
|
||||||
|
|
||||||
|
func _on_update_dialog(s):
|
||||||
|
_update_dialog(s)
|
||||||
|
|
||||||
|
func _fade_in():
|
||||||
|
var FADE_TIME = 1.0
|
||||||
|
tween.interpolate_property(
|
||||||
|
self,
|
||||||
|
"modulate:a", 0.0, 1.0, FADE_TIME,
|
||||||
|
Tween.TRANS_QUAD, Tween.EASE_IN
|
||||||
|
)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
func _fade_out():
|
||||||
|
var FADE_TIME = 1.0
|
||||||
|
tween.interpolate_property(
|
||||||
|
self,
|
||||||
|
"modulate:a", 1.0, 0.0, FADE_TIME,
|
||||||
|
Tween.TRANS_QUAD, Tween.EASE_OUT
|
||||||
|
)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
yield(tween, "tween_completed")
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
func enter_frame():
|
||||||
|
|
||||||
|
_fade_in()
|
||||||
|
|
||||||
|
var r = Game.current_registry
|
||||||
|
r["IS_IN_DIALOG"] = true
|
||||||
|
|
||||||
|
# reload if is debug
|
||||||
|
if IS_DEBUG: reload_dialog()
|
||||||
|
|
||||||
|
active = true
|
||||||
|
visible = true
|
||||||
|
current_dialog.reset()
|
||||||
|
# next_arrow.visible = false
|
||||||
|
emit_signal("entered_dialog")
|
||||||
|
|
||||||
|
# dialogs
|
||||||
|
var first_segment = current_dialog.advance()
|
||||||
|
_update_dialog(first_segment)
|
||||||
|
|
||||||
|
|
||||||
|
func is_active():
|
||||||
|
return active
|
||||||
|
|
||||||
|
func exit_frame():
|
||||||
|
|
||||||
|
_fade_out()
|
||||||
|
|
||||||
|
# HACK: cludge to reset state
|
||||||
|
advance_button.set_pressed(false)
|
||||||
|
fastforward_button.set_pressed(false)
|
||||||
|
advance_button.emit_signal("pressed")
|
||||||
|
fastforward_button.emit_signal("pressed")
|
||||||
|
|
||||||
|
current_dialog_controller.reset()
|
||||||
|
active = false
|
||||||
|
|
||||||
|
var r = Game.current_registry
|
||||||
|
r["IS_IN_DIALOG"] = false
|
||||||
|
emit_signal("exited_frame")
|
||||||
|
|
||||||
|
|
||||||
|
func _set_speaker_subject(subject):
|
||||||
|
if Game.Characters.has(subject):
|
||||||
|
var data = Game.Characters[subject]
|
||||||
|
var subject_name = data.name
|
||||||
|
var subject_colour = data.name_colour
|
||||||
|
var subject_voice = data.voice
|
||||||
|
current_dialog_controller.chars_per_second = Game.DEFAULT_CHARS_PER_SECOND * data.talking_speed
|
||||||
|
_set_speaker_name(subject_name, subject_colour)
|
||||||
|
if subject_voice != null:
|
||||||
|
_set_speaker_voice(subject_voice)
|
||||||
|
else:
|
||||||
|
var subject_name = subject
|
||||||
|
current_dialog_controller.chars_per_second = Game.DEFAULT_CHARS_PER_SECOND
|
||||||
|
_set_speaker_name(subject_name, Color(1, 1, 1))
|
||||||
|
|
||||||
|
func _get_speaker_name():
|
||||||
|
return title_label.text
|
||||||
|
|
||||||
|
func _set_speaker_name(speaker_name, colour = Color(1, 1, 1)):
|
||||||
|
title_label.set_text(speaker_name)
|
||||||
|
title_label.modulate = colour
|
||||||
|
|
||||||
|
func _set_speaker_voice(voice_sample):
|
||||||
|
audio_player.stream = voice_sample
|
||||||
|
|
||||||
|
func _set_speaker_expression(speaker, expression):
|
||||||
|
emit_signal("on_speaker_expression_changed", speaker, expression)
|
||||||
|
|
||||||
|
# temporary maybe
|
||||||
|
|
||||||
|
func _setup_question(new_question):
|
||||||
|
body_container.add_child(new_question)
|
||||||
|
current_dialog_controller.waiting_for_answer = true
|
||||||
|
|
||||||
|
func _question_answered_yes(qs):
|
||||||
|
body_container.remove_child(qs)
|
||||||
|
current_dialog_controller.waiting_for_answer = false
|
||||||
|
current_dialog_controller._advance_dialog()
|
||||||
|
|
||||||
|
func _question_answered_no(qs):
|
||||||
|
body_container.remove_child(qs)
|
||||||
|
current_dialog_controller.waiting_for_answer = false
|
||||||
|
exit_frame()
|
||||||
|
|
||||||
|
func _choice_made(choice_modal, choice):
|
||||||
|
if IS_DEBUG: print("chose: ", choice.get_choice())
|
||||||
|
# Game.add_history_entry("you", choice.get_choice())
|
||||||
|
remove_child(choice_modal)
|
||||||
|
if choice is ChoiceWithJump:
|
||||||
|
# HACK: fix this later or make this unnecessary
|
||||||
|
var current_segment = current_dialog.jump(choice.target)
|
||||||
|
call_deferred("_update_dialog", current_segment)
|
||||||
|
else:
|
||||||
|
_update_dialog(choice)
|
||||||
|
current_dialog_controller.waiting_for_answer = false
|
||||||
|
|
||||||
|
# loop de loop
|
||||||
|
func _update_dialog(segment):
|
||||||
|
|
||||||
|
if segment is ChoiceSegment:
|
||||||
|
|
||||||
|
var choices = segment.get_choices()
|
||||||
|
|
||||||
|
# create new dialog choices and shit
|
||||||
|
var new_choices = DialogChoices.instance()
|
||||||
|
var vbox = new_choices.get_node("vbox")
|
||||||
|
|
||||||
|
for choice in choices:
|
||||||
|
var new_choice = DialogChoice.instance()
|
||||||
|
new_choice.text = choice.get_choice()
|
||||||
|
new_choice.connect("pressed", self, "_choice_made", [new_choices, choice])
|
||||||
|
vbox.add_child(new_choice)
|
||||||
|
|
||||||
|
add_child(new_choices)
|
||||||
|
|
||||||
|
elif segment is Choice:
|
||||||
|
var new_content = segment.get_response()
|
||||||
|
if typeof(new_content) == TYPE_OBJECT and (new_content is DialogWithSubjectSegment or new_content is DialogWithSubjectExpressionSegment):
|
||||||
|
_update_dialog(new_content)
|
||||||
|
else:
|
||||||
|
body_label.text = new_content
|
||||||
|
# Game.add_history_entry(_get_speaker_name(), new_content)
|
||||||
|
|
||||||
|
elif segment is DialogSegment or segment is DialogWithSubjectSegment or segment is DialogWithSubjectExpressionSegment:
|
||||||
|
var new_content = segment.get_content()
|
||||||
|
body_label.visible_characters = 0
|
||||||
|
body_label.text = new_content
|
||||||
|
|
||||||
|
if segment is DialogWithSubjectSegment:
|
||||||
|
_set_speaker_subject(segment.subject)
|
||||||
|
# Game.add_history_entry(_get_speaker_name(), new_content)
|
||||||
|
elif segment is DialogWithSubjectExpressionSegment:
|
||||||
|
_set_speaker_subject(segment.subject)
|
||||||
|
_set_speaker_expression(segment.subject, segment.expression)
|
||||||
|
# Game.add_history_entry("%s (%s)" % [_get_speaker_name(), segment.expression], new_content)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
# Game.add_history_entry(_get_speaker_name(), new_content)
|
||||||
|
|
||||||
|
elif segment is WaitSegment:
|
||||||
|
var new_content = segment.get_content()
|
||||||
|
body_label.visible_characters = 0
|
||||||
|
body_label.text = new_content
|
||||||
|
|
||||||
|
# whatever subject you want during functions to wait on, animations and such
|
||||||
|
_set_speaker_subject("")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("encountered unknown segment: " + segment.get_content())
|
||||||
|
|
||||||
|
current_dialog_controller.update_logic_dialog(segment)
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if is_active():
|
||||||
|
current_dialog_controller.tick(delta, body_label)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<BRAIN> ... You wake up to the sound of sirens blaring.
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
extends Reference
|
||||||
|
|
||||||
|
const Dialog = preload("res://dialog_vm.gd")
|
||||||
|
|
||||||
|
# classes from vm
|
||||||
|
const DialogSegment = Dialog.DialogSegment
|
||||||
|
const DialogWithSubjectSegment = Dialog.DialogWithSubjectSegment
|
||||||
|
const DialogWithSubjectExpressionSegment = Dialog.DialogWithSubjectExpressionSegment
|
||||||
|
const QuestionSegment = Dialog.QuestionSegment
|
||||||
|
const ChoiceSegment = Dialog.ChoiceSegment
|
||||||
|
const ChoiceWithJump = Dialog.ChoiceWithJump
|
||||||
|
const Choice = Dialog.Choice
|
||||||
|
|
||||||
|
const WaitSegment = Dialog.YieldCallSegment
|
||||||
|
|
||||||
|
# current dialog vm
|
||||||
|
var current_dialog
|
||||||
|
var audio_player
|
||||||
|
|
||||||
|
# dialog controller related state, internal
|
||||||
|
|
||||||
|
# speed at which dialog prints characters
|
||||||
|
var chars_per_second = 16 # initialized from which character is speaking
|
||||||
|
var reading_speed_mul = 1
|
||||||
|
var special_speed_mul = 1
|
||||||
|
|
||||||
|
# intermediate state for dialog
|
||||||
|
var waiting_for_answer = false
|
||||||
|
var print_done = false setget _on_print_set
|
||||||
|
var print_target = 0
|
||||||
|
var print_delta = 0
|
||||||
|
|
||||||
|
# ui button controlled state
|
||||||
|
var is_auto_advancing = false
|
||||||
|
var auto_advance_delay = 1
|
||||||
|
var auto_advance_timer = 0
|
||||||
|
|
||||||
|
var is_new_word = false
|
||||||
|
var is_fastforwarding = false
|
||||||
|
var ff_speed_mul = 1
|
||||||
|
|
||||||
|
# character printing sound related state
|
||||||
|
var sound_playing = false
|
||||||
|
var sound_play_time = 2.08 # TODO: maybe adjust this too depending on voice sample/chars per second
|
||||||
|
var sound_played_time = 0
|
||||||
|
|
||||||
|
# signals
|
||||||
|
signal on_printing_done()
|
||||||
|
signal on_printing_changed(status)
|
||||||
|
signal on_update_dialog(segment)
|
||||||
|
signal on_dialog_completed(d)
|
||||||
|
|
||||||
|
func _init(d, a):
|
||||||
|
current_dialog = d
|
||||||
|
audio_player = a
|
||||||
|
|
||||||
|
func reset():
|
||||||
|
self.print_done = true
|
||||||
|
print_target = 0
|
||||||
|
print_delta = 0
|
||||||
|
|
||||||
|
# sfx related
|
||||||
|
|
||||||
|
func sound_play():
|
||||||
|
sound_playing = true
|
||||||
|
audio_player.play()
|
||||||
|
|
||||||
|
func sound_stop():
|
||||||
|
audio_player.stop()
|
||||||
|
sound_playing = false
|
||||||
|
|
||||||
|
func sound_done_playing(delta):
|
||||||
|
sound_played_time += delta * reading_speed_mul * special_speed_mul
|
||||||
|
if sound_played_time >= sound_play_time / chars_per_second:
|
||||||
|
sound_played_time = 0
|
||||||
|
sound_playing = false
|
||||||
|
return not sound_playing
|
||||||
|
|
||||||
|
# temporary hopefully
|
||||||
|
func _advance_dialog():
|
||||||
|
var current_segment = current_dialog.advance()
|
||||||
|
if not current_segment == null:
|
||||||
|
emit_signal("on_update_dialog", current_segment)
|
||||||
|
else:
|
||||||
|
emit_signal("on_dialog_completed", self)
|
||||||
|
|
||||||
|
func _on_body_click(is_visible, event):
|
||||||
|
if is_visible and not waiting_for_answer:
|
||||||
|
if event.is_action_pressed("dialog_click"):
|
||||||
|
if print_done == false: # if still printing, jump forwards now
|
||||||
|
print_delta = print_target - 1
|
||||||
|
self.print_done = true
|
||||||
|
else:
|
||||||
|
_advance_dialog()
|
||||||
|
|
||||||
|
# interior callbacks
|
||||||
|
func _on_print_set(v):
|
||||||
|
print_done = v
|
||||||
|
if print_done:
|
||||||
|
emit_signal("on_printing_done")
|
||||||
|
emit_signal("on_printing_changed", v)
|
||||||
|
|
||||||
|
func set_reading_speed(spd):
|
||||||
|
reading_speed_mul = spd
|
||||||
|
|
||||||
|
func set_advance_state(s):
|
||||||
|
is_auto_advancing = s
|
||||||
|
|
||||||
|
func set_fastforward_state(s):
|
||||||
|
is_fastforwarding = s
|
||||||
|
if is_fastforwarding:
|
||||||
|
is_auto_advancing = true
|
||||||
|
ff_speed_mul = 10
|
||||||
|
auto_advance_delay = 0.1
|
||||||
|
else:
|
||||||
|
ff_speed_mul = 1
|
||||||
|
auto_advance_delay = 1
|
||||||
|
|
||||||
|
func update_logic_dialog(segment):
|
||||||
|
|
||||||
|
if segment is QuestionSegment:
|
||||||
|
var new_content = segment.get_content()
|
||||||
|
print_target = new_content.length()
|
||||||
|
self.print_done = false
|
||||||
|
print_delta = 0
|
||||||
|
|
||||||
|
elif segment is ChoiceSegment:
|
||||||
|
waiting_for_answer = true
|
||||||
|
|
||||||
|
elif segment is Choice:
|
||||||
|
var new_content = segment.get_response()
|
||||||
|
if typeof(new_content) == TYPE_OBJECT and (new_content is DialogWithSubjectSegment or new_content is DialogWithSubjectExpressionSegment):
|
||||||
|
_update_logic_dialog(new_content)
|
||||||
|
else:
|
||||||
|
print_target = new_content.length()
|
||||||
|
self.print_done = false
|
||||||
|
print_delta = 0
|
||||||
|
|
||||||
|
elif segment is DialogSegment or segment is DialogWithSubjectSegment or segment is DialogWithSubjectExpressionSegment:
|
||||||
|
var new_content = segment.get_content()
|
||||||
|
print_target = new_content.length()
|
||||||
|
self.print_done = false
|
||||||
|
print_delta = 0
|
||||||
|
|
||||||
|
elif segment is WaitSegment:
|
||||||
|
var new_content = segment.get_content()
|
||||||
|
print_target = new_content.length()
|
||||||
|
self.print_done = false
|
||||||
|
print_delta = 0
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("encountered unknown segment: " + segment.get_content())
|
||||||
|
|
||||||
|
func tick(delta, body_label):
|
||||||
|
|
||||||
|
if not current_dialog.is_eof():
|
||||||
|
var cur_segment = current_dialog.segments[current_dialog.segment_index]
|
||||||
|
if cur_segment is WaitSegment and cur_segment.finished: _advance_dialog()
|
||||||
|
|
||||||
|
if print_target != 0:
|
||||||
|
if print_delta >= print_target:
|
||||||
|
self.print_done = true
|
||||||
|
auto_advance_timer = auto_advance_delay
|
||||||
|
print_target = 0
|
||||||
|
print_delta = 0
|
||||||
|
else:
|
||||||
|
if sound_done_playing(delta) and not is_fastforwarding: sound_play()
|
||||||
|
body_label.visible_characters = print_delta
|
||||||
|
print_delta += delta * (chars_per_second * reading_speed_mul) * ff_speed_mul
|
||||||
|
elif print_target == 0:
|
||||||
|
auto_advance_timer -= delta
|
||||||
|
if auto_advance_timer <= 0 and is_auto_advancing and not waiting_for_answer:
|
||||||
|
call_deferred("_advance_dialog")
|
|
@ -0,0 +1,29 @@
|
||||||
|
extends CanvasLayer
|
||||||
|
|
||||||
|
export (String, FILE, "*.txt") var dialog_path;
|
||||||
|
|
||||||
|
onready var dialog_box = get_node("dialog_box")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
|
||||||
|
# start signal
|
||||||
|
get_parent().connect("on_scene_ready", self, "_on_scene_ready")
|
||||||
|
|
||||||
|
dialog_box.connect("on_dialog_init", self, "_on_dialog_init")
|
||||||
|
dialog_box.connect("on_dialog_completed", self, "_on_dialog_completed")
|
||||||
|
|
||||||
|
# set up params
|
||||||
|
dialog_box.set_dialog_path(dialog_path)
|
||||||
|
|
||||||
|
# init after yes
|
||||||
|
dialog_box.initialize_dialog()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_scene_ready():
|
||||||
|
dialog_box.enter_frame()
|
||||||
|
|
||||||
|
func _on_dialog_init(d):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_dialog_completed(d):
|
||||||
|
dialog_box.exit_frame()
|
|
@ -0,0 +1,570 @@
|
||||||
|
extends Reference
|
||||||
|
|
||||||
|
static func dialog_from_text(text):
|
||||||
|
|
||||||
|
var label_regex = RegEx.new()
|
||||||
|
label_regex.compile("[A-Z0-9_]+:")
|
||||||
|
|
||||||
|
# validation
|
||||||
|
var has_question = false
|
||||||
|
var lines = text.split("\n")
|
||||||
|
|
||||||
|
var new_dialog = Dialog.new()
|
||||||
|
|
||||||
|
# intermediate state
|
||||||
|
var current_choice_segment
|
||||||
|
var choices = 0
|
||||||
|
|
||||||
|
if current_choice_segment == null:
|
||||||
|
current_choice_segment = ChoiceSegment.new()
|
||||||
|
|
||||||
|
var line_number = 0
|
||||||
|
for line in lines:
|
||||||
|
|
||||||
|
line_number += 1
|
||||||
|
|
||||||
|
# comment lines
|
||||||
|
if line.begins_with("#"):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# is flag unset
|
||||||
|
elif line.begins_with("!@"):
|
||||||
|
var l = line.right(3).strip_edges()
|
||||||
|
var flag = l.left(l.length() - 1)
|
||||||
|
# if OS.is_debug_build(): print("flag to false: ", flag)
|
||||||
|
new_dialog.add_segment(FlagSetSegment.new(flag, false))
|
||||||
|
|
||||||
|
# is goto, or conditional goto
|
||||||
|
elif line.begins_with("!"):
|
||||||
|
|
||||||
|
var label_end = line.find(",")
|
||||||
|
|
||||||
|
# unconditional goto
|
||||||
|
if label_end == -1:
|
||||||
|
var label = line.substr(2, line.length() - 3).strip_edges()
|
||||||
|
|
||||||
|
# if OS.is_debug_build(): print("goto: ", label)
|
||||||
|
new_dialog.add_segment(GotoSegment.new(label))
|
||||||
|
else: # conditional goto
|
||||||
|
var label = line.substr(2, label_end - 2).strip_edges()
|
||||||
|
var target_end = line.find("]")
|
||||||
|
var target = line.substr(label_end + 1, (target_end - 1) - label_end).strip_edges()
|
||||||
|
|
||||||
|
# if OS.is_debug_build(): print("goto: ", target, " - ", label)
|
||||||
|
new_dialog.add_segment(ConditionalGotoSegment.new(target, label, true))
|
||||||
|
|
||||||
|
# is either random goto or question
|
||||||
|
elif line.begins_with("?"):
|
||||||
|
|
||||||
|
var str_line = line.strip_edges().right(1)
|
||||||
|
|
||||||
|
# question, initiates dialog, treat first encountered question as question
|
||||||
|
if str_line.begins_with("<"):
|
||||||
|
|
||||||
|
var q_line = str_line.strip_edges()
|
||||||
|
|
||||||
|
has_question = true
|
||||||
|
var subject_right_bracket_index = q_line.find(">")
|
||||||
|
var subject = q_line.substr(1, subject_right_bracket_index - 1).strip_edges()
|
||||||
|
var question_text = q_line.right(subject_right_bracket_index + 1).strip_edges()
|
||||||
|
|
||||||
|
var question_segment = QuestionSegment.new(question_text, subject)
|
||||||
|
new_dialog.add_segment(question_segment)
|
||||||
|
|
||||||
|
else: # random goto: picks one of the choices to goto, used like ?[P1, P2, P3]
|
||||||
|
|
||||||
|
var left_bracket = str_line.find("[")
|
||||||
|
var right_bracket = str_line.find("]")
|
||||||
|
|
||||||
|
if left_bracket == -1:
|
||||||
|
printerr("couldn't find left [ on line: %d" % line_number)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
|
if right_bracket == -1:
|
||||||
|
printerr("couldn't find right ] on line: %d" % line_number)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
|
# if there's actually even a single thing inside
|
||||||
|
if right_bracket - left_bracket > 1:
|
||||||
|
|
||||||
|
var arg_string = str_line.substr(left_bracket + 1, (right_bracket - left_bracket) - 1)
|
||||||
|
var args = arg_string.split(",", false)
|
||||||
|
|
||||||
|
var stripped_args = []
|
||||||
|
for arg in args:
|
||||||
|
stripped_args.push_back(arg.strip_edges())
|
||||||
|
|
||||||
|
# if OS.is_debug_build(): print("random goto, arg_string: %s" % arg_string)
|
||||||
|
|
||||||
|
new_dialog.add_segment(RandomGotoSegment.new(stripped_args))
|
||||||
|
|
||||||
|
# is flag set, either a normal set to true with @[SOME_FLAG] or a set to string with @[FLAG, STR]
|
||||||
|
elif line.begins_with("@"):
|
||||||
|
var l = line.right(2)
|
||||||
|
var comma_index = l.find(",")
|
||||||
|
if comma_index == -1:
|
||||||
|
var flag = l.left(l.length() - 1)
|
||||||
|
# if OS.is_debug_build(): print("flag to true: ", flag)
|
||||||
|
new_dialog.add_segment(FlagSetSegment.new(flag, true))
|
||||||
|
else:
|
||||||
|
var flag = l.left(comma_index).strip_edges()
|
||||||
|
var arg_end = l.find("]")
|
||||||
|
var arg_int = l.right(comma_index + 1)
|
||||||
|
var arg = arg_int.left(arg_int.length() - 1).strip_edges()
|
||||||
|
# if OS.is_debug_build(): print("flag: ", flag, " with arg: ", arg)
|
||||||
|
new_dialog.add_segment(FlagSetSegment.new(flag, arg))
|
||||||
|
|
||||||
|
# is label, can goto
|
||||||
|
elif line.ends_with(":") and label_regex.search(line):
|
||||||
|
var label = line.left(line.length() - 1).strip_edges()
|
||||||
|
|
||||||
|
# if OS.is_debug_build(): print("label: ", label)
|
||||||
|
new_dialog.add_segment(LabelSegment.new(label))
|
||||||
|
|
||||||
|
# is choice in conversation by player
|
||||||
|
elif line.begins_with("["):
|
||||||
|
|
||||||
|
var right_end_index = line.find("]")
|
||||||
|
var choice = line.substr(1, right_end_index - 1).strip_edges()
|
||||||
|
var response = line.right(right_end_index + 1).strip_edges()
|
||||||
|
|
||||||
|
# is it a jump choice?
|
||||||
|
var left_brace_index = response.find("[")
|
||||||
|
var right_brace_index = response.find("]")
|
||||||
|
if left_brace_index != -1 and right_brace_index != -1:
|
||||||
|
var jump_target = response.substr(left_brace_index + 1, right_brace_index - 1)
|
||||||
|
# if OS.is_debug_build(): print("choice: ", choice, " target: ", jump_target)
|
||||||
|
current_choice_segment.add_choice_with_jump(choice, jump_target)
|
||||||
|
else:
|
||||||
|
|
||||||
|
var subject_right_comma_index = response.find(",")
|
||||||
|
var subject_right_bracket_index = response.find(">")
|
||||||
|
|
||||||
|
# is response with <SUBJECT, EXPR>
|
||||||
|
if response.begins_with("<") and subject_right_bracket_index > 0 and subject_right_comma_index < subject_right_bracket_index:
|
||||||
|
var subject = response.substr(1, subject_right_comma_index - 1).strip_edges()
|
||||||
|
var expression = response.substr(subject_right_comma_index + 1, (subject_right_bracket_index - 1) - subject_right_comma_index).strip_edges()
|
||||||
|
var line_text = response.right(subject_right_bracket_index + 1).strip_edges()
|
||||||
|
# if OS.is_debug_build(): print("choice: ", choice, " response: ", line_text, " with: <", subject, ", ", expression, ">")
|
||||||
|
current_choice_segment.add_choice(choice, DialogWithSubjectExpressionSegment.new(line_text, subject, expression))
|
||||||
|
elif response.begins_with("<"): # is response with <SUBJECT>
|
||||||
|
var subject = response.substr(1, subject_right_bracket_index - 1).strip_edges()
|
||||||
|
var line_text = response.right(subject_right_bracket_index + 1).strip_edges()
|
||||||
|
# if OS.is_debug_build(): print("choice: ", choice, " response: ", line_text, " with: <", subject, ">")
|
||||||
|
current_choice_segment.add_choice(choice, DialogWithSubjectSegment.new(line_text, subject))
|
||||||
|
else:
|
||||||
|
# if OS.is_debug_build(): print("choice: ", choice, " response: ", response)
|
||||||
|
current_choice_segment.add_choice(choice, response)
|
||||||
|
|
||||||
|
choices += 1
|
||||||
|
|
||||||
|
# we're full
|
||||||
|
if choices == 3:
|
||||||
|
# if OS.is_debug_build(): print("choice segment created.")
|
||||||
|
new_dialog.add_segment(current_choice_segment)
|
||||||
|
|
||||||
|
# setup new one for next round
|
||||||
|
current_choice_segment = ChoiceSegment.new()
|
||||||
|
choices = 0
|
||||||
|
|
||||||
|
elif line.begins_with("<"):
|
||||||
|
|
||||||
|
# test for right comma and >
|
||||||
|
var subject_right_comma_index = line.find(",")
|
||||||
|
var subject_right_bracket_index = line.find(">")
|
||||||
|
|
||||||
|
# is <SUBJECT, EXPRESSION> dialog
|
||||||
|
if subject_right_comma_index > 0 and subject_right_comma_index < subject_right_bracket_index:
|
||||||
|
var subject = line.substr(1, subject_right_comma_index - 1).strip_edges()
|
||||||
|
var expression = line.substr(subject_right_comma_index + 1, (subject_right_bracket_index - 1) - subject_right_comma_index).strip_edges()
|
||||||
|
var line_text = line.right(subject_right_bracket_index + 1).strip_edges()
|
||||||
|
var dialog_subject_segment = DialogWithSubjectExpressionSegment.new(line_text, subject, expression)
|
||||||
|
new_dialog.add_segment(dialog_subject_segment)
|
||||||
|
|
||||||
|
else: # is <SUBJECT> dialog
|
||||||
|
var subject = line.substr(1, subject_right_bracket_index - 1).strip_edges()
|
||||||
|
var line_text = line.right(subject_right_bracket_index + 1).strip_edges()
|
||||||
|
var dialog_subject_segment = DialogWithSubjectSegment.new(line_text, subject)
|
||||||
|
new_dialog.add_segment(dialog_subject_segment)
|
||||||
|
|
||||||
|
# simple function calls, can look like: > FUNC, but also like > FUNC [A, B, C, D]
|
||||||
|
# yieldable function calls can look like: >> FUNC, but also like >> FUNC [A, B, C, D]
|
||||||
|
elif line.begins_with(">"):
|
||||||
|
|
||||||
|
var str_line = line.right(1).strip_edges()
|
||||||
|
var is_yielding_function = false
|
||||||
|
|
||||||
|
if str_line.begins_with(">"):
|
||||||
|
str_line = str_line.right(1).strip_edges()
|
||||||
|
is_yielding_function = true
|
||||||
|
|
||||||
|
var left_bracket = str_line.find("[")
|
||||||
|
var right_bracket = str_line.find("]")
|
||||||
|
|
||||||
|
# has left bracket, should have right bracket, has params
|
||||||
|
if (left_bracket != -1 and right_bracket != -1) or \
|
||||||
|
(left_bracket != -1 and right_bracket == -1) or \
|
||||||
|
(left_bracket == -1 and right_bracket != -1):
|
||||||
|
|
||||||
|
var command_end = str_line.find("[")
|
||||||
|
var command = str_line.left(command_end).strip_edges()
|
||||||
|
# if OS.is_debug_build(): print("parsing command with args: ", command)
|
||||||
|
|
||||||
|
if left_bracket == -1:
|
||||||
|
printerr("couldn't find left [ on line: %d" % line_number)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
|
if right_bracket == -1:
|
||||||
|
printerr("couldn't find right ] on line: %d" % line_number)
|
||||||
|
assert(false)
|
||||||
|
|
||||||
|
var args_str = str_line.substr(left_bracket + 1, (right_bracket - left_bracket) - 1).strip_edges()
|
||||||
|
var args = args_str.split(",", false)
|
||||||
|
|
||||||
|
var stripped_args = []
|
||||||
|
for a in args:
|
||||||
|
stripped_args.push_back(a.strip_edges())
|
||||||
|
|
||||||
|
if is_yielding_function:
|
||||||
|
var call_segment = YieldCallSegment.new(command, stripped_args)
|
||||||
|
new_dialog.add_segment(call_segment)
|
||||||
|
else:
|
||||||
|
var call_segment = CallSegment.new(command, stripped_args)
|
||||||
|
new_dialog.add_segment(call_segment)
|
||||||
|
|
||||||
|
else: # no params, argless call
|
||||||
|
|
||||||
|
var command = str_line.strip_edges()
|
||||||
|
# if OS.is_debug_build(): print("parsing command: ", command)
|
||||||
|
|
||||||
|
if is_yielding_function:
|
||||||
|
var call_segment = YieldCallSegment.new(command)
|
||||||
|
new_dialog.add_segment(call_segment)
|
||||||
|
else:
|
||||||
|
var call_segment = CallSegment.new(command)
|
||||||
|
new_dialog.add_segment(call_segment)
|
||||||
|
|
||||||
|
|
||||||
|
else: # is normal text
|
||||||
|
var line_text = line.strip_edges()
|
||||||
|
|
||||||
|
# if line is not empty, process
|
||||||
|
if not line_text.empty():
|
||||||
|
var dialog_segment = DialogSegment.new(line_text)
|
||||||
|
new_dialog.add_segment(dialog_segment)
|
||||||
|
|
||||||
|
return new_dialog
|
||||||
|
|
||||||
|
static func parse_dialog_line(text):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# types of segments of text, held in Dialogs array
|
||||||
|
|
||||||
|
class QuestionSegment:
|
||||||
|
|
||||||
|
var subject
|
||||||
|
var question
|
||||||
|
|
||||||
|
func _init(q, s):
|
||||||
|
question = q
|
||||||
|
subject = s
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return question
|
||||||
|
|
||||||
|
class DialogSegment:
|
||||||
|
|
||||||
|
var text
|
||||||
|
|
||||||
|
func _init(t):
|
||||||
|
text = t
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return text
|
||||||
|
|
||||||
|
class DialogWithSubjectSegment:
|
||||||
|
|
||||||
|
var text
|
||||||
|
var subject
|
||||||
|
|
||||||
|
func _init(t, s):
|
||||||
|
text = t
|
||||||
|
subject = s
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return text
|
||||||
|
|
||||||
|
class DialogWithSubjectExpressionSegment:
|
||||||
|
|
||||||
|
var text
|
||||||
|
var subject
|
||||||
|
var expression
|
||||||
|
|
||||||
|
func _init(t, s, e):
|
||||||
|
text = t
|
||||||
|
subject = s
|
||||||
|
expression = e
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return text
|
||||||
|
|
||||||
|
class Choice:
|
||||||
|
|
||||||
|
var choice
|
||||||
|
var response
|
||||||
|
|
||||||
|
func _init(c, r):
|
||||||
|
choice = c
|
||||||
|
response = r
|
||||||
|
|
||||||
|
func get_choice():
|
||||||
|
return choice
|
||||||
|
|
||||||
|
func get_response():
|
||||||
|
return response
|
||||||
|
|
||||||
|
class ChoiceWithJump:
|
||||||
|
|
||||||
|
var choice
|
||||||
|
var target
|
||||||
|
|
||||||
|
func _init(c, t):
|
||||||
|
choice = c
|
||||||
|
target = t
|
||||||
|
|
||||||
|
func get_choice():
|
||||||
|
return choice
|
||||||
|
|
||||||
|
func get_target():
|
||||||
|
return target
|
||||||
|
|
||||||
|
class ChoiceSegment:
|
||||||
|
|
||||||
|
var choices
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
choices = []
|
||||||
|
|
||||||
|
func add_choice(choice, response):
|
||||||
|
var new_choice = Choice.new(choice, response)
|
||||||
|
choices.push_back(new_choice)
|
||||||
|
|
||||||
|
func add_choice_with_jump(choice, target):
|
||||||
|
var new_choice = ChoiceWithJump.new(choice, target)
|
||||||
|
choices.push_back(new_choice)
|
||||||
|
|
||||||
|
func get_choices():
|
||||||
|
return choices
|
||||||
|
|
||||||
|
class LabelSegment:
|
||||||
|
|
||||||
|
var label
|
||||||
|
|
||||||
|
func _init(l):
|
||||||
|
label = l
|
||||||
|
|
||||||
|
class GotoSegment:
|
||||||
|
|
||||||
|
var target
|
||||||
|
|
||||||
|
func _init(t):
|
||||||
|
target = t
|
||||||
|
|
||||||
|
class RandomGotoSegment:
|
||||||
|
|
||||||
|
var targets
|
||||||
|
|
||||||
|
func _init(t):
|
||||||
|
targets = t
|
||||||
|
|
||||||
|
class ConditionalGotoSegment extends GotoSegment:
|
||||||
|
|
||||||
|
var variable
|
||||||
|
var expected_value
|
||||||
|
|
||||||
|
func _init(t, v, e).(t):
|
||||||
|
variable = v
|
||||||
|
expected_value = e
|
||||||
|
|
||||||
|
func test(registry):
|
||||||
|
if variable in registry:
|
||||||
|
var v = registry[variable]
|
||||||
|
return v
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
|
||||||
|
class CallSegment:
|
||||||
|
|
||||||
|
var fname
|
||||||
|
var args
|
||||||
|
|
||||||
|
func _init(f, a = null):
|
||||||
|
fname = f
|
||||||
|
args = a
|
||||||
|
|
||||||
|
func call(l, r):
|
||||||
|
if l.has(fname):
|
||||||
|
if args != null: return l[fname].call_func(args)
|
||||||
|
else: return l[fname].call_func([])
|
||||||
|
elif r.has(fname):
|
||||||
|
if args != null: return r[fname].call_func(args)
|
||||||
|
else: return r[fname].call_func([])
|
||||||
|
|
||||||
|
class YieldCallSegment extends CallSegment:
|
||||||
|
|
||||||
|
var started
|
||||||
|
var finished
|
||||||
|
|
||||||
|
func _init(f, a = null).(f, a):
|
||||||
|
started = false
|
||||||
|
|
||||||
|
func call(l, r):
|
||||||
|
started = true
|
||||||
|
finished = false
|
||||||
|
return .call(l, r)
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return "..."
|
||||||
|
|
||||||
|
class FlagSetSegment:
|
||||||
|
|
||||||
|
var flag
|
||||||
|
var value
|
||||||
|
|
||||||
|
func _init(f, v):
|
||||||
|
flag = f
|
||||||
|
value = v
|
||||||
|
|
||||||
|
func set(registry):
|
||||||
|
registry[flag] = value
|
||||||
|
|
||||||
|
class Dialog:
|
||||||
|
|
||||||
|
var segment_index = -1
|
||||||
|
var segments
|
||||||
|
|
||||||
|
# goto label dictionary
|
||||||
|
var labels
|
||||||
|
|
||||||
|
# local registry
|
||||||
|
var locals
|
||||||
|
|
||||||
|
# dependency, registry of stuff
|
||||||
|
var registry
|
||||||
|
|
||||||
|
# yield state
|
||||||
|
var is_yielding
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
is_yielding = false
|
||||||
|
segments = []
|
||||||
|
labels = {}
|
||||||
|
locals = {}
|
||||||
|
|
||||||
|
func get_local_registry():
|
||||||
|
return locals
|
||||||
|
|
||||||
|
func set_registry(r):
|
||||||
|
registry = r
|
||||||
|
|
||||||
|
func add_segment(s):
|
||||||
|
|
||||||
|
if s is GotoSegment:
|
||||||
|
if not s.target in labels:
|
||||||
|
labels[s.target] = -1
|
||||||
|
elif s is RandomGotoSegment:
|
||||||
|
for t in s.targets:
|
||||||
|
if not t in labels:
|
||||||
|
labels[t] = -1
|
||||||
|
elif s is LabelSegment:
|
||||||
|
var sz = segments.size()
|
||||||
|
if not labels.has(s.label) or labels[s.label] == -1:
|
||||||
|
# if OS.is_debug_build(): print("added label: ", s.label, " to: ", sz)
|
||||||
|
labels[s.label] = sz
|
||||||
|
else:
|
||||||
|
printerr("ERROR: label with name: %s already registered at %d!" % [s.label, labels[s.label]])
|
||||||
|
assert(labels[s.label] != -1)
|
||||||
|
|
||||||
|
segments.push_back(s)
|
||||||
|
|
||||||
|
func push_instruction():
|
||||||
|
if is_eof(): return null
|
||||||
|
var new_segment = segments[segment_index]
|
||||||
|
while (new_segment is GotoSegment \
|
||||||
|
or new_segment is RandomGotoSegment \
|
||||||
|
or new_segment is LabelSegment \
|
||||||
|
or new_segment is CallSegment \
|
||||||
|
or new_segment is FlagSetSegment) and not is_yielding and not is_eof():
|
||||||
|
new_segment = segments[segment_index]
|
||||||
|
if new_segment is ConditionalGotoSegment:
|
||||||
|
if new_segment.test(registry): # if true, jump to offset
|
||||||
|
var offset = labels[new_segment.target]
|
||||||
|
if offset == -1:
|
||||||
|
printerr("could not find label: %s" % new_segment.target)
|
||||||
|
assert(offset != -1)
|
||||||
|
# if OS.is_debug_build(): print("conditionally jumped to offset: ", offset)
|
||||||
|
segment_index = offset
|
||||||
|
else: # else skip
|
||||||
|
segment_index += 1
|
||||||
|
elif new_segment is RandomGotoSegment:
|
||||||
|
var rand_idx = floor(rand_range(0, new_segment.targets.size()))
|
||||||
|
var rand_target = new_segment.targets[rand_idx]
|
||||||
|
var offset = labels[rand_target]
|
||||||
|
if offset == -1:
|
||||||
|
printerr("could not find label: %s" % rand_target)
|
||||||
|
assert(offset != -1)
|
||||||
|
# if OS.is_debug_build(): print("random jumped to: ", offset, " with: ", rand_target)
|
||||||
|
segment_index = offset
|
||||||
|
elif new_segment is GotoSegment:
|
||||||
|
var offset = labels[new_segment.target]
|
||||||
|
if offset == -1:
|
||||||
|
printerr("could not find label: %s" % new_segment.target)
|
||||||
|
assert(offset != -1)
|
||||||
|
# if OS.is_debug_build(): print("jumped to: ", offset, " with: ", new_segment.target, " at: ", segment_index)
|
||||||
|
segment_index = offset
|
||||||
|
elif new_segment is YieldCallSegment:
|
||||||
|
if not new_segment.started:
|
||||||
|
var state = new_segment.call(locals, registry)
|
||||||
|
if state != null:
|
||||||
|
var obj = state[0]
|
||||||
|
var sgn = state[1]
|
||||||
|
is_yielding = true
|
||||||
|
_do_yield_wait(obj, sgn, new_segment)
|
||||||
|
else:
|
||||||
|
segment_index += 1
|
||||||
|
elif new_segment is CallSegment:
|
||||||
|
new_segment.call(locals, registry)
|
||||||
|
segment_index += 1
|
||||||
|
elif new_segment is FlagSetSegment:
|
||||||
|
new_segment.set(registry)
|
||||||
|
segment_index += 1
|
||||||
|
elif new_segment is LabelSegment:
|
||||||
|
segment_index += 1
|
||||||
|
if not is_eof():
|
||||||
|
return segments[segment_index]
|
||||||
|
else:
|
||||||
|
return null
|
||||||
|
|
||||||
|
func advance():
|
||||||
|
if not is_yielding:
|
||||||
|
segment_index += 1
|
||||||
|
return push_instruction()
|
||||||
|
else:
|
||||||
|
return push_instruction()
|
||||||
|
|
||||||
|
# external jump, is fudge
|
||||||
|
func jump(target):
|
||||||
|
segment_index = labels[target]
|
||||||
|
return push_instruction()
|
||||||
|
|
||||||
|
func is_eof():
|
||||||
|
return segment_index >= segments.size()
|
||||||
|
|
||||||
|
func reset():
|
||||||
|
segment_index = -1
|
||||||
|
|
||||||
|
func _do_yield_wait(obj, sgn, segment):
|
||||||
|
yield(obj, sgn)
|
||||||
|
segment.finished = true
|
||||||
|
is_yielding = false
|
||||||
|
printt("Dialog VM: %s %s %s" % [obj, sgn, "completed"])
|
|
@ -0,0 +1,59 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
# globals, for the game
|
||||||
|
var reading_speed = 1.0
|
||||||
|
|
||||||
|
var game_started = false setget _on_game_started_set
|
||||||
|
|
||||||
|
var current_registry
|
||||||
|
|
||||||
|
# music related
|
||||||
|
onready var music_player = get_node("music_player")
|
||||||
|
onready var sfx_player = get_node("sfx_player")
|
||||||
|
|
||||||
|
signal on_music_volume_changed(new_value)
|
||||||
|
signal on_sfx_volume_changed(new_value)
|
||||||
|
signal on_reading_speed_changed(new_value)
|
||||||
|
|
||||||
|
signal on_settings_enter()
|
||||||
|
signal on_settings_exit()
|
||||||
|
|
||||||
|
const Themes = {}
|
||||||
|
|
||||||
|
# voices for characters
|
||||||
|
const brain_voice = null
|
||||||
|
const arborator_voice = null
|
||||||
|
|
||||||
|
const DEFAULT_CHARS_PER_SECOND = 32
|
||||||
|
|
||||||
|
const Characters = {
|
||||||
|
BRAIN = {
|
||||||
|
name = "~brain~",
|
||||||
|
name_colour = Color(1, 1, 1, 1),
|
||||||
|
voice = brain_voice,
|
||||||
|
talking_speed = 1.0,
|
||||||
|
},
|
||||||
|
ARBORATOR = {
|
||||||
|
name = "arborator",
|
||||||
|
name_colour = Color(1, 1, 1, 1),
|
||||||
|
voice = arborator_voice,
|
||||||
|
talking_speed = 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _register_functions():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_game_started_set(v):
|
||||||
|
if v and not game_started:
|
||||||
|
_on_game_start()
|
||||||
|
game_started = v
|
||||||
|
|
||||||
|
func _on_game_start():
|
||||||
|
|
||||||
|
# all game state here
|
||||||
|
current_registry = {}
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
|
@ -0,0 +1,27 @@
|
||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://game.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="Game" type="Node"]
|
||||||
|
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="music_player" type="AudioStreamPlayer" parent="." index="0"]
|
||||||
|
|
||||||
|
stream = null
|
||||||
|
volume_db = 0.0
|
||||||
|
pitch_scale = 1.0
|
||||||
|
autoplay = false
|
||||||
|
mix_target = 0
|
||||||
|
bus = "Music"
|
||||||
|
|
||||||
|
[node name="sfx_player" type="AudioStreamPlayer" parent="." index="1"]
|
||||||
|
|
||||||
|
stream = null
|
||||||
|
volume_db = 0.0
|
||||||
|
pitch_scale = 1.0
|
||||||
|
autoplay = false
|
||||||
|
mix_target = 0
|
||||||
|
bus = "Sfx"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon.png"
|
||||||
|
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=1.0
|
|
@ -0,0 +1,26 @@
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
onready var start_btn = get_node("split/buttons/start_btn")
|
||||||
|
onready var load_btn = get_node("split/buttons/load_btn")
|
||||||
|
onready var options_btn = get_node("split/buttons/options_btn")
|
||||||
|
onready var quit_btn = get_node("split/buttons/quit_btn")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
|
||||||
|
start_btn.connect("pressed", self, "_on_start_pressed")
|
||||||
|
load_btn.connect("pressed", self, "_on_load_pressed")
|
||||||
|
options_btn.connect("pressed", self, "_on_options_pressed")
|
||||||
|
quit_btn.connect("pressed", self, "_on_quit_pressed")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_start_pressed():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_load_pressed():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_options_pressed():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_quit_pressed():
|
||||||
|
get_tree().quit()
|
|
@ -0,0 +1,182 @@
|
||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://menus/main_menu.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="main_menu" type="Control"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="split" type="VSplitContainer" parent="." index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
split_offset = 0
|
||||||
|
collapsed = false
|
||||||
|
dragger_visibility = 0
|
||||||
|
|
||||||
|
[node name="title" type="Label" parent="split" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 140.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 154.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 6
|
||||||
|
text = "godot-vn"
|
||||||
|
align = 1
|
||||||
|
percent_visible = 1.0
|
||||||
|
lines_skipped = 0
|
||||||
|
max_lines_visible = -1
|
||||||
|
_sections_unfolded = [ "Size Flags" ]
|
||||||
|
|
||||||
|
[node name="buttons" type="VBoxContainer" parent="split" index="1"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 306.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 600.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 1
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 3
|
||||||
|
alignment = 0
|
||||||
|
_sections_unfolded = [ "Size Flags" ]
|
||||||
|
|
||||||
|
[node name="start_btn" type="Button" parent="split/buttons" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 0, 0, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 0, 0, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "start game"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[node name="load_btn" type="Button" parent="split/buttons" index="1"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 24.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 44.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 0, 0, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 0, 0, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "load game"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[node name="options_btn" type="Button" parent="split/buttons" index="2"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 48.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 68.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 0, 0, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 0, 0, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "options"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[node name="quit_btn" type="Button" parent="split/buttons" index="3"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 72.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 92.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 0, 0, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 0, 0, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "quit"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
; Engine configuration file.
|
||||||
|
; It's best edited using the editor UI and not directly,
|
||||||
|
; since the parameters that go here are not all obvious.
|
||||||
|
;
|
||||||
|
; Format:
|
||||||
|
; [section] ; section goes between []
|
||||||
|
; param=value ; assign values to parameters
|
||||||
|
|
||||||
|
config_version=3
|
||||||
|
|
||||||
|
[application]
|
||||||
|
|
||||||
|
config/name="godot-vn"
|
||||||
|
run/main_scene="res://scene.tscn"
|
||||||
|
config/icon="res://icon.png"
|
||||||
|
|
||||||
|
[autoload]
|
||||||
|
|
||||||
|
SceneSwitcher="*res://scene_switcher.gd"
|
||||||
|
Game="*res://game.tscn"
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/size/resizable=false
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
dialog_click=[ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
|
||||||
|
]
|
||||||
|
|
||||||
|
[rendering]
|
||||||
|
|
||||||
|
environment/default_environment="res://default_env.tres"
|
|
@ -0,0 +1,7 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
signal on_scene_ready
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
Game.game_started = true
|
||||||
|
emit_signal("on_scene_ready")
|
|
@ -0,0 +1,307 @@
|
||||||
|
[gd_scene load_steps=5 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://scene.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://dialog_layer.gd" type="Script" id=2]
|
||||||
|
[ext_resource path="res://dialog.gd" type="Script" id=3]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id=1]
|
||||||
|
|
||||||
|
content_margin_left = -1.0
|
||||||
|
content_margin_right = -1.0
|
||||||
|
content_margin_top = -1.0
|
||||||
|
content_margin_bottom = -1.0
|
||||||
|
|
||||||
|
[node name="scene" type="Node2D" index="0"]
|
||||||
|
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="background" type="Sprite" parent="." index="0"]
|
||||||
|
|
||||||
|
[node name="dialog_layer" type="CanvasLayer" parent="." index="1"]
|
||||||
|
|
||||||
|
layer = 1
|
||||||
|
offset = Vector2( 0, 0 )
|
||||||
|
rotation = 0.0
|
||||||
|
scale = Vector2( 1, 1 )
|
||||||
|
transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||||
|
script = ExtResource( 2 )
|
||||||
|
dialog_path = "res://dialog/introduction.txt"
|
||||||
|
|
||||||
|
[node name="dialog_box" type="Control" parent="dialog_layer" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
|
||||||
|
[node name="audio_player" type="AudioStreamPlayer" parent="dialog_layer/dialog_box" index="0"]
|
||||||
|
|
||||||
|
stream = null
|
||||||
|
volume_db = 0.0
|
||||||
|
pitch_scale = 1.0
|
||||||
|
autoplay = false
|
||||||
|
mix_target = 0
|
||||||
|
bus = "Master"
|
||||||
|
|
||||||
|
[node name="top_panel" type="HBoxContainer" parent="dialog_layer/dialog_box" index="1"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 16.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 1
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
alignment = 2
|
||||||
|
_sections_unfolded = [ "Margin", "Size Flags", "Theme", "custom_constants" ]
|
||||||
|
|
||||||
|
[node name="auto_btn" type="Button" parent="dialog_layer/dialog_box/top_panel" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 847.0
|
||||||
|
margin_right = 887.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color_disabled = Color( 0.378906, 0.378906, 0.378906, 1 )
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 1, 0.647059, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 1, 0.647059, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "auto"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
_sections_unfolded = [ "custom_constants" ]
|
||||||
|
|
||||||
|
[node name="ffwd_btn" type="Button" parent="dialog_layer/dialog_box/top_panel" index="1"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 891.0
|
||||||
|
margin_right = 926.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color_disabled = Color( 0.378906, 0.378906, 0.378906, 1 )
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 1, 0.647059, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 1, 0.647059, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = "fast"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[node name="menu_btn" type="Button" parent="dialog_layer/dialog_box/top_panel" index="2"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 930.0
|
||||||
|
margin_right = 1002.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_colors/font_color_disabled = Color( 0.378906, 0.378906, 0.378906, 1 )
|
||||||
|
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||||
|
custom_colors/font_color_hover = Color( 1, 0.647059, 0, 1 )
|
||||||
|
custom_colors/font_color_pressed = Color( 1, 0.647059, 0, 1 )
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
text = " | menu"
|
||||||
|
flat = true
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
[node name="spacing" type="Control" parent="dialog_layer/dialog_box/top_panel" index="3"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 1006.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_min_size = Vector2( 18, 0 )
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
_sections_unfolded = [ "Rect" ]
|
||||||
|
|
||||||
|
[node name="body_container" type="PanelContainer" parent="dialog_layer/dialog_box" index="2"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_top = -100.0
|
||||||
|
grow_vertical = 0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_styles/panel = SubResource( 1 )
|
||||||
|
_sections_unfolded = [ "Grow Direction", "Mouse", "Size Flags", "custom_styles" ]
|
||||||
|
|
||||||
|
[node name="bottom_panel" type="VBoxContainer" parent="dialog_layer/dialog_box/body_container" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 100.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
alignment = 0
|
||||||
|
_sections_unfolded = [ "Grow Direction", "Mouse" ]
|
||||||
|
|
||||||
|
[node name="subject_margin" type="MarginContainer" parent="dialog_layer/dialog_box/body_container/bottom_panel" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 14.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_constants/margin_right = 0
|
||||||
|
custom_constants/margin_top = 0
|
||||||
|
custom_constants/margin_left = 4
|
||||||
|
custom_constants/margin_bottom = 0
|
||||||
|
_sections_unfolded = [ "Mouse", "custom_constants" ]
|
||||||
|
|
||||||
|
[node name="subject_panel" type="HBoxContainer" parent="dialog_layer/dialog_box/body_container/bottom_panel/subject_margin" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 4.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 14.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
alignment = 0
|
||||||
|
_sections_unfolded = [ "Mouse" ]
|
||||||
|
|
||||||
|
[node name="subject_label" type="Label" parent="dialog_layer/dialog_box/body_container/bottom_panel/subject_margin/subject_panel" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 60.0
|
||||||
|
margin_bottom = 14.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 4
|
||||||
|
text = "Arborator"
|
||||||
|
percent_visible = 1.0
|
||||||
|
lines_skipped = 0
|
||||||
|
max_lines_visible = -1
|
||||||
|
_sections_unfolded = [ "Margin" ]
|
||||||
|
|
||||||
|
[node name="body_margin" type="MarginContainer" parent="dialog_layer/dialog_box/body_container/bottom_panel" index="1"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 48.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
custom_constants/margin_top = 8
|
||||||
|
custom_constants/margin_left = 8
|
||||||
|
custom_constants/margin_bottom = 8
|
||||||
|
_sections_unfolded = [ "Margin", "Mouse", "custom_constants" ]
|
||||||
|
|
||||||
|
[node name="body_label" type="Label" parent="dialog_layer/dialog_box/body_container/bottom_panel/body_margin" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 8.0
|
||||||
|
margin_top = 8.0
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 22.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 2
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 4
|
||||||
|
text = "Sup new kid, you skippin?"
|
||||||
|
percent_visible = 1.0
|
||||||
|
lines_skipped = 0
|
||||||
|
max_lines_visible = -1
|
||||||
|
_sections_unfolded = [ "Margin", "Mouse", "Rect", "Size Flags" ]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
var current_scene
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
var root = get_tree().get_root()
|
||||||
|
current_scene = root.get_child(root.get_child_count() - 1)
|
||||||
|
|
||||||
|
func goto_scene(path, from_end = false):
|
||||||
|
call_deferred("_deferred_goto_scene", path, from_end)
|
||||||
|
|
||||||
|
func _deferred_goto_scene(path, from_end):
|
||||||
|
|
||||||
|
# Store old name so we can pass it to next one
|
||||||
|
var current_scene_name = current_scene.get_filename()
|
||||||
|
|
||||||
|
var old_scene = current_scene
|
||||||
|
current_scene.get_parent().remove_child(current_scene)
|
||||||
|
current_scene.queue_free()
|
||||||
|
|
||||||
|
# Load new scene
|
||||||
|
var s = ResourceLoader.load(path)
|
||||||
|
|
||||||
|
# Instance the new scene
|
||||||
|
current_scene = s.instance()
|
||||||
|
|
||||||
|
if "from_scene_name" in current_scene:
|
||||||
|
if current_scene_name != current_scene.get_filename():
|
||||||
|
current_scene.from_scene_name = current_scene_name
|
||||||
|
else:
|
||||||
|
if "from_scene_name" in old_scene:
|
||||||
|
current_scene.from_scene_name = old_scene.from_scene_name
|
||||||
|
|
||||||
|
# Add it to the active scene, as child of root
|
||||||
|
get_tree().get_root().add_child(current_scene)
|
||||||
|
|
||||||
|
# optional, to make it compatible with the SceneTree.change_scene() API
|
||||||
|
get_tree().set_current_scene(current_scene)
|
|
@ -0,0 +1,25 @@
|
||||||
|
[gd_scene format=2]
|
||||||
|
|
||||||
|
[node name="dialog_choice" type="Button"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 40.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
focus_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
toggle_mode = false
|
||||||
|
enabled_focus_mode = 2
|
||||||
|
shortcut = null
|
||||||
|
group = null
|
||||||
|
flat = false
|
||||||
|
align = 1
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[gd_scene format=2]
|
||||||
|
|
||||||
|
[node name="dialog_choices" type="Control"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 40.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue