Integrate per-save identity and interaction UI
This commit is contained in:
parent
ac82a28f3b
commit
4fda6e97f6
58 changed files with 3471 additions and 461 deletions
|
|
@ -1,12 +1,17 @@
|
|||
class_name NetworkProfilePreferences
|
||||
extends Node
|
||||
|
||||
signal profile_changed
|
||||
|
||||
const FORMAT_VERSION: int = 1
|
||||
const DEFAULT_DISPLAY_NAME: String = "stray"
|
||||
const DEFAULT_TITLE: String = "newbie"
|
||||
const VoiceProfilesType = preload(
|
||||
"res://player/animalese_voice_profiles.gd"
|
||||
)
|
||||
var profile_id: String = ""
|
||||
var display_name: String = "Player"
|
||||
var display_name: String = DEFAULT_DISPLAY_NAME
|
||||
var title: String = DEFAULT_TITLE
|
||||
var voice_id: String = VoiceProfilesType.DEFAULT_ID
|
||||
var speech_speed_id: String = VoiceProfilesType.DEFAULT_SPEED_ID
|
||||
var call_id: String = VoiceProfilesType.DEFAULT_CALL_ID
|
||||
|
|
@ -56,7 +61,8 @@ func load_or_create() -> bool:
|
|||
int(Time.get_unix_time_from_system()),
|
||||
Time.get_ticks_usec(),
|
||||
]
|
||||
display_name = "Player"
|
||||
display_name = DEFAULT_DISPLAY_NAME
|
||||
title = DEFAULT_TITLE
|
||||
voice_id = VoiceProfilesType.DEFAULT_ID
|
||||
speech_speed_id = VoiceProfilesType.DEFAULT_SPEED_ID
|
||||
call_id = VoiceProfilesType.DEFAULT_CALL_ID
|
||||
|
|
@ -65,6 +71,113 @@ func load_or_create() -> bool:
|
|||
return _save_atomic()
|
||||
|
||||
|
||||
func to_save_data() -> Dictionary:
|
||||
return {
|
||||
"profile_id": profile_id,
|
||||
"display_name": display_name,
|
||||
"title": title,
|
||||
"voice_id": voice_id,
|
||||
"speech_speed_id": speech_speed_id,
|
||||
"call_id": call_id,
|
||||
"sample_set_id": sample_set_id,
|
||||
"created_at_unix": created_at_unix,
|
||||
}
|
||||
|
||||
|
||||
static func validate_save_data(value: Variant) -> bool:
|
||||
if typeof(value) != TYPE_DICTIONARY:
|
||||
return false
|
||||
var data: Dictionary = value
|
||||
if (
|
||||
typeof(data.get("profile_id")) != TYPE_STRING
|
||||
or typeof(data.get("display_name")) != TYPE_STRING
|
||||
or (
|
||||
data.has("title")
|
||||
and typeof(data.get("title")) != TYPE_STRING
|
||||
)
|
||||
or typeof(data.get("created_at_unix")) not in [TYPE_INT, TYPE_FLOAT]
|
||||
):
|
||||
return false
|
||||
var saved_profile_id := str(data.get("profile_id", ""))
|
||||
var saved_name := str(data.get("display_name", ""))
|
||||
var saved_title := str(data.get("title", DEFAULT_TITLE))
|
||||
return (
|
||||
not saved_profile_id.is_empty()
|
||||
and saved_profile_id.length() <= NetworkProtocol.MAX_PROFILE_ID_LENGTH
|
||||
and is_valid_display_name(saved_name)
|
||||
and is_valid_title(saved_title)
|
||||
and VoiceProfilesType.is_valid(str(data.get(
|
||||
"voice_id",
|
||||
VoiceProfilesType.DEFAULT_ID,
|
||||
)))
|
||||
and VoiceProfilesType.is_valid_speed(str(data.get(
|
||||
"speech_speed_id",
|
||||
VoiceProfilesType.DEFAULT_SPEED_ID,
|
||||
)))
|
||||
and VoiceProfilesType.is_valid_call(str(data.get(
|
||||
"call_id",
|
||||
VoiceProfilesType.DEFAULT_CALL_ID,
|
||||
)))
|
||||
and VoiceProfilesType.is_valid_sample_set(str(data.get(
|
||||
"sample_set_id",
|
||||
VoiceProfilesType.DEFAULT_SAMPLE_SET_ID,
|
||||
)))
|
||||
and int(data.get("created_at_unix", -1)) >= 0
|
||||
)
|
||||
|
||||
|
||||
func restore_from_save_data(
|
||||
value: Variant,
|
||||
persist_to_profile_file: bool = true,
|
||||
) -> bool:
|
||||
if not validate_save_data(value):
|
||||
return false
|
||||
var data: Dictionary = value
|
||||
var previous: Dictionary = to_save_data()
|
||||
profile_id = str(data["profile_id"])
|
||||
display_name = str(data["display_name"]).strip_edges()
|
||||
title = str(data.get("title", DEFAULT_TITLE)).strip_edges()
|
||||
voice_id = str(data.get("voice_id", VoiceProfilesType.DEFAULT_ID))
|
||||
speech_speed_id = str(data.get(
|
||||
"speech_speed_id",
|
||||
VoiceProfilesType.DEFAULT_SPEED_ID,
|
||||
))
|
||||
call_id = str(data.get("call_id", VoiceProfilesType.DEFAULT_CALL_ID))
|
||||
sample_set_id = str(data.get(
|
||||
"sample_set_id",
|
||||
VoiceProfilesType.DEFAULT_SAMPLE_SET_ID,
|
||||
))
|
||||
created_at_unix = int(data["created_at_unix"])
|
||||
if persist_to_profile_file and not _save_atomic():
|
||||
_assign_save_data(previous)
|
||||
return false
|
||||
if to_save_data() != previous:
|
||||
profile_changed.emit()
|
||||
return true
|
||||
|
||||
|
||||
func reset_to_defaults(persist_to_profile_file: bool = true) -> bool:
|
||||
var previous: Dictionary = to_save_data()
|
||||
profile_id = Crypto.new().generate_random_bytes(16).hex_encode()
|
||||
if profile_id.is_empty():
|
||||
profile_id = "%d-%d" % [
|
||||
int(Time.get_unix_time_from_system()),
|
||||
Time.get_ticks_usec(),
|
||||
]
|
||||
display_name = DEFAULT_DISPLAY_NAME
|
||||
title = DEFAULT_TITLE
|
||||
voice_id = VoiceProfilesType.DEFAULT_ID
|
||||
speech_speed_id = VoiceProfilesType.DEFAULT_SPEED_ID
|
||||
call_id = VoiceProfilesType.DEFAULT_CALL_ID
|
||||
sample_set_id = VoiceProfilesType.DEFAULT_SAMPLE_SET_ID
|
||||
created_at_unix = int(Time.get_unix_time_from_system())
|
||||
if persist_to_profile_file and not _save_atomic():
|
||||
_assign_save_data(previous)
|
||||
return false
|
||||
profile_changed.emit()
|
||||
return true
|
||||
|
||||
|
||||
func set_display_name(value: String) -> bool:
|
||||
return set_profile_identity(
|
||||
value,
|
||||
|
|
@ -72,6 +185,7 @@ func set_display_name(value: String) -> bool:
|
|||
speech_speed_id,
|
||||
call_id,
|
||||
sample_set_id,
|
||||
title,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -81,10 +195,15 @@ func set_profile_identity(
|
|||
selected_speech_speed_id: String,
|
||||
selected_call_id: String,
|
||||
selected_sample_set_id: String = VoiceProfilesType.DEFAULT_SAMPLE_SET_ID,
|
||||
selected_title: String = "",
|
||||
) -> bool:
|
||||
var clean_name: String = value.strip_edges()
|
||||
var clean_title: String = (
|
||||
title if selected_title.is_empty() else selected_title.strip_edges()
|
||||
)
|
||||
if (
|
||||
not is_valid_display_name(clean_name)
|
||||
or not is_valid_title(clean_title)
|
||||
or not VoiceProfilesType.is_valid(selected_voice_id)
|
||||
or not VoiceProfilesType.is_valid_speed(selected_speech_speed_id)
|
||||
or not VoiceProfilesType.is_valid_call(selected_call_id)
|
||||
|
|
@ -92,18 +211,30 @@ func set_profile_identity(
|
|||
):
|
||||
return false
|
||||
var previous_name: String = display_name
|
||||
var previous_title: String = title
|
||||
var previous_voice_id: String = voice_id
|
||||
var previous_speech_speed_id: String = speech_speed_id
|
||||
var previous_call_id: String = call_id
|
||||
var previous_sample_set_id: String = sample_set_id
|
||||
display_name = clean_name
|
||||
title = clean_title
|
||||
voice_id = selected_voice_id
|
||||
speech_speed_id = selected_speech_speed_id
|
||||
call_id = selected_call_id
|
||||
sample_set_id = selected_sample_set_id
|
||||
if _save_atomic():
|
||||
if (
|
||||
display_name != previous_name
|
||||
or voice_id != previous_voice_id
|
||||
or title != previous_title
|
||||
or speech_speed_id != previous_speech_speed_id
|
||||
or call_id != previous_call_id
|
||||
or sample_set_id != previous_sample_set_id
|
||||
):
|
||||
profile_changed.emit()
|
||||
return true
|
||||
display_name = previous_name
|
||||
title = previous_title
|
||||
voice_id = previous_voice_id
|
||||
speech_speed_id = previous_speech_speed_id
|
||||
call_id = previous_call_id
|
||||
|
|
@ -111,6 +242,23 @@ func set_profile_identity(
|
|||
return false
|
||||
|
||||
|
||||
func _assign_save_data(data: Dictionary) -> void:
|
||||
profile_id = str(data.get("profile_id", ""))
|
||||
display_name = str(data.get("display_name", DEFAULT_DISPLAY_NAME))
|
||||
title = str(data.get("title", DEFAULT_TITLE))
|
||||
voice_id = str(data.get("voice_id", VoiceProfilesType.DEFAULT_ID))
|
||||
speech_speed_id = str(data.get(
|
||||
"speech_speed_id",
|
||||
VoiceProfilesType.DEFAULT_SPEED_ID,
|
||||
))
|
||||
call_id = str(data.get("call_id", VoiceProfilesType.DEFAULT_CALL_ID))
|
||||
sample_set_id = str(data.get(
|
||||
"sample_set_id",
|
||||
VoiceProfilesType.DEFAULT_SAMPLE_SET_ID,
|
||||
))
|
||||
created_at_unix = int(data.get("created_at_unix", 0))
|
||||
|
||||
|
||||
static func is_valid_display_name(value: String) -> bool:
|
||||
var clean_name := value.strip_edges()
|
||||
if clean_name.is_empty() or clean_name.length() > 24:
|
||||
|
|
@ -122,6 +270,17 @@ static func is_valid_display_name(value: String) -> bool:
|
|||
return true
|
||||
|
||||
|
||||
static func is_valid_title(value: String) -> bool:
|
||||
var clean_title := value.strip_edges()
|
||||
if clean_title.is_empty() or clean_title.length() > NetworkProtocol.MAX_PLAYER_TITLE_LENGTH:
|
||||
return false
|
||||
for index: int in clean_title.length():
|
||||
var codepoint: int = clean_title.unicode_at(index)
|
||||
if codepoint < 32 or codepoint == 127:
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _load_existing() -> bool:
|
||||
var file := FileAccess.open(_profile_path, FileAccess.READ)
|
||||
if file == null:
|
||||
|
|
@ -142,20 +301,27 @@ func _load_existing() -> bool:
|
|||
data.get("format_version") != FORMAT_VERSION
|
||||
or typeof(data.get("profile_id")) != TYPE_STRING
|
||||
or typeof(data.get("display_name")) != TYPE_STRING
|
||||
or (
|
||||
data.has("title")
|
||||
and typeof(data.get("title")) != TYPE_STRING
|
||||
)
|
||||
or typeof(data.get("created_at_unix")) not in [TYPE_INT, TYPE_FLOAT]
|
||||
):
|
||||
return false
|
||||
var loaded_id: String = data["profile_id"]
|
||||
var loaded_name: String = data["display_name"]
|
||||
var loaded_title := str(data.get("title", DEFAULT_TITLE))
|
||||
if (
|
||||
loaded_id.is_empty()
|
||||
or loaded_id.length() > NetworkProtocol.MAX_PROFILE_ID_LENGTH
|
||||
or loaded_name.is_empty()
|
||||
or loaded_name.length() > NetworkProtocol.MAX_DISPLAY_NAME_LENGTH
|
||||
or not is_valid_title(loaded_title)
|
||||
):
|
||||
return false
|
||||
profile_id = loaded_id
|
||||
display_name = loaded_name
|
||||
title = loaded_title.strip_edges()
|
||||
voice_id = VoiceProfilesType.sanitized_id(
|
||||
str(data.get("voice_id", VoiceProfilesType.DEFAULT_ID))
|
||||
)
|
||||
|
|
@ -180,6 +346,7 @@ func _save_atomic() -> bool:
|
|||
"format_version": FORMAT_VERSION,
|
||||
"profile_id": profile_id,
|
||||
"display_name": display_name,
|
||||
"title": title,
|
||||
"voice_id": voice_id,
|
||||
"speech_speed_id": speech_speed_id,
|
||||
"call_id": call_id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue