frame-of-mind/src/singletons/global_state.gd

358 lines
10 KiB
GDScript3
Raw Normal View History

2024-10-21 09:39:16 +00:00
@tool
extends Node
#region configuration
signal settings_changed
var settings_initialised
2024-10-07 09:13:22 +00:00
@export_file var user_settings_path:String = "user://user_settings.json"
@export_file var user_saves_path:String = "user://savegames"
@export_group("Acessability")
@export var reduce_motion: bool = false:
set(value):
reduce_motion = value
if settings_initialised:
settings_changed.emit()
@export var screen_reader_enabled:bool = false:
set(value):
screen_reader_enabled = value
if settings_initialised:
settings_changed.emit()
2025-10-07 22:33:15 +00:00
@export var rendering_disabled: bool = false:
set(value):
rendering_disabled = value
if settings_initialised:
settings_changed.emit()
@export var use_simplified_navigation:bool = false:
set(value):
use_simplified_navigation = value
if settings_initialised:
settings_changed.emit()
2024-10-21 09:39:16 +00:00
@export var enable_hyperacoustic_filter: bool = false:
set(value):
enable_hyperacoustic_filter = value
if enable_hyperacoustic_filter:
AudioServer.set_bus_effect_enabled(0, 0, enable_hyperacoustic_filter)
if settings_initialised:
settings_changed.emit()
@export var show_navigation_buttons: bool = false:
set(value):
show_navigation_buttons = value
if settings_initialised:
settings_changed.emit()
@export_enum("handwriting", "serif", "legible", "system") var font_style: int = 0:
set(value):
font_style = value
if settings_initialised:
settings_changed.emit()
@export_enum("disabled", "text", "cc") var subtitles: int = false:
set(value):
subtitles = value
if settings_initialised:
settings_changed.emit()
@export var ui_scaling: float = 1:
set(value):
ui_scaling = value
2025-10-07 22:33:15 +00:00
ProjectSettings.set_setting("display/window/stretch/scale", value)
get_tree().root.content_scale_factor = value
@export var show_content_notes: bool = false:
set(value):
show_content_notes = value
if settings_initialised:
settings_changed.emit()
@export var provide_summaries: bool = false:
set(value):
provide_summaries = value
if settings_initialised:
settings_changed.emit()
@export var allow_skipping: bool = false:
set(value):
allow_skipping = value
if settings_initialised:
settings_changed.emit()
2025-02-06 17:55:05 +00:00
# FIXME find a better way to switch fonts and maybe emit the theme_changed signal!
var current_main_theme:Theme = preload("res://logic-scenes/themes/handwriting.theme")
@export_group("AudioSettings")
@export var main_volume:float = 1:
set(volume):
main_volume = volume
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db(volume))
@export var sfx_muted:bool = false:
set(mute):
sfx_muted = mute
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("sfx"), linear_to_db(mute))
@export var sfx_volume:float = 1:
set(volume):
sfx_volume = volume
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("sfx"), linear_to_db(volume/2))
@export var music_muted:bool = false:
set(mute):
sfx_muted = mute
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("sfx"), linear_to_db(mute))
@export var music_volume:float = 1:
set(volume):
music_volume = volume
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("music"), linear_to_db(volume/2.5))
@export var speech_volume: float = 1:
set(volume):
speech_volume = volume
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("text"), linear_to_db(volume))
@export var force_stereo: bool = false:
set(stereo):
if stereo != force_stereo:
force_stereo = stereo
settings_changed.emit()
2025-06-04 13:25:23 +00:00
@export var disconnect_steam:bool = false:
set(disconnect):
if disconnect and not disconnect_steam:
Steam.steamShutdown()
Steamworks.has_initialized = false
elif not disconnect and disconnect_steam:
Steamworks._ready()
disconnect_steam = disconnect
@export var obscure_logs:bool = true
@export_enum("system_locale", "english", "german") var text_language: int = 0:
set(value):
text_language = value
match text_language:
1: TranslationServer.set_locale("en")
2: TranslationServer.set_locale("de")
_: TranslationServer.set_locale(OS.get_locale())
2025-05-21 09:13:44 +00:00
settings_changed.emit()
@export_enum("system_locale", "english", "german") var speech_language: int = 0:
set(value):
2024-10-18 16:15:46 +00:00
speech_language = value
@export_group("Gameplay Settings")
2025-10-07 22:33:15 +00:00
@export var input_sensitivity: float = 1.0
@export var fov: float = 35.0
@export var inverty_y_axis: bool = false
@export var inverty_y_mouse: bool = false
@export_enum("off", "top_left", "top_right", "bottom_left", "bottom_right") var stream_overlay_position: int
# for passing VFX settings not contained by project settings to scene environemnt
2024-09-27 20:02:28 +00:00
var ssil_enable:bool = false:
set(value):
ssil_enable = value
environment_settings_changed.emit()
var sdfgi_enable:bool = false:
set(value):
sdfgi_enable = value
environment_settings_changed.emit()
var active_save_game: SaveGame
2024-09-27 20:02:28 +00:00
signal environment_settings_changed
2024-02-06 20:58:29 +00:00
signal theme_changed
2024-02-03 21:00:44 +00:00
func load_user_settings():
if FileAccess.file_exists(user_settings_path):
var file = FileAccess.open(user_settings_path, FileAccess.READ)
var raw_json = FileAccess.get_file_as_string(user_settings_path)
file.close()
var parsed: Dictionary = JSON.parse_string(raw_json)
for kategory in parsed.values():
for key in kategory.keys():
set(key, parsed[key])
else:
if OS.has_feature("macos"):
var out: Array
OS.execute("defaults", ["read", "/Users/$loggedInUser/Library/Preferences/com.apple.universalaccess.plist", "reduceMotion"], out)
if out[0] == "reduce":
reduce_motion = true
settings_initialised = true
settings_changed.emit()
func save_settings():
var out_dict = {
"accessability": {
"reduce_motion:": reduce_motion,
"screen_reader_enabled": screen_reader_enabled,
"rendering_disabled": rendering_disabled,
"use_simplified_navigation": use_simplified_navigation,
"show_navigation_buttons": show_navigation_buttons,
"subtitles": subtitles,
"font_style": font_style,
"ui_scaling": ui_scaling,
"show_content_notes:": show_content_notes,
"provide_summaries:": provide_summaries,
"allow_skipping:": allow_skipping
},
"audio": {
"main_volume": main_volume,
"sfx_muted": sfx_muted,
"sfx_volume": sfx_volume,
"music_muted": music_muted,
"music_volume": music_volume,
"speech_volume": speech_volume,
"speech_language": speech_language,
2025-05-16 12:30:52 +00:00
"text_language": text_language,
"force_stereo": force_stereo
},
"gameplay": {
"input_sensitivity": input_sensitivity,
"inverty_y_axis": inverty_y_axis,
2025-10-07 22:33:15 +00:00
"inverty_y_mouse": inverty_y_mouse,
"fov": fov,
"stream_overlay_position": stream_overlay_position
},
"privacy": {
"disconnect_steam": disconnect_steam,
"obscure_logs": obscure_logs
}
}
var file = FileAccess.open(user_settings_path, FileAccess.WRITE)
file.store_string(JSON.stringify(out_dict))
file.close()
settings_initialised = true
settings_changed.emit()
2025-02-06 17:55:05 +00:00
var last_mode := DisplayServer.WINDOW_MODE_WINDOWED
func _unhandled_input(event: InputEvent) -> void:
#FIXME this can be removed when state no longer needs to be a tool
if not Engine.is_editor_hint():
if event.is_action_pressed("toggle_fullscreen"):
# I have no idea why I wrote thit as conviluted,
# but it works(TM) so I am not gonna change it :D
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
DisplayServer.window_set_mode(last_mode)
else:
last_mode = DisplayServer.window_get_mode()
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
#endregion
func _ready():
await get_tree().process_frame
2024-10-07 09:13:22 +00:00
for child in get_tree().root.get_children():
if child is RoomTemplate and active_save_game == null:
push_warning("Room initialised without a SaveGame. Creating proxy save.")
#TODO: make this a bit more clean maybe?
active_save_game = ResourceLoader.load("res://dev-util/debug_save.tres")
2024-09-15 09:30:31 +00:00
if "has_stage" in child:
pass_stage_to(child)
2024-10-07 09:13:22 +00:00
break
music_volume = music_volume
2025-02-06 17:55:05 +00:00
#region focus handling (called staging to avoid name colisions)
2025-02-06 17:55:05 +00:00
# CAUTION: scene_reference directly accesses stage list to play sequences.
var stage_list:Array = []
var focus_locked: bool = false
# Intented for use when an actor wants focus for itself, can reclaim focus, thus dropping the stack that focused.
func take_stage(actor: Object, reclaim: bool = false) -> bool:
2025-02-06 17:55:05 +00:00
if focus_locked or Scenes.current_sequence != -1: return false
2024-09-15 09:30:31 +00:00
if reclaim:
stage_list.front().has_stage = false
if stage_list.has(actor):
while stage_list.pop_front() != actor: break
actor.has_stage = true
stage_list.push_front(actor)
return actor.has_stage
push_warning(actor, " wanted to reclaim focus, but was not on list.")
return pass_stage_to(actor)
# Element no longer wants focus, if Element itself is also dropped, this option can be chosen aswell.
2025-02-06 17:55:05 +00:00
func leave_stage(actor:Object) -> bool:
2024-09-15 09:30:31 +00:00
2025-02-06 17:55:05 +00:00
if stage_list[0] == actor:
actor.has_stage = false
focus_locked = false
2024-09-15 09:30:31 +00:00
stage_list.erase(actor)
if stage_list != []:
stage_list.front().has_stage = true
else:
get_tree().quit()
return false
func get_current_actor(): return stage_list.front()
# Used to put a new target on top of the Focus Stack.
func pass_stage_to(target:Object, force = false, lock_focus = false) -> bool:
2024-09-15 09:30:31 +00:00
if "pass_to_actor" in target:
2025-02-06 17:55:05 +00:00
return pass_stage_to(target.pass_to_actor)
2024-09-15 09:30:31 +00:00
if (focus_locked or get_tree().paused) and not force:
push_error(target, " requested focus while it was locked or tree is paused.")
elif !is_instance_valid(target):
push_error("Focus instance not valid")
elif !"has_stage" in target:
push_error(target, " has no has focus method.")
else:
if stage_list.size() > 0:
if stage_list.front() == target:
push_warning(target, " is already target. Abort passing focus.")
return false
if not stage_list.size() == 0: stage_list.front().has_stage = false
target.has_stage = true
if target.has_stage:
stage_list.push_front(target)
assert(stage_list.size() < 100)
focus_locked = lock_focus
2024-09-15 09:30:31 +00:00
return true
return false
2025-02-06 17:55:05 +00:00
# Currently focused element loses focus, but remains in stack.
func free_focus():
2024-09-15 09:30:31 +00:00
if focus_locked: return false
if stage_list.size() > 0: stage_list.front().has_stage = false
2023-07-13 14:14:40 +00:00
func transition_stage_to(thief: Object, lock_focus = false):
2024-09-15 09:30:31 +00:00
focus_locked = lock_focus
if stage_list.size() > 0:
if stage_list.front().has_stage:
stage_list.pop_front().has_stage = false
return pass_stage_to(thief, true)
2023-07-13 14:14:40 +00:00
func queue_for_stage(target: Object, index: int = 1):
2024-09-15 09:30:31 +00:00
stage_list.insert(index, target)
#endregion
#region play state
enum rooms {
2025-03-25 21:34:13 +00:00
NULL,
YOUTH,
2024-10-16 10:29:20 +00:00
TRANSITION,
ADULTHOOD,
ENDING
}
2025-02-06 17:55:05 +00:00
enum sequences {
DRAEVEN,
CHILDHOOD,
VOICE,
JUI_JUTSU,
TRANS,
AUTISM,
UNI_START,
VOLUNTARY,
UNI_CONTINUE,
UNI_ALT,
THERAPY,
BURNOUT
}
2025-03-25 21:34:13 +00:00
var current_room = rooms.NULL