Refresh menus chat and player expression
BIN
items/icons/equipment/64_cooler_plus.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
40
items/icons/equipment/64_cooler_plus.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://baht2hredfky8"
|
||||
path="res://.godot/imported/64_cooler_plus.png-d0daa39246f92fd9774ec1721970efad.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/icons/equipment/64_cooler_plus.png"
|
||||
dest_files=["res://.godot/imported/64_cooler_plus.png-d0daa39246f92fd9774ec1721970efad.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
|
@ -36,7 +36,7 @@ var _pending_rewards: Array[Dictionary] = []
|
|||
var _lifetime_claimed: Array[String] = []
|
||||
var _total_catches: int = 0
|
||||
var _total_sold: int = 0
|
||||
var _previous_hour: float = WorldTimeService.DEFAULT_START_HOUR
|
||||
var _daily_clock_hour: float = WorldTimeService.DEFAULT_START_HOUR
|
||||
|
||||
|
||||
func setup(
|
||||
|
|
@ -55,8 +55,8 @@ func setup(
|
|||
_world_time = world_time
|
||||
_world_weather = world_weather
|
||||
_session = session
|
||||
_previous_hour = _world_time.get_time_hours()
|
||||
_world_time.time_changed.connect(_on_time_changed)
|
||||
_daily_clock_hour = _world_time.get_time_hours()
|
||||
_world_time.natural_time_advanced.connect(_on_natural_time_advanced)
|
||||
_session.state_changed.connect(_on_session_state_changed)
|
||||
_collection.collection_changed.connect(_on_current_state_changed)
|
||||
_experience.experience_changed.connect(_on_experience_changed)
|
||||
|
|
@ -86,7 +86,6 @@ func set_save_manager(save_manager: PlayerSaveManager) -> void:
|
|||
|
||||
func begin_progression_session() -> void:
|
||||
_progression_ready = true
|
||||
_previous_hour = _world_time.get_time_hours()
|
||||
if _session.is_host():
|
||||
_activate_host_board()
|
||||
changed.emit()
|
||||
|
|
@ -155,7 +154,7 @@ func get_time_until_refresh_text() -> String:
|
|||
if _active_plan_id.is_empty() or _world_time == null:
|
||||
return "daily jobs unavailable"
|
||||
var elapsed: float = fposmod(
|
||||
_world_time.get_time_hours() - DAILY_REFRESH_HOUR,
|
||||
_daily_clock_hour - DAILY_REFRESH_HOUR,
|
||||
WorldTimeService.HOURS_PER_DAY,
|
||||
)
|
||||
var hours_remaining: float = WorldTimeService.HOURS_PER_DAY - elapsed
|
||||
|
|
@ -185,7 +184,10 @@ func claim(claim_id: String) -> bool:
|
|||
|
||||
|
||||
func get_host_board_network_data() -> Dictionary:
|
||||
return _host_board.duplicate(true)
|
||||
var board := _host_board.duplicate(true)
|
||||
if not board.is_empty():
|
||||
board["daily_clock_hour"] = _daily_clock_hour
|
||||
return board
|
||||
|
||||
|
||||
func apply_remote_board(board: Dictionary) -> bool:
|
||||
|
|
@ -198,6 +200,8 @@ func apply_remote_board(board: Dictionary) -> bool:
|
|||
_daily_progress.clear()
|
||||
_daily_completions.clear()
|
||||
_active_board = board.duplicate(true)
|
||||
if board.has("daily_clock_hour"):
|
||||
_daily_clock_hour = float(board["daily_clock_hour"])
|
||||
changed.emit()
|
||||
return true
|
||||
|
||||
|
|
@ -223,6 +227,7 @@ func to_save_data() -> Dictionary:
|
|||
"active_plan_id": _active_plan_id,
|
||||
"daily_progress": progress,
|
||||
"daily_completions": completions,
|
||||
"daily_clock_hour": _daily_clock_hour,
|
||||
"pending_rewards": _pending_rewards.duplicate(true),
|
||||
"lifetime_claimed": _lifetime_claimed.duplicate(),
|
||||
"statistics": {
|
||||
|
|
@ -246,6 +251,12 @@ func restore_from_save_data(data: Dictionary) -> bool:
|
|||
var completions: Dictionary = data.get("daily_completions", {})
|
||||
for key: Variant in completions:
|
||||
_daily_completions[str(key)] = mini(int(completions[key]), 1)
|
||||
_daily_clock_hour = float(data.get(
|
||||
"daily_clock_hour",
|
||||
_world_time.get_time_hours()
|
||||
if _world_time != null
|
||||
else WorldTimeService.DEFAULT_START_HOUR,
|
||||
))
|
||||
_pending_rewards.clear()
|
||||
var rewards: Array = data.get("pending_rewards", [])
|
||||
var restored_daily_rewards: Dictionary[String, bool] = {}
|
||||
|
|
@ -290,6 +301,7 @@ func reset_to_defaults() -> void:
|
|||
_lifetime_claimed.clear()
|
||||
_total_catches = 0
|
||||
_total_sold = 0
|
||||
_daily_clock_hour = WorldTimeService.DEFAULT_START_HOUR
|
||||
changed.emit()
|
||||
|
||||
|
||||
|
|
@ -300,6 +312,7 @@ static func default_save_data() -> Dictionary:
|
|||
"active_plan_id": "",
|
||||
"daily_progress": {},
|
||||
"daily_completions": {},
|
||||
"daily_clock_hour": WorldTimeService.DEFAULT_START_HOUR,
|
||||
"pending_rewards": [],
|
||||
"lifetime_claimed": [],
|
||||
"statistics": {"fish_caught": 0, "fish_sold": 0},
|
||||
|
|
@ -363,6 +376,16 @@ static func validate_save_data(value: Variant) -> bool:
|
|||
var host_board: Dictionary = data.get("host_board", {})
|
||||
if not host_board.is_empty() and not validate_board(host_board):
|
||||
return false
|
||||
if (
|
||||
data.has("daily_clock_hour")
|
||||
and (
|
||||
typeof(data["daily_clock_hour"]) not in [TYPE_FLOAT, TYPE_INT]
|
||||
or not is_finite(float(data["daily_clock_hour"]))
|
||||
or float(data["daily_clock_hour"]) < 0.0
|
||||
or float(data["daily_clock_hour"]) >= WorldTimeService.HOURS_PER_DAY
|
||||
)
|
||||
):
|
||||
return false
|
||||
var progress: Dictionary = data.get("daily_progress", {})
|
||||
if progress.size() > 8:
|
||||
return false
|
||||
|
|
@ -475,19 +498,22 @@ func _apply_host_weather_plan() -> void:
|
|||
)
|
||||
|
||||
|
||||
func _on_time_changed(
|
||||
time_hours: float,
|
||||
_phase: WorldTimeService.Phase,
|
||||
) -> void:
|
||||
func _on_natural_time_advanced(hours: float) -> void:
|
||||
if not is_finite(hours) or hours <= 0.0:
|
||||
return
|
||||
var previous_hour := _daily_clock_hour
|
||||
_daily_clock_hour = fposmod(
|
||||
_daily_clock_hour + hours,
|
||||
WorldTimeService.HOURS_PER_DAY,
|
||||
)
|
||||
if (
|
||||
_progression_ready
|
||||
and _session != null
|
||||
and _session.is_host()
|
||||
and _crossed_daily_refresh(_previous_hour, time_hours)
|
||||
and _crossed_daily_refresh(previous_hour, _daily_clock_hour)
|
||||
):
|
||||
var cycle: int = int(_host_board.get("cycle", -1)) + 1
|
||||
_generate_host_board(maxi(cycle, 0))
|
||||
_previous_hour = time_hours
|
||||
|
||||
|
||||
func _on_session_state_changed(state: NetworkSession.State) -> void:
|
||||
|
|
|
|||
|
|
@ -79,6 +79,21 @@ func send_local_message(body: String) -> bool:
|
|||
return true
|
||||
|
||||
|
||||
func broadcast_system_message(body: String) -> bool:
|
||||
if _session == null or not _session.is_host():
|
||||
return false
|
||||
var clean := NetworkChatProtocol.sanitize_body(body)
|
||||
if clean.is_empty():
|
||||
return false
|
||||
_broadcast(_make_message(
|
||||
NetworkChatProtocol.Kind.SYSTEM,
|
||||
0,
|
||||
"",
|
||||
clean,
|
||||
))
|
||||
return true
|
||||
|
||||
|
||||
func get_history() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
for message: Dictionary in _history:
|
||||
|
|
|
|||
|
|
@ -2,8 +2,13 @@ class_name NetworkProfilePreferences
|
|||
extends Node
|
||||
|
||||
const FORMAT_VERSION: int = 1
|
||||
const VoiceProfilesType = preload(
|
||||
"res://player/animalese_voice_profiles.gd"
|
||||
)
|
||||
var profile_id: String = ""
|
||||
var display_name: String = "Player"
|
||||
var voice_id: String = VoiceProfilesType.DEFAULT_ID
|
||||
var speech_speed_id: String = VoiceProfilesType.DEFAULT_SPEED_ID
|
||||
var created_at_unix: int = 0
|
||||
var _profile_path := ""
|
||||
var _expected_hash := ""
|
||||
|
|
@ -48,19 +53,39 @@ func load_or_create() -> bool:
|
|||
Time.get_ticks_usec(),
|
||||
]
|
||||
display_name = "Player"
|
||||
voice_id = VoiceProfilesType.DEFAULT_ID
|
||||
speech_speed_id = VoiceProfilesType.DEFAULT_SPEED_ID
|
||||
created_at_unix = int(Time.get_unix_time_from_system())
|
||||
return _save_atomic()
|
||||
|
||||
|
||||
func set_display_name(value: String) -> bool:
|
||||
return set_profile_identity(value, voice_id, speech_speed_id)
|
||||
|
||||
|
||||
func set_profile_identity(
|
||||
value: String,
|
||||
selected_voice_id: String,
|
||||
selected_speech_speed_id: String,
|
||||
) -> bool:
|
||||
var clean_name: String = value.strip_edges()
|
||||
if not is_valid_display_name(clean_name):
|
||||
if (
|
||||
not is_valid_display_name(clean_name)
|
||||
or not VoiceProfilesType.is_valid(selected_voice_id)
|
||||
or not VoiceProfilesType.is_valid_speed(selected_speech_speed_id)
|
||||
):
|
||||
return false
|
||||
var previous: String = display_name
|
||||
var previous_name: String = display_name
|
||||
var previous_voice_id: String = voice_id
|
||||
var previous_speech_speed_id: String = speech_speed_id
|
||||
display_name = clean_name
|
||||
voice_id = selected_voice_id
|
||||
speech_speed_id = selected_speech_speed_id
|
||||
if _save_atomic():
|
||||
return true
|
||||
display_name = previous
|
||||
display_name = previous_name
|
||||
voice_id = previous_voice_id
|
||||
speech_speed_id = previous_speech_speed_id
|
||||
return false
|
||||
|
||||
|
||||
|
|
@ -109,6 +134,12 @@ func _load_existing() -> bool:
|
|||
return false
|
||||
profile_id = loaded_id
|
||||
display_name = loaded_name
|
||||
voice_id = VoiceProfilesType.sanitized_id(
|
||||
str(data.get("voice_id", VoiceProfilesType.DEFAULT_ID))
|
||||
)
|
||||
speech_speed_id = VoiceProfilesType.sanitized_speed_id(
|
||||
str(data.get("speech_speed_id", VoiceProfilesType.DEFAULT_SPEED_ID))
|
||||
)
|
||||
created_at_unix = int(data["created_at_unix"])
|
||||
return true
|
||||
|
||||
|
|
@ -118,6 +149,8 @@ func _save_atomic() -> bool:
|
|||
"format_version": FORMAT_VERSION,
|
||||
"profile_id": profile_id,
|
||||
"display_name": display_name,
|
||||
"voice_id": voice_id,
|
||||
"speech_speed_id": speech_speed_id,
|
||||
"created_at_unix": created_at_unix,
|
||||
}
|
||||
var result := PortableFileGuard.write_guarded(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
class_name NetworkProfileService
|
||||
extends Node
|
||||
|
||||
const VoiceProfilesType = preload(
|
||||
"res://player/animalese_voice_profiles.gd"
|
||||
)
|
||||
|
||||
signal conflict_result(
|
||||
request_id: String,
|
||||
has_conflict: bool,
|
||||
|
|
@ -18,6 +22,8 @@ var _preferences: NetworkProfilePreferences
|
|||
var _appearance_store: PlayerAppearanceStore
|
||||
var _spawn_service: PlayerSpawnService
|
||||
var _pending_apply: Dictionary[String, Dictionary] = {}
|
||||
var _pending_voice_ids: Dictionary[String, String] = {}
|
||||
var _pending_speech_speed_ids: Dictionary[String, String] = {}
|
||||
var _host_pending_apply: Dictionary[String, Dictionary] = {}
|
||||
var _latest_check_id: String = ""
|
||||
var _latest_check_name: String = ""
|
||||
|
|
@ -40,6 +46,7 @@ func setup(
|
|||
_session.join_authenticated.connect(_on_join_authenticated)
|
||||
_session.state_changed.connect(_on_session_state_changed)
|
||||
_apply_to_avatar(1, _appearance_store.get_snapshot())
|
||||
_apply_local_voice_to_avatar()
|
||||
|
||||
|
||||
func get_persisted_name() -> String:
|
||||
|
|
@ -50,6 +57,14 @@ func get_persisted_appearance() -> Dictionary:
|
|||
return _appearance_store.get_snapshot()
|
||||
|
||||
|
||||
func get_persisted_voice_id() -> String:
|
||||
return _preferences.voice_id
|
||||
|
||||
|
||||
func get_persisted_speech_speed_id() -> String:
|
||||
return _preferences.speech_speed_id
|
||||
|
||||
|
||||
func get_identity_fingerprint() -> String:
|
||||
return (
|
||||
_session.get_local_identity_fingerprint()
|
||||
|
|
@ -87,11 +102,15 @@ func apply_profile(
|
|||
display_name: String,
|
||||
appearance: Dictionary,
|
||||
use_anyway: bool,
|
||||
voice_id: String = VoiceProfilesType.DEFAULT_ID,
|
||||
speech_speed_id: String = VoiceProfilesType.DEFAULT_SPEED_ID,
|
||||
) -> bool:
|
||||
var clean_name := display_name.strip_edges()
|
||||
if (
|
||||
not NetworkProfilePreferences.is_valid_display_name(clean_name)
|
||||
or not CharacterCustomizationCatalog.validate_snapshot(appearance)
|
||||
or not VoiceProfilesType.is_valid(voice_id)
|
||||
or not VoiceProfilesType.is_valid_speed(speech_speed_id)
|
||||
):
|
||||
apply_finished.emit(false, "Check the player name and appearance choices.")
|
||||
return false
|
||||
|
|
@ -108,6 +127,8 @@ func apply_profile(
|
|||
"profile_update", NetworkProfileProtocol.signature_fields(request)
|
||||
)
|
||||
_pending_apply[request_id] = request
|
||||
_pending_voice_ids[request_id] = voice_id
|
||||
_pending_speech_speed_ids[request_id] = speech_speed_id
|
||||
if _session == null or not _session.is_gameplay_session_active():
|
||||
_apply_local_result(request_id, true, "", false, PackedStringArray())
|
||||
elif _session.is_host():
|
||||
|
|
@ -264,20 +285,46 @@ func _apply_local_result(
|
|||
return
|
||||
if not accepted:
|
||||
_pending_apply.erase(request_id)
|
||||
_pending_voice_ids.erase(request_id)
|
||||
_pending_speech_speed_ids.erase(request_id)
|
||||
conflict_result.emit(request_id, conflict, suggestions)
|
||||
apply_finished.emit(false, message)
|
||||
return
|
||||
var previous_name := _preferences.display_name
|
||||
if not _preferences.set_display_name(str(request["display_name"])):
|
||||
var previous_voice_id := _preferences.voice_id
|
||||
var previous_speech_speed_id := _preferences.speech_speed_id
|
||||
var requested_voice_id: String = _pending_voice_ids.get(
|
||||
request_id,
|
||||
VoiceProfilesType.DEFAULT_ID,
|
||||
)
|
||||
var requested_speech_speed_id: String = _pending_speech_speed_ids.get(
|
||||
request_id,
|
||||
VoiceProfilesType.DEFAULT_SPEED_ID,
|
||||
)
|
||||
if not _preferences.set_profile_identity(
|
||||
str(request["display_name"]),
|
||||
requested_voice_id,
|
||||
requested_speech_speed_id,
|
||||
):
|
||||
_pending_apply.erase(request_id)
|
||||
_pending_voice_ids.erase(request_id)
|
||||
_pending_speech_speed_ids.erase(request_id)
|
||||
apply_finished.emit(false, "Profile could not be saved.")
|
||||
return
|
||||
if not _appearance_store.save_snapshot(request["appearance"]):
|
||||
_preferences.set_display_name(previous_name)
|
||||
_preferences.set_profile_identity(
|
||||
previous_name,
|
||||
previous_voice_id,
|
||||
previous_speech_speed_id,
|
||||
)
|
||||
_pending_apply.erase(request_id)
|
||||
_pending_voice_ids.erase(request_id)
|
||||
_pending_speech_speed_ids.erase(request_id)
|
||||
apply_finished.emit(false, "Profile could not be saved.")
|
||||
return
|
||||
_pending_apply.erase(request_id)
|
||||
_pending_voice_ids.erase(request_id)
|
||||
_pending_speech_speed_ids.erase(request_id)
|
||||
if _session != null and _session.is_gameplay_session_active():
|
||||
if _session.is_host():
|
||||
_session.apply_canonical_profile(
|
||||
|
|
@ -304,6 +351,7 @@ func _apply_local_result(
|
|||
_session.get_local_peer_id() if _session != null else 1,
|
||||
_appearance_store.get_snapshot(),
|
||||
)
|
||||
_apply_local_voice_to_avatar()
|
||||
apply_finished.emit(true, "Profile saved.")
|
||||
|
||||
|
||||
|
|
@ -361,6 +409,7 @@ func _on_join_authenticated() -> void:
|
|||
_apply_to_avatar(
|
||||
_session.get_local_peer_id(), _appearance_store.get_snapshot()
|
||||
)
|
||||
_apply_local_voice_to_avatar()
|
||||
|
||||
|
||||
func _on_peer_removed(_peer_id: int) -> void:
|
||||
|
|
@ -400,6 +449,8 @@ func _refresh_latest_check() -> void:
|
|||
func _on_session_state_changed(state: NetworkSession.State) -> void:
|
||||
if state == NetworkSession.State.INACTIVE:
|
||||
_pending_apply.clear()
|
||||
_pending_voice_ids.clear()
|
||||
_pending_speech_speed_ids.clear()
|
||||
_host_pending_apply.clear()
|
||||
_latest_check_id = ""
|
||||
_latest_check_name = ""
|
||||
|
|
@ -465,5 +516,16 @@ func _apply_to_avatar(peer_id: int, appearance: Dictionary) -> void:
|
|||
avatar.apply_appearance_snapshot(appearance)
|
||||
|
||||
|
||||
func _apply_local_voice_to_avatar() -> void:
|
||||
if _spawn_service == null:
|
||||
return
|
||||
var local_peer_id := (
|
||||
_session.get_local_peer_id() if _session != null else 1
|
||||
)
|
||||
var avatar := _spawn_service.get_avatar(local_peer_id)
|
||||
if avatar != null:
|
||||
avatar.apply_animalese_voice_id(_preferences.voice_id)
|
||||
|
||||
|
||||
func _new_id() -> String:
|
||||
return Crypto.new().generate_random_bytes(16).hex_encode()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ func setup(session: NetworkSession, world_time: WorldTimeService) -> void:
|
|||
_world_time = world_time
|
||||
_session.state_changed.connect(_on_session_state_changed)
|
||||
_session.peer_authenticated.connect(_on_peer_authenticated)
|
||||
if not _world_time.authoritative_time_set.is_connected(
|
||||
_on_authoritative_time_set
|
||||
):
|
||||
_world_time.authoritative_time_set.connect(
|
||||
_on_authoritative_time_set
|
||||
)
|
||||
set_process(true)
|
||||
|
||||
|
||||
|
|
@ -82,6 +88,13 @@ func _on_peer_authenticated(peer_id: int, _display_name: String) -> void:
|
|||
_send_snapshot(peer_id)
|
||||
|
||||
|
||||
func _on_authoritative_time_set(_time_hours: float) -> void:
|
||||
if _session == null or not _session.is_host():
|
||||
return
|
||||
_sync_elapsed = 0.0
|
||||
_broadcast_snapshot()
|
||||
|
||||
|
||||
func _broadcast_snapshot() -> void:
|
||||
if _session == null or not _session.is_host():
|
||||
return
|
||||
|
|
|
|||
57
player/animalese_voice_profiles.gd
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
class_name AnimaleseVoiceProfiles
|
||||
extends RefCounted
|
||||
|
||||
const DEFAULT_ID: String = "natural"
|
||||
const DEFAULT_SPEED_ID: String = "normal"
|
||||
const OPTIONS: Array[Dictionary] = [
|
||||
{"id": "tiny", "label": "tiny", "pitch": 1.24},
|
||||
{"id": "bright", "label": "bright", "pitch": 1.10},
|
||||
{"id": "natural", "label": "natural", "pitch": 1.0},
|
||||
{"id": "mellow", "label": "mellow", "pitch": 0.89},
|
||||
{"id": "deep", "label": "deep", "pitch": 0.77},
|
||||
]
|
||||
const SPEED_OPTIONS: Array[Dictionary] = [
|
||||
{"id": "slow", "label": "slow", "characters_per_second": 20.0},
|
||||
{"id": "relaxed", "label": "relaxed", "characters_per_second": 24.0},
|
||||
{"id": "normal", "label": "normal", "characters_per_second": 28.0},
|
||||
{"id": "quick", "label": "quick", "characters_per_second": 34.0},
|
||||
{"id": "rapid", "label": "rapid", "characters_per_second": 40.0},
|
||||
]
|
||||
|
||||
|
||||
static func is_valid(voice_id: String) -> bool:
|
||||
for option: Dictionary in OPTIONS:
|
||||
if str(option.get("id", "")) == voice_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
static func sanitized_id(voice_id: String) -> String:
|
||||
return voice_id if is_valid(voice_id) else DEFAULT_ID
|
||||
|
||||
|
||||
static func pitch_for(voice_id: String) -> float:
|
||||
var resolved_id := sanitized_id(voice_id)
|
||||
for option: Dictionary in OPTIONS:
|
||||
if str(option.get("id", "")) == resolved_id:
|
||||
return float(option.get("pitch", 1.0))
|
||||
return 1.0
|
||||
|
||||
|
||||
static func is_valid_speed(speed_id: String) -> bool:
|
||||
for option: Dictionary in SPEED_OPTIONS:
|
||||
if str(option.get("id", "")) == speed_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
static func sanitized_speed_id(speed_id: String) -> String:
|
||||
return speed_id if is_valid_speed(speed_id) else DEFAULT_SPEED_ID
|
||||
|
||||
|
||||
static func speed_for(speed_id: String) -> float:
|
||||
var resolved_id := sanitized_speed_id(speed_id)
|
||||
for option: Dictionary in SPEED_OPTIONS:
|
||||
if str(option.get("id", "")) == resolved_id:
|
||||
return float(option.get("characters_per_second", 28.0))
|
||||
return 28.0
|
||||
1
player/animalese_voice_profiles.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://dlut32tq2v66j
|
||||
185
player/player.gd
|
|
@ -50,6 +50,7 @@ const CONTROLLER_ZOOM_TRIGGER_AXIS: JoyAxis = JOY_AXIS_TRIGGER_LEFT
|
|||
var appearance_snapshot: Dictionary = (
|
||||
CharacterCustomizationCatalog.default_snapshot()
|
||||
)
|
||||
var animalese_voice_id: String = "natural"
|
||||
var active_bait_id: StringName = StringName()
|
||||
signal active_bait_changed(item_id: StringName)
|
||||
|
||||
|
|
@ -76,6 +77,14 @@ func apply_appearance_snapshot(snapshot: Dictionary) -> void:
|
|||
appearance_snapshot = snapshot.duplicate(true)
|
||||
PlayerVisualPresenter.apply_appearance(_visuals, appearance_snapshot)
|
||||
|
||||
|
||||
func apply_animalese_voice_id(voice_id: String) -> void:
|
||||
animalese_voice_id = voice_id
|
||||
|
||||
|
||||
func get_animalese_voice_id() -> String:
|
||||
return animalese_voice_id
|
||||
|
||||
class ShowcaseCameraSnapshot:
|
||||
extends RefCounted
|
||||
|
||||
|
|
@ -129,6 +138,8 @@ class ShowcaseCameraSnapshot:
|
|||
@export var zoom_smoothing: float = 12.0
|
||||
@export_range(0.1, 12.0, 0.1) var controller_zoom_speed: float = 4.0
|
||||
@export_range(0.0, 1.0, 0.01) var controller_trigger_threshold: float = 0.55
|
||||
@export_range(1.0, 40.0, 0.5) var free_camera_speed: float = 10.0
|
||||
@export_range(1.0, 10.0, 0.5) var free_camera_sprint_multiplier: float = 3.0
|
||||
|
||||
@onready var _visuals: Node3D = %Visuals
|
||||
@onready var _character_rig: Node3D = get_node_or_null(
|
||||
|
|
@ -141,6 +152,7 @@ class ShowcaseCameraSnapshot:
|
|||
@onready var _camera_pitch: Node3D = %CameraPitch
|
||||
@onready var _spring_arm: SpringArm3D = %SpringArm3D
|
||||
@onready var _camera: Camera3D = %Camera3D
|
||||
@onready var _player_collision_shape: CollisionShape3D = $CollisionShape3D
|
||||
@onready var inventory: FishInventoryType = %Inventory
|
||||
@onready var collection_log: CollectionLogType = %CollectionLog
|
||||
@onready var wallet: PlayerWalletType = %Wallet
|
||||
|
|
@ -165,6 +177,11 @@ var _catch_attachment_offset: Vector3 = Vector3(0.0, 0.08, 0.04)
|
|||
var _gravity: float = float(ProjectSettings.get_setting("physics/3d/default_gravity"))
|
||||
var _camera_dragging: bool = false
|
||||
var _camera_input_enabled: bool = true
|
||||
var _free_camera_active: bool = false
|
||||
var _free_camera_body: CharacterBody3D
|
||||
var _free_camera: Camera3D
|
||||
var _free_camera_yaw: float = 0.0
|
||||
var _free_camera_pitch: float = 0.0
|
||||
var _movement_enabled: bool = true
|
||||
var _water_recovery_active: bool = false
|
||||
var _remote_recovery_presentation_active: bool = false
|
||||
|
|
@ -197,6 +214,8 @@ var _network_target_visual_yaw: float = 0.0
|
|||
var _network_snapshot_ready: bool = false
|
||||
var _character_animation_name: StringName = &""
|
||||
var _sitting: bool = false
|
||||
var _sitting_intent_pending: bool = false
|
||||
var _sitting_intent_sequence: int = -1
|
||||
var _held_fish_visible: bool = false
|
||||
var _showcase_animation_active: bool = false
|
||||
var _fishing_rod: Node3D
|
||||
|
|
@ -205,6 +224,8 @@ var _controller_mapping_manager: ControllerMappingManagerType
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
if not bag.contents_changed.is_connected(_on_bag_contents_changed):
|
||||
bag.contents_changed.connect(_on_bag_contents_changed)
|
||||
PlayerVisualPresenter.apply_appearance(_visuals, appearance_snapshot)
|
||||
_initialize_fishing_rod()
|
||||
_target_zoom = clampf(_spring_arm.spring_length, minimum_zoom, maximum_zoom)
|
||||
|
|
@ -213,6 +234,14 @@ func _ready() -> void:
|
|||
_initialize_held_item_attachment()
|
||||
|
||||
|
||||
func _on_bag_contents_changed() -> void:
|
||||
if (
|
||||
not active_bait_id.is_empty()
|
||||
and bag.get_quantity(active_bait_id) <= 0
|
||||
):
|
||||
unequip_bait()
|
||||
|
||||
|
||||
func set_controller_mapping_manager(
|
||||
mapping_manager: ControllerMappingManagerType,
|
||||
) -> void:
|
||||
|
|
@ -267,8 +296,18 @@ func _physics_process(delta: float) -> void:
|
|||
if _network_interpolation_enabled:
|
||||
_update_network_interpolation(delta)
|
||||
return
|
||||
if local_control_enabled and _free_camera_active:
|
||||
_update_free_camera_physics()
|
||||
velocity.x = 0.0
|
||||
velocity.z = 0.0
|
||||
if not is_on_floor():
|
||||
velocity.y -= _gravity * fall_gravity_multiplier * delta
|
||||
move_and_slide()
|
||||
_network_jump_pending = false
|
||||
return
|
||||
var jump_requested: bool = (
|
||||
_movement_enabled
|
||||
and not _free_camera_active
|
||||
and (
|
||||
(local_control_enabled and Input.is_action_just_pressed("jump"))
|
||||
or (_network_authoritative_simulation and _network_jump_pending)
|
||||
|
|
@ -276,7 +315,7 @@ func _physics_process(delta: float) -> void:
|
|||
)
|
||||
if _sitting:
|
||||
if jump_requested:
|
||||
_set_sitting(false)
|
||||
_set_sitting(false, local_control_enabled)
|
||||
else:
|
||||
velocity = Vector3.ZERO
|
||||
_network_jump_pending = false
|
||||
|
|
@ -370,6 +409,8 @@ func _process(delta: float) -> void:
|
|||
)
|
||||
if not local_control_enabled:
|
||||
return
|
||||
if _free_camera_active:
|
||||
return
|
||||
|
||||
if (
|
||||
_camera_input_enabled
|
||||
|
|
@ -519,7 +560,7 @@ func toggle_sitting() -> void:
|
|||
])
|
||||
):
|
||||
return
|
||||
_set_sitting(should_sit)
|
||||
_set_sitting(should_sit, local_control_enabled)
|
||||
|
||||
|
||||
func _has_any_character_animation(candidates: Array[StringName]) -> bool:
|
||||
|
|
@ -531,10 +572,16 @@ func _has_any_character_animation(candidates: Array[StringName]) -> bool:
|
|||
return false
|
||||
|
||||
|
||||
func _set_sitting(should_sit: bool) -> void:
|
||||
func _set_sitting(
|
||||
should_sit: bool,
|
||||
is_local_intent: bool = false,
|
||||
) -> void:
|
||||
if _sitting == should_sit:
|
||||
return
|
||||
_sitting = should_sit
|
||||
if is_local_intent:
|
||||
_sitting_intent_pending = true
|
||||
_sitting_intent_sequence = -1
|
||||
if _sitting:
|
||||
velocity = Vector3.ZERO
|
||||
_character_animation_name = &""
|
||||
|
|
@ -548,6 +595,10 @@ func is_sitting() -> bool:
|
|||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not local_control_enabled or not _camera_input_enabled:
|
||||
return
|
||||
if event.is_action_pressed("toggle_free_camera"):
|
||||
_set_free_camera_active(not _free_camera_active)
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
|
||||
if event.is_action("camera_drag"):
|
||||
_camera_dragging = event.is_pressed()
|
||||
|
|
@ -555,9 +606,14 @@ func _unhandled_input(event: InputEvent) -> void:
|
|||
return
|
||||
|
||||
if event is InputEventMouseMotion and _camera_dragging:
|
||||
if _free_camera_active:
|
||||
_rotate_free_camera(event.relative * mouse_sensitivity)
|
||||
else:
|
||||
_rotate_camera(event.relative * mouse_sensitivity)
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
if _free_camera_active:
|
||||
return
|
||||
|
||||
var mouse_zoom_in: bool = (
|
||||
event is InputEventMouseButton
|
||||
|
|
@ -617,6 +673,98 @@ func _rotate_camera(delta_rotation: Vector2) -> void:
|
|||
)
|
||||
|
||||
|
||||
func _set_free_camera_active(active: bool) -> void:
|
||||
if _free_camera_active == active:
|
||||
return
|
||||
if active:
|
||||
var camera_transform: Transform3D = _camera.global_transform
|
||||
var duplicated_camera := _camera.duplicate() as Camera3D
|
||||
if duplicated_camera == null:
|
||||
return
|
||||
var camera_body := CharacterBody3D.new()
|
||||
camera_body.name = "FreeCameraBody"
|
||||
camera_body.collision_layer = 0
|
||||
camera_body.collision_mask = collision_mask
|
||||
camera_body.motion_mode = CharacterBody3D.MOTION_MODE_FLOATING
|
||||
add_child(camera_body)
|
||||
camera_body.top_level = true
|
||||
camera_body.global_position = camera_transform.origin
|
||||
var camera_collision := CollisionShape3D.new()
|
||||
camera_collision.name = "FreeCameraCollision"
|
||||
camera_collision.shape = _player_collision_shape.shape
|
||||
camera_body.add_child(camera_collision)
|
||||
duplicated_camera.name = "FreeCamera"
|
||||
duplicated_camera.unique_name_in_owner = false
|
||||
camera_body.add_child(duplicated_camera)
|
||||
duplicated_camera.transform = Transform3D(
|
||||
camera_transform.basis,
|
||||
Vector3.ZERO,
|
||||
)
|
||||
_free_camera_body = camera_body
|
||||
_free_camera = duplicated_camera
|
||||
var camera_rotation: Vector3 = _free_camera.global_rotation
|
||||
_free_camera_yaw = camera_rotation.y
|
||||
_free_camera_pitch = camera_rotation.x
|
||||
_camera.current = false
|
||||
_free_camera.current = true
|
||||
_free_camera_active = true
|
||||
return
|
||||
_free_camera_active = false
|
||||
_camera_dragging = false
|
||||
if _free_camera != null:
|
||||
_free_camera.current = false
|
||||
_free_camera = null
|
||||
if _free_camera_body != null:
|
||||
_free_camera_body.queue_free()
|
||||
_free_camera_body = null
|
||||
_camera.current = local_control_enabled
|
||||
|
||||
|
||||
func _update_free_camera_physics() -> void:
|
||||
if _free_camera == null or _free_camera_body == null:
|
||||
_set_free_camera_active(false)
|
||||
return
|
||||
var input_vector: Vector2 = Input.get_vector(
|
||||
"move_left",
|
||||
"move_right",
|
||||
"move_forward",
|
||||
"move_backward",
|
||||
)
|
||||
var vertical_input: float = (
|
||||
Input.get_action_strength("jump")
|
||||
- Input.get_action_strength("sneak")
|
||||
)
|
||||
var movement: Vector3 = (
|
||||
_free_camera.global_basis.x * input_vector.x
|
||||
+ _free_camera.global_basis.z * input_vector.y
|
||||
+ Vector3.UP * vertical_input
|
||||
)
|
||||
if movement.length_squared() > 1.0:
|
||||
movement = movement.normalized()
|
||||
var movement_speed: float = free_camera_speed
|
||||
if Input.is_action_pressed("sprint"):
|
||||
movement_speed *= free_camera_sprint_multiplier
|
||||
_free_camera_body.velocity = movement * movement_speed
|
||||
_free_camera_body.move_and_slide()
|
||||
|
||||
|
||||
func _rotate_free_camera(delta_rotation: Vector2) -> void:
|
||||
if _free_camera == null:
|
||||
return
|
||||
_free_camera_yaw -= delta_rotation.x
|
||||
var vertical_direction: float = -1.0 if invert_camera_y else 1.0
|
||||
_free_camera_pitch = clampf(
|
||||
_free_camera_pitch - delta_rotation.y * vertical_direction,
|
||||
deg_to_rad(minimum_pitch_degrees),
|
||||
deg_to_rad(maximum_pitch_degrees),
|
||||
)
|
||||
_free_camera.global_rotation = Vector3(
|
||||
_free_camera_pitch,
|
||||
_free_camera_yaw,
|
||||
0.0,
|
||||
)
|
||||
|
||||
|
||||
func _set_target_zoom(value: float) -> void:
|
||||
_target_zoom = clampf(value, minimum_zoom, maximum_zoom)
|
||||
|
||||
|
|
@ -633,6 +781,8 @@ func _apply_axis_deadzone(value: float) -> float:
|
|||
|
||||
|
||||
func set_local_control(enabled: bool) -> void:
|
||||
if not enabled and _free_camera_active:
|
||||
_set_free_camera_active(false)
|
||||
local_control_enabled = enabled
|
||||
if is_node_ready():
|
||||
_camera.current = enabled
|
||||
|
|
@ -657,7 +807,9 @@ func configure_network_remote(authoritative_simulation: bool) -> void:
|
|||
|
||||
|
||||
func capture_network_input(sequence: int) -> Dictionary:
|
||||
if not _movement_enabled or _water_recovery_active:
|
||||
if _sitting_intent_pending and _sitting_intent_sequence < 0:
|
||||
_sitting_intent_sequence = sequence
|
||||
if not _movement_enabled or _water_recovery_active or _free_camera_active:
|
||||
return {
|
||||
"sequence": sequence,
|
||||
"axis": [0.0, 0.0],
|
||||
|
|
@ -734,6 +886,16 @@ func apply_local_prediction_correction(snapshot: Dictionary) -> void:
|
|||
var parsed: Dictionary = _parse_network_snapshot(snapshot)
|
||||
if parsed.is_empty():
|
||||
return
|
||||
var acknowledged_input: int = parsed["acknowledged_input"]
|
||||
var sitting_intent_acknowledged: bool = (
|
||||
_sitting_intent_pending
|
||||
and _sitting_intent_sequence >= 0
|
||||
and acknowledged_input >= _sitting_intent_sequence
|
||||
)
|
||||
if sitting_intent_acknowledged:
|
||||
_sitting_intent_pending = false
|
||||
_sitting_intent_sequence = -1
|
||||
if not _sitting_intent_pending:
|
||||
_set_sitting(bool(parsed["sitting"]))
|
||||
var authoritative_position: Vector3 = parsed["position"]
|
||||
var error_distance: float = global_position.distance_to(
|
||||
|
|
@ -780,6 +942,17 @@ func _parse_network_snapshot(snapshot: Dictionary) -> Dictionary:
|
|||
float(network_velocity[2])
|
||||
)
|
||||
var visual_yaw: float = float(snapshot.get("visual_yaw", 0.0))
|
||||
if (
|
||||
snapshot.has("acknowledged_input")
|
||||
and (
|
||||
typeof(snapshot.get("acknowledged_input")) != TYPE_INT
|
||||
or int(snapshot.get("acknowledged_input")) < 0
|
||||
)
|
||||
):
|
||||
return {}
|
||||
var acknowledged_input: int = int(
|
||||
snapshot.get("acknowledged_input", 0)
|
||||
)
|
||||
if snapshot.has("sitting") and typeof(snapshot.get("sitting")) != TYPE_BOOL:
|
||||
return {}
|
||||
var sitting: bool = bool(snapshot.get("sitting", false))
|
||||
|
|
@ -793,6 +966,7 @@ func _parse_network_snapshot(snapshot: Dictionary) -> Dictionary:
|
|||
"position": parsed_position,
|
||||
"velocity": parsed_velocity,
|
||||
"visual_yaw": visual_yaw,
|
||||
"acknowledged_input": acknowledged_input,
|
||||
"sitting": sitting,
|
||||
}
|
||||
|
||||
|
|
@ -835,6 +1009,9 @@ func set_camera_input_enabled(enabled: bool) -> void:
|
|||
|
||||
|
||||
func set_camera_active(active: bool) -> void:
|
||||
if _free_camera_active and _free_camera != null:
|
||||
_free_camera.current = active
|
||||
else:
|
||||
_camera.current = active
|
||||
|
||||
|
||||
|
|
|
|||
71
scripts/generate_placeholder_animalese.gd
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
extends SceneTree
|
||||
|
||||
const OUTPUT_DIRECTORY := "res://sound/dialogue/animalese/placeholder"
|
||||
const SAMPLE_RATE: int = 22050
|
||||
const SAMPLE_SECONDS: float = 0.055
|
||||
const CHARACTERS := "abcdefghijklmnopqrstuvwxyz"
|
||||
const VOWELS := "aeiou"
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
var absolute_directory := ProjectSettings.globalize_path(OUTPUT_DIRECTORY)
|
||||
var directory_error: Error = DirAccess.make_dir_recursive_absolute(
|
||||
absolute_directory
|
||||
)
|
||||
if directory_error != OK:
|
||||
push_error("Could not create animalese sample directory.")
|
||||
quit(1)
|
||||
return
|
||||
for character_index: int in range(CHARACTERS.length()):
|
||||
var character := CHARACTERS.substr(character_index, 1)
|
||||
_save_sample(character, character_index)
|
||||
_save_sample("fallback", CHARACTERS.length())
|
||||
quit()
|
||||
|
||||
|
||||
func _save_sample(sample_name: String, sample_index: int) -> void:
|
||||
var stream := _build_sample(sample_name, sample_index)
|
||||
var output_path := "%s/%s" % [OUTPUT_DIRECTORY, sample_name]
|
||||
var save_error: Error = stream.save_to_wav(output_path)
|
||||
if save_error != OK:
|
||||
push_error("Could not save animalese sample: %s" % sample_name)
|
||||
|
||||
|
||||
func _build_sample(sample_name: String, sample_index: int) -> AudioStreamWAV:
|
||||
var frame_count := roundi(SAMPLE_RATE * SAMPLE_SECONDS)
|
||||
var pcm := PackedByteArray()
|
||||
pcm.resize(frame_count * 2)
|
||||
var base_frequency := 245.0 + float(sample_index % 7) * 18.0
|
||||
var formant_one := 620.0 + float(sample_index % 5) * 85.0
|
||||
var formant_two := 1320.0 + float(sample_index % 6) * 115.0
|
||||
var is_vowel := VOWELS.contains(sample_name)
|
||||
var noise_seed := sample_index * 7919 + 104729
|
||||
for frame_index: int in range(frame_count):
|
||||
var time := float(frame_index) / SAMPLE_RATE
|
||||
var attack := minf(time / 0.004, 1.0)
|
||||
var release := minf((SAMPLE_SECONDS - time) / 0.014, 1.0)
|
||||
var envelope := maxf(minf(attack, release), 0.0)
|
||||
noise_seed = int(
|
||||
(noise_seed * 1103515245 + 12345) & 0x7fffffff
|
||||
)
|
||||
var noise := float(noise_seed % 65536) / 32767.5 - 1.0
|
||||
var voiced := (
|
||||
sin(TAU * base_frequency * time) * 0.42
|
||||
+ sin(TAU * base_frequency * 2.0 * time) * 0.16
|
||||
)
|
||||
var formants := (
|
||||
sin(TAU * formant_one * time) * 0.18
|
||||
+ sin(TAU * formant_two * time) * 0.10
|
||||
)
|
||||
var consonant_noise := noise * (0.08 if is_vowel else 0.24)
|
||||
var value := envelope * (voiced + formants + consonant_noise) * 0.72
|
||||
var signed_sample := clampi(roundi(value * 32767.0), -32768, 32767)
|
||||
var encoded_sample := signed_sample if signed_sample >= 0 else signed_sample + 65536
|
||||
pcm[frame_index * 2] = encoded_sample & 0xff
|
||||
pcm[frame_index * 2 + 1] = (encoded_sample >> 8) & 0xff
|
||||
var stream := AudioStreamWAV.new()
|
||||
stream.set("format", AudioStreamWAV.FORMAT_16_BITS)
|
||||
stream.mix_rate = SAMPLE_RATE
|
||||
stream.stereo = false
|
||||
stream.data = pcm
|
||||
return stream
|
||||
1
scripts/generate_placeholder_animalese.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://cwqm75icgcr4u
|
||||
BIN
sound/dialogue/animalese/placeholder/a.wav
Normal file
24
sound/dialogue/animalese/placeholder/a.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dvajjy4bwadio"
|
||||
path="res://.godot/imported/a.wav-9ab4b1a9a555e6fcf07951f399769b30.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/a.wav"
|
||||
dest_files=["res://.godot/imported/a.wav-9ab4b1a9a555e6fcf07951f399769b30.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/b.wav
Normal file
24
sound/dialogue/animalese/placeholder/b.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cs30tdyuo6wtc"
|
||||
path="res://.godot/imported/b.wav-eed860af2033bda258bd172899061b45.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/b.wav"
|
||||
dest_files=["res://.godot/imported/b.wav-eed860af2033bda258bd172899061b45.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/c.wav
Normal file
24
sound/dialogue/animalese/placeholder/c.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://2inox7x31xam"
|
||||
path="res://.godot/imported/c.wav-61dc49533634805d70c71d509b63e37b.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/c.wav"
|
||||
dest_files=["res://.godot/imported/c.wav-61dc49533634805d70c71d509b63e37b.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/d.wav
Normal file
24
sound/dialogue/animalese/placeholder/d.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://yvha8eukw6l7"
|
||||
path="res://.godot/imported/d.wav-910bc02bc42bdb1b37561959a317c28a.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/d.wav"
|
||||
dest_files=["res://.godot/imported/d.wav-910bc02bc42bdb1b37561959a317c28a.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/e.wav
Normal file
24
sound/dialogue/animalese/placeholder/e.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://8ujopf8aqs83"
|
||||
path="res://.godot/imported/e.wav-7da5f8fcd017bf931de2bd49dc00f652.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/e.wav"
|
||||
dest_files=["res://.godot/imported/e.wav-7da5f8fcd017bf931de2bd49dc00f652.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/f.wav
Normal file
24
sound/dialogue/animalese/placeholder/f.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c0gv4cphnfcxf"
|
||||
path="res://.godot/imported/f.wav-8eb31f2de6240647a0d6d2520aadcd6a.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/f.wav"
|
||||
dest_files=["res://.godot/imported/f.wav-8eb31f2de6240647a0d6d2520aadcd6a.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/fallback.wav
Normal file
24
sound/dialogue/animalese/placeholder/fallback.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bw0pod4tmexm0"
|
||||
path="res://.godot/imported/fallback.wav-7a40516b188f10028ac39bdc24fb52e5.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/fallback.wav"
|
||||
dest_files=["res://.godot/imported/fallback.wav-7a40516b188f10028ac39bdc24fb52e5.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/g.wav
Normal file
24
sound/dialogue/animalese/placeholder/g.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c7706p0fc8y7c"
|
||||
path="res://.godot/imported/g.wav-45b2cbd9653a31477e3f00c9432d560c.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/g.wav"
|
||||
dest_files=["res://.godot/imported/g.wav-45b2cbd9653a31477e3f00c9432d560c.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/h.wav
Normal file
24
sound/dialogue/animalese/placeholder/h.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cl66wka105xmo"
|
||||
path="res://.godot/imported/h.wav-2da53a6638eebb75f0867eaf75dc24ba.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/h.wav"
|
||||
dest_files=["res://.godot/imported/h.wav-2da53a6638eebb75f0867eaf75dc24ba.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/i.wav
Normal file
24
sound/dialogue/animalese/placeholder/i.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://jicgdbnyt6bm"
|
||||
path="res://.godot/imported/i.wav-1e8d7f13980a6f2f61d73f65a2efc91c.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/i.wav"
|
||||
dest_files=["res://.godot/imported/i.wav-1e8d7f13980a6f2f61d73f65a2efc91c.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/j.wav
Normal file
24
sound/dialogue/animalese/placeholder/j.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cji2evr0u3m6c"
|
||||
path="res://.godot/imported/j.wav-2f355374ffcea77f8dc630ee45879444.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/j.wav"
|
||||
dest_files=["res://.godot/imported/j.wav-2f355374ffcea77f8dc630ee45879444.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/k.wav
Normal file
24
sound/dialogue/animalese/placeholder/k.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://eypaqf1iaq5"
|
||||
path="res://.godot/imported/k.wav-b85d045dc022b9055c25a650b2e3af2a.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/k.wav"
|
||||
dest_files=["res://.godot/imported/k.wav-b85d045dc022b9055c25a650b2e3af2a.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/l.wav
Normal file
24
sound/dialogue/animalese/placeholder/l.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bixgnaq4idkhj"
|
||||
path="res://.godot/imported/l.wav-b21006c3b048e0c797d6baf19ab0f663.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/l.wav"
|
||||
dest_files=["res://.godot/imported/l.wav-b21006c3b048e0c797d6baf19ab0f663.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/m.wav
Normal file
24
sound/dialogue/animalese/placeholder/m.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dan4o17oreugv"
|
||||
path="res://.godot/imported/m.wav-aa394c4b1d5309d859ce73a368754264.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/m.wav"
|
||||
dest_files=["res://.godot/imported/m.wav-aa394c4b1d5309d859ce73a368754264.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/n.wav
Normal file
24
sound/dialogue/animalese/placeholder/n.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dxup6pw80km61"
|
||||
path="res://.godot/imported/n.wav-84e9a6fa6664222868d647187a09f374.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/n.wav"
|
||||
dest_files=["res://.godot/imported/n.wav-84e9a6fa6664222868d647187a09f374.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/o.wav
Normal file
24
sound/dialogue/animalese/placeholder/o.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://lntkug4avr2k"
|
||||
path="res://.godot/imported/o.wav-6c18faa9701875d7753d91afcd1b09e6.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/o.wav"
|
||||
dest_files=["res://.godot/imported/o.wav-6c18faa9701875d7753d91afcd1b09e6.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/p.wav
Normal file
24
sound/dialogue/animalese/placeholder/p.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://crubsdrd220eh"
|
||||
path="res://.godot/imported/p.wav-c32b759c822f258d8d947827adf8127a.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/p.wav"
|
||||
dest_files=["res://.godot/imported/p.wav-c32b759c822f258d8d947827adf8127a.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/q.wav
Normal file
24
sound/dialogue/animalese/placeholder/q.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://ct0decr76agoq"
|
||||
path="res://.godot/imported/q.wav-d494b927c6f2b8bfbaa44d1f81887731.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/q.wav"
|
||||
dest_files=["res://.godot/imported/q.wav-d494b927c6f2b8bfbaa44d1f81887731.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/r.wav
Normal file
24
sound/dialogue/animalese/placeholder/r.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dpq7rin4pr1n3"
|
||||
path="res://.godot/imported/r.wav-d1d419e3246c0e918ff51a9dd662a742.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/r.wav"
|
||||
dest_files=["res://.godot/imported/r.wav-d1d419e3246c0e918ff51a9dd662a742.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/s.wav
Normal file
24
sound/dialogue/animalese/placeholder/s.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c00meumj2blfa"
|
||||
path="res://.godot/imported/s.wav-15abb20075aacc8d5fe95cd206ae25ce.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/s.wav"
|
||||
dest_files=["res://.godot/imported/s.wav-15abb20075aacc8d5fe95cd206ae25ce.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/t.wav
Normal file
24
sound/dialogue/animalese/placeholder/t.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dr0dp5v8fdb8r"
|
||||
path="res://.godot/imported/t.wav-3a26c5be0f8e3007adf1daa05a6a1ea2.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/t.wav"
|
||||
dest_files=["res://.godot/imported/t.wav-3a26c5be0f8e3007adf1daa05a6a1ea2.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/u.wav
Normal file
24
sound/dialogue/animalese/placeholder/u.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bln1bkdu20muo"
|
||||
path="res://.godot/imported/u.wav-06e44c423f3d1cd6cdd34b54270211bb.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/u.wav"
|
||||
dest_files=["res://.godot/imported/u.wav-06e44c423f3d1cd6cdd34b54270211bb.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/v.wav
Normal file
24
sound/dialogue/animalese/placeholder/v.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://y3g1s3pw3bn0"
|
||||
path="res://.godot/imported/v.wav-5a9986e91dbdd0da4f0583b35a986b1c.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/v.wav"
|
||||
dest_files=["res://.godot/imported/v.wav-5a9986e91dbdd0da4f0583b35a986b1c.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/w.wav
Normal file
24
sound/dialogue/animalese/placeholder/w.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://5ml2iuf8cpgt"
|
||||
path="res://.godot/imported/w.wav-d3e9035a1fc5e7946be782a0d4f95e64.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/w.wav"
|
||||
dest_files=["res://.godot/imported/w.wav-d3e9035a1fc5e7946be782a0d4f95e64.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/x.wav
Normal file
24
sound/dialogue/animalese/placeholder/x.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://b5al0m4de1m5x"
|
||||
path="res://.godot/imported/x.wav-b1beaddcc7d6663882ddd8b86e65db56.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/x.wav"
|
||||
dest_files=["res://.godot/imported/x.wav-b1beaddcc7d6663882ddd8b86e65db56.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/y.wav
Normal file
24
sound/dialogue/animalese/placeholder/y.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c6hust77yamoe"
|
||||
path="res://.godot/imported/y.wav-5ef178912b2921bb7c790b12e2e82337.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/y.wav"
|
||||
dest_files=["res://.godot/imported/y.wav-5ef178912b2921bb7c790b12e2e82337.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
BIN
sound/dialogue/animalese/placeholder/z.wav
Normal file
24
sound/dialogue/animalese/placeholder/z.wav.import
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://djvv63b0jlll"
|
||||
path="res://.godot/imported/z.wav-3e6ff24f53b1014b381cc80ee9fb1a84.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sound/dialogue/animalese/placeholder/z.wav"
|
||||
dest_files=["res://.godot/imported/z.wav-3e6ff24f53b1014b381cc80ee9fb1a84.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
123
ui/animalese_voice.gd
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
class_name AnimaleseVoice
|
||||
extends Node
|
||||
|
||||
const SAMPLE_DIRECTORY := "res://sound/dialogue/animalese/placeholder"
|
||||
const SUPPORTED_CHARACTERS := "abcdefghijklmnopqrstuvwxyz"
|
||||
const DEFAULT_CHARACTERS_PER_SECOND: float = 28.0
|
||||
const POLYPHONY: int = 8
|
||||
const VoiceProfilesType = preload(
|
||||
"res://player/animalese_voice_profiles.gd"
|
||||
)
|
||||
const TypewriterRevealType = preload("res://ui/typewriter_reveal.gd")
|
||||
|
||||
var base_pitch: float = 1.0
|
||||
var volume_db: float = -13.0
|
||||
|
||||
var _samples: Dictionary[String, AudioStream] = {}
|
||||
var _player: AudioStreamPlayer
|
||||
var _playback: AudioStreamPlaybackPolyphonic
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_load_samples()
|
||||
var polyphonic_stream := AudioStreamPolyphonic.new()
|
||||
polyphonic_stream.polyphony = POLYPHONY
|
||||
_player = AudioStreamPlayer.new()
|
||||
_player.name = "AnimaleseAudio"
|
||||
_player.stream = polyphonic_stream
|
||||
add_child(_player)
|
||||
_player.play()
|
||||
_playback = (
|
||||
_player.get_stream_playback() as AudioStreamPlaybackPolyphonic
|
||||
)
|
||||
|
||||
|
||||
func speak_text(
|
||||
owner: Node,
|
||||
text: String,
|
||||
voice_key: String,
|
||||
voice_profile_id: String = VoiceProfilesType.DEFAULT_ID,
|
||||
characters_per_second: float = -1.0,
|
||||
) -> Tween:
|
||||
var speech_tween := owner.create_tween()
|
||||
var resolved_characters_per_second := (
|
||||
characters_per_second
|
||||
if characters_per_second > 0.0
|
||||
else TypewriterRevealType.get_characters_per_second()
|
||||
)
|
||||
var character_seconds := 1.0 / maxf(
|
||||
resolved_characters_per_second,
|
||||
1.0,
|
||||
)
|
||||
var voice_pitch := (
|
||||
base_pitch * VoiceProfilesType.pitch_for(voice_profile_id)
|
||||
)
|
||||
for character_index: int in range(text.length()):
|
||||
speech_tween.tween_interval(character_seconds)
|
||||
speech_tween.tween_callback(
|
||||
_play_character.bind(
|
||||
text.substr(character_index, 1),
|
||||
character_index,
|
||||
text,
|
||||
voice_key,
|
||||
voice_pitch,
|
||||
)
|
||||
)
|
||||
return speech_tween
|
||||
|
||||
|
||||
func _load_samples() -> void:
|
||||
for character_index: int in range(SUPPORTED_CHARACTERS.length()):
|
||||
var character := SUPPORTED_CHARACTERS.substr(character_index, 1)
|
||||
_load_sample(character)
|
||||
_load_sample("fallback")
|
||||
|
||||
|
||||
func _load_sample(sample_name: String) -> void:
|
||||
var sample_path := "%s/%s.wav" % [SAMPLE_DIRECTORY, sample_name]
|
||||
var sample := load(sample_path) as AudioStream
|
||||
if sample != null:
|
||||
_samples[sample_name] = sample
|
||||
|
||||
|
||||
func _play_character(
|
||||
character: String,
|
||||
character_index: int,
|
||||
full_text: String,
|
||||
voice_key: String,
|
||||
voice_pitch: float,
|
||||
) -> void:
|
||||
if _playback == null or character.strip_edges().is_empty():
|
||||
return
|
||||
var normalized := character.to_lower()
|
||||
if normalized in [".", ",", "!", "?", ":", ";", "-", "_"]:
|
||||
return
|
||||
var sample_name := (
|
||||
normalized if SUPPORTED_CHARACTERS.contains(normalized) else "fallback"
|
||||
)
|
||||
var sample: AudioStream = _samples.get(sample_name)
|
||||
if sample == null:
|
||||
return
|
||||
var speaker_variation := (
|
||||
float(posmod(hash(voice_key), 1001)) / 1000.0 - 0.5
|
||||
) * 0.16
|
||||
var character_variation := (
|
||||
float(posmod(hash("%s:%d" % [voice_key, character_index]), 1001))
|
||||
/ 1000.0
|
||||
- 0.5
|
||||
) * 0.10
|
||||
var question_lift := 0.0
|
||||
if full_text.ends_with("?") and character_index >= full_text.length() * 3 / 4:
|
||||
var final_progress := (
|
||||
float(character_index) / maxf(float(full_text.length() - 1), 1.0)
|
||||
)
|
||||
question_lift = lerpf(0.0, 0.14, final_progress)
|
||||
var pitch := clampf(
|
||||
voice_pitch
|
||||
+ speaker_variation
|
||||
+ character_variation
|
||||
+ question_lift,
|
||||
0.72,
|
||||
1.45,
|
||||
)
|
||||
_playback.play_stream(sample, 0.0, volume_db, pitch)
|
||||
1
ui/animalese_voice.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://djst00wf8yntj
|
||||
BIN
ui/assets/logbook/ui_logbook.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
40
ui/assets/logbook/ui_logbook.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bnwbcopsjmi3s"
|
||||
path="res://.godot/imported/ui_logbook.png-e45558834671114c04857bb4a6091575.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/assets/logbook/ui_logbook.png"
|
||||
dest_files=["res://.godot/imported/ui_logbook.png-e45558834671114c04857bb4a6091575.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
167
ui/chat_ui.gd
|
|
@ -6,6 +6,7 @@ const RECENT_SECONDS: float = 8.0
|
|||
const SPEECH_SECONDS: float = 6.0
|
||||
const DRAFT_SAVE_DELAY: float = 0.4
|
||||
const IDLE_ALPHA: float = 0.58
|
||||
const CHAT_SURFACE_COLOR := Color(0.025, 0.13, 0.19, 0.94)
|
||||
const ORIGINAL_PANEL_WIDTH: float = 390.0
|
||||
const PANEL_WIDTH: float = ORIGINAL_PANEL_WIDTH * 0.85
|
||||
const COMPACT_HEIGHT: float = 250.0
|
||||
|
|
@ -33,12 +34,31 @@ const CLOCK_SIZE := Vector2(116.0, 34.0)
|
|||
const CLOCK_EDGE_MARGIN: float = 10.0
|
||||
const WEATHER_ICON_SIZE := Vector2(34.0, 34.0)
|
||||
const WEATHER_ICON_GAP: float = 6.0
|
||||
const CHAT_SHOW_ICON: Texture2D = preload(
|
||||
"res://ui/icons/pictograms/arrow_light_right_more.png"
|
||||
)
|
||||
const CHAT_HIDE_ICON: Texture2D = preload(
|
||||
"res://ui/icons/pictograms/arrow_light_left_more.png"
|
||||
)
|
||||
const CHAT_EXPAND_ICON: Texture2D = preload(
|
||||
"res://ui/icons/pictograms/arrow_light_up_more.png"
|
||||
)
|
||||
const CHAT_COMPACT_ICON: Texture2D = preload(
|
||||
"res://ui/icons/pictograms/arrow_light_down_more.png"
|
||||
)
|
||||
const WorldTimeServiceType = preload("res://world/world_time_service.gd")
|
||||
const WorldWeatherServiceType = preload(
|
||||
"res://world/world_weather_service.gd"
|
||||
)
|
||||
const WeatherIconType = preload("res://ui/weather_icon.gd")
|
||||
|
||||
const TypewriterRevealType = preload("res://ui/typewriter_reveal.gd")
|
||||
const AnimaleseVoiceType = preload("res://ui/animalese_voice.gd")
|
||||
const VoiceProfilesType = preload(
|
||||
"res://player/animalese_voice_profiles.gd"
|
||||
)
|
||||
|
||||
|
||||
enum PresentationState {
|
||||
COLLAPSED,
|
||||
COMPACT,
|
||||
|
|
@ -62,6 +82,7 @@ var _height_button: Button
|
|||
var _unread_indicator: Label
|
||||
var _hint: Label
|
||||
var _speech_layer: Control
|
||||
var _animalese_voice: AnimaleseVoiceType
|
||||
var _clock_panel: PanelContainer
|
||||
var _clock_label: Label
|
||||
var _weather_icon: WeatherIconType
|
||||
|
|
@ -379,6 +400,15 @@ func _build_ui() -> void:
|
|||
_collapse_button.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_collapse_button.focus_mode = Control.FOCUS_ALL
|
||||
_collapse_button.z_index = 3
|
||||
_collapse_button.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
_collapse_button.expand_icon = true
|
||||
_collapse_button.alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_collapse_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_collapse_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_collapse_button.add_theme_constant_override(
|
||||
"icon_max_width",
|
||||
roundi(minf(HANDLE_SIZE.x, HANDLE_SIZE.y) * 0.5),
|
||||
)
|
||||
_collapse_button.tooltip_text = "Collapse chat"
|
||||
_collapse_button.pressed.connect(func() -> void:
|
||||
if _presentation_state == PresentationState.COLLAPSED:
|
||||
|
|
@ -405,6 +435,15 @@ func _build_ui() -> void:
|
|||
_height_button.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
_height_button.focus_mode = Control.FOCUS_ALL
|
||||
_height_button.z_index = 3
|
||||
_height_button.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
_height_button.expand_icon = true
|
||||
_height_button.alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_height_button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_height_button.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_height_button.add_theme_constant_override(
|
||||
"icon_max_width",
|
||||
roundi(minf(HANDLE_SIZE.x, HANDLE_SIZE.y) * 0.5),
|
||||
)
|
||||
_height_button.pressed.connect(func() -> void:
|
||||
if _presentation_state == PresentationState.COLLAPSED:
|
||||
_visible_state_before_collapse = (
|
||||
|
|
@ -461,6 +500,9 @@ func _build_ui() -> void:
|
|||
_speech_layer.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_speech_layer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
add_child(_speech_layer)
|
||||
_animalese_voice = AnimaleseVoiceType.new()
|
||||
_animalese_voice.name = "PlayerAnimaleseVoice"
|
||||
add_child(_animalese_voice)
|
||||
_draft_save_timer = Timer.new()
|
||||
_draft_save_timer.one_shot = true
|
||||
_draft_save_timer.wait_time = DRAFT_SAVE_DELAY
|
||||
|
|
@ -478,7 +520,7 @@ func _build_ui() -> void:
|
|||
|
||||
|
||||
func _chat_panel_style() -> StyleBoxFlat:
|
||||
var style := _borderless_style(Color(0.025, 0.13, 0.19, 0.94))
|
||||
var style := _borderless_style(CHAT_SURFACE_COLOR)
|
||||
if _mobile_mode:
|
||||
style.corner_radius_top_left = 0
|
||||
style.corner_radius_top_right = 0
|
||||
|
|
@ -509,7 +551,7 @@ func _refresh_input_ownership() -> void:
|
|||
|
||||
|
||||
func _clock_panel_style() -> StyleBoxFlat:
|
||||
var style := _borderless_style(Color(0.025, 0.13, 0.19, 0.94))
|
||||
var style := _borderless_style(CHAT_SURFACE_COLOR)
|
||||
style.set_corner_radius_all(12)
|
||||
style.content_margin_left = 10
|
||||
style.content_margin_right = 10
|
||||
|
|
@ -522,6 +564,10 @@ func _borderless_style(color: Color) -> StyleBoxFlat:
|
|||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = color
|
||||
style.set_border_width_all(0)
|
||||
style.anti_aliasing = false
|
||||
style.shadow_size = 0
|
||||
style.shadow_color = Color.TRANSPARENT
|
||||
style.shadow_offset = Vector2.ZERO
|
||||
return style
|
||||
|
||||
|
||||
|
|
@ -530,6 +576,12 @@ func _flat_chat_button_style(color: Color) -> StyleBoxFlat:
|
|||
style.bg_color = color
|
||||
style.set_border_width_all(0)
|
||||
style.set_corner_radius_all(0)
|
||||
if _dock_right:
|
||||
style.corner_radius_top_left = 10
|
||||
style.corner_radius_bottom_left = 10
|
||||
else:
|
||||
style.corner_radius_top_right = 10
|
||||
style.corner_radius_bottom_right = 10
|
||||
style.anti_aliasing = false
|
||||
style.shadow_size = 0
|
||||
style.shadow_color = Color.TRANSPARENT
|
||||
|
|
@ -572,6 +624,18 @@ func _apply_flat_chat_button(button: Button) -> void:
|
|||
button.add_theme_stylebox_override(
|
||||
"disabled", _flat_chat_button_style(UtilityPageStyle.OCEAN_DISABLED)
|
||||
)
|
||||
for state: StringName in [
|
||||
&"normal",
|
||||
&"hover",
|
||||
&"pressed",
|
||||
&"hover_pressed",
|
||||
&"focus",
|
||||
&"disabled",
|
||||
]:
|
||||
button.add_theme_stylebox_override(
|
||||
state,
|
||||
_flat_chat_button_style(CHAT_SURFACE_COLOR),
|
||||
)
|
||||
|
||||
|
||||
func _speech_panel_style() -> StyleBoxFlat:
|
||||
|
|
@ -605,6 +669,8 @@ func _send() -> void:
|
|||
if _send_pending:
|
||||
return
|
||||
var body := _entry.text
|
||||
if _handle_chat_command(body):
|
||||
return
|
||||
_send_pending = true
|
||||
_pending_send_body = NetworkChatProtocol.sanitize_body(body)
|
||||
_entry.editable = false
|
||||
|
|
@ -616,6 +682,59 @@ func _send() -> void:
|
|||
_set_status("Sending…")
|
||||
|
||||
|
||||
func _handle_chat_command(body: String) -> bool:
|
||||
var command_text := body.strip_edges()
|
||||
if not command_text.begins_with("/"):
|
||||
return false
|
||||
var parts: PackedStringArray = command_text.split(" ", false)
|
||||
var command := String(parts[0]).trim_prefix("/").to_lower()
|
||||
match command:
|
||||
"time":
|
||||
_handle_time_command(parts)
|
||||
"":
|
||||
_set_status("Enter a command after /.")
|
||||
_:
|
||||
_set_status("Unknown command: /%s" % command)
|
||||
_entry.clear()
|
||||
_flush_draft()
|
||||
return true
|
||||
|
||||
|
||||
func _handle_time_command(parts: PackedStringArray) -> void:
|
||||
if parts.size() != 2:
|
||||
_set_status("Usage: /time [dawn, day, dusk, night]")
|
||||
return
|
||||
if _session == null or not _session.is_host():
|
||||
_set_status("Only the host can change world time.")
|
||||
return
|
||||
if _world_time == null:
|
||||
_set_status("World time is unavailable.")
|
||||
return
|
||||
var phase_name := String(parts[1]).to_lower()
|
||||
var target_hour: float
|
||||
match phase_name:
|
||||
"dawn":
|
||||
target_hour = WorldTimeServiceType.DAWN_START_HOUR
|
||||
"day":
|
||||
target_hour = WorldTimeServiceType.DAWN_END_HOUR
|
||||
"dusk":
|
||||
target_hour = WorldTimeServiceType.DUSK_START_HOUR
|
||||
"night":
|
||||
target_hour = WorldTimeServiceType.DUSK_END_HOUR
|
||||
_:
|
||||
_set_status("Usage: /time [dawn, day, dusk, night]")
|
||||
return
|
||||
if not _world_time.set_authoritative_time(target_hour):
|
||||
_set_status("World time could not be changed.")
|
||||
return
|
||||
_set_status("")
|
||||
_service.broadcast_system_message(
|
||||
"World time set to %s (%s)."
|
||||
% [phase_name, _world_time.get_clock_text()]
|
||||
)
|
||||
close_chat()
|
||||
|
||||
|
||||
func _on_local_message_confirmed(message: Dictionary) -> void:
|
||||
if (
|
||||
not _send_pending
|
||||
|
|
@ -664,10 +783,27 @@ func _on_message(message: Dictionary) -> void:
|
|||
)
|
||||
bubble.add_child(label)
|
||||
_speech_layer.add_child(bubble)
|
||||
var reveal_seconds := TypewriterRevealType.start(label)
|
||||
var voice_profile_id: String = VoiceProfilesType.DEFAULT_ID
|
||||
var speaker_avatar := _spawn.get_avatar(peer_id)
|
||||
if speaker_avatar != null:
|
||||
voice_profile_id = VoiceProfilesType.sanitized_id(
|
||||
speaker_avatar.get_animalese_voice_id()
|
||||
)
|
||||
_animalese_voice.speak_text(
|
||||
label,
|
||||
label.text,
|
||||
str(peer_id),
|
||||
voice_profile_id,
|
||||
)
|
||||
_speech[peer_id] = {
|
||||
"bubble": bubble,
|
||||
"pointer": pointer,
|
||||
"expires": Time.get_ticks_msec() / 1000.0 + SPEECH_SECONDS,
|
||||
"expires": (
|
||||
Time.get_ticks_msec() / 1000.0
|
||||
+ reveal_seconds
|
||||
+ SPEECH_SECONDS
|
||||
),
|
||||
"fingerprint": str(message.get("sender_fingerprint", "")),
|
||||
}
|
||||
|
||||
|
|
@ -770,6 +906,8 @@ func set_dock_right(should_dock_right: bool) -> void:
|
|||
if not is_node_ready() or _panel == null:
|
||||
return
|
||||
_panel.add_theme_stylebox_override("panel", _chat_panel_style())
|
||||
_apply_flat_chat_button(_collapse_button)
|
||||
_apply_flat_chat_button(_height_button)
|
||||
_refresh_handle_labels(_presentation_state)
|
||||
_layout_presentation(false)
|
||||
|
||||
|
|
@ -800,21 +938,24 @@ func is_mobile_mode() -> bool:
|
|||
func _refresh_handle_labels(state: PresentationState) -> void:
|
||||
var collapsed := state == PresentationState.COLLAPSED
|
||||
var height_state := _visible_state_before_collapse if collapsed else state
|
||||
if _mobile_mode:
|
||||
_collapse_button.text = "v" if collapsed else "^"
|
||||
elif _dock_right:
|
||||
_collapse_button.text = "<" if collapsed else ">"
|
||||
else:
|
||||
_collapse_button.text = ">" if collapsed else "<"
|
||||
_collapse_button.text = ""
|
||||
_collapse_button.icon = CHAT_SHOW_ICON if collapsed else CHAT_HIDE_ICON
|
||||
_collapse_button.tooltip_text = (
|
||||
"Show chat" if collapsed else "Hide chat"
|
||||
)
|
||||
_height_button.text = "v" if height_state == PresentationState.EXPANDED else "^"
|
||||
_collapse_button.accessibility_name = _collapse_button.tooltip_text
|
||||
_height_button.text = ""
|
||||
_height_button.icon = (
|
||||
CHAT_COMPACT_ICON
|
||||
if height_state == PresentationState.EXPANDED
|
||||
else CHAT_EXPAND_ICON
|
||||
)
|
||||
_height_button.tooltip_text = (
|
||||
"Compact chat"
|
||||
if height_state == PresentationState.EXPANDED
|
||||
else "Expand chat history"
|
||||
)
|
||||
_height_button.accessibility_name = _height_button.tooltip_text
|
||||
|
||||
|
||||
func _update_panel_opacity(immediate_recheck: bool = false) -> void:
|
||||
|
|
@ -823,10 +964,8 @@ func _update_panel_opacity(immediate_recheck: bool = false) -> void:
|
|||
if _presentation_state == PresentationState.COLLAPSED:
|
||||
if _height_tween == null or not _height_tween.is_running():
|
||||
_panel.modulate.a = IDLE_ALPHA
|
||||
_collapse_button.modulate.a = (
|
||||
1.0 if _collapsed_has_unread else 0.82
|
||||
)
|
||||
_height_button.modulate.a = 0.82
|
||||
_collapse_button.modulate.a = IDLE_ALPHA
|
||||
_height_button.modulate.a = IDLE_ALPHA
|
||||
return
|
||||
var recent := (
|
||||
Time.get_ticks_msec() / 1000.0 - _last_message_time < RECENT_SECONDS
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
class_name BubbleButton
|
||||
extends Button
|
||||
|
||||
const ICON_FILL_RATIO: float = 0.76
|
||||
|
||||
@export var profile: BubbleMenuProfile
|
||||
|
||||
@export_group("Authored Layout")
|
||||
|
|
@ -37,6 +39,7 @@ func _ready() -> void:
|
|||
resized.connect(_update_pivot)
|
||||
_update_pivot()
|
||||
apply_profile()
|
||||
_apply_icon_presentation(neutral_size)
|
||||
|
||||
|
||||
func apply_layout(
|
||||
|
|
@ -49,6 +52,7 @@ func apply_layout(
|
|||
neutral_position = position
|
||||
presented_size = bubble_size
|
||||
_update_pivot()
|
||||
_apply_icon_presentation(bubble_size)
|
||||
var label_control: Control = get_label_control()
|
||||
var font_size := clampi(
|
||||
roundi(minf(bubble_size.x, bubble_size.y) * font_size_ratio),
|
||||
|
|
@ -63,6 +67,9 @@ func get_layout_size(layout_scale: float, compact: bool) -> Vector2:
|
|||
if compact:
|
||||
bubble_size.x = maxf(bubble_size.x, compact_minimum_size.x)
|
||||
bubble_size.y = maxf(bubble_size.y, compact_minimum_size.y)
|
||||
if _uses_icon_only_presentation():
|
||||
var diameter: float = maxf(bubble_size.x, bubble_size.y)
|
||||
bubble_size = Vector2(diameter, diameter)
|
||||
return bubble_size
|
||||
|
||||
|
||||
|
|
@ -78,6 +85,24 @@ func get_label_control() -> Control:
|
|||
return self
|
||||
|
||||
|
||||
func _uses_icon_only_presentation() -> bool:
|
||||
return icon != null and text.is_empty() and label_control_path.is_empty()
|
||||
|
||||
|
||||
func _apply_icon_presentation(bubble_size: Vector2) -> void:
|
||||
if not _uses_icon_only_presentation():
|
||||
return
|
||||
alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
expand_icon = true
|
||||
texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
add_theme_constant_override(
|
||||
"icon_max_width",
|
||||
maxi(1, roundi(minf(bubble_size.x, bubble_size.y) * ICON_FILL_RATIO)),
|
||||
)
|
||||
|
||||
|
||||
func advance_emphasis(delta: float) -> void:
|
||||
var target: float = 1.0 if _hovered or _focused else 0.0
|
||||
emphasis = move_toward(
|
||||
|
|
@ -122,6 +147,8 @@ func calculate_visual_scale(
|
|||
* motion_scale
|
||||
* lerpf(1.0, profile.emphasized_deformation_scale, emphasis)
|
||||
)
|
||||
if _uses_icon_only_presentation():
|
||||
deformation_amount = 0.0
|
||||
var hover_scale: float = lerpf(
|
||||
1.0,
|
||||
profile.hover_focus_scale,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
[ext_resource type="Texture2D" path="res://items/icons/placeholder/reel_speed_upgrade.svg" id="3_reel"]
|
||||
[ext_resource type="Texture2D" path="res://items/icons/placeholder/barrier_power_upgrade.svg" id="4_barrier"]
|
||||
[ext_resource type="Texture2D" path="res://items/icons/placeholder/fish_coin.svg" id="5_coin"]
|
||||
[ext_resource type="Texture2D" path="res://items/icons/placeholder/cooler_expansion.svg" id="6_cooler"]
|
||||
[ext_resource type="Texture2D" path="res://items/icons/equipment/64_cooler_plus.png" id="6_cooler"]
|
||||
|
||||
[node name="FishingShop" type="Control"]
|
||||
unique_name_in_owner = true
|
||||
|
|
@ -196,7 +196,7 @@ layout_mode = 2
|
|||
theme_override_constants/separation = 9
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="ShopPanel/Margin/Layout/Body/Upgrades/ReelCard/Margin/Row"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
texture = ExtResource("3_reel")
|
||||
expand_mode = 1
|
||||
|
|
@ -250,7 +250,7 @@ layout_mode = 2
|
|||
theme_override_constants/separation = 9
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="ShopPanel/Margin/Layout/Body/Upgrades/BarrierCard/Margin/Row"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
texture = ExtResource("4_barrier")
|
||||
expand_mode = 1
|
||||
|
|
@ -304,7 +304,7 @@ layout_mode = 2
|
|||
theme_override_constants/separation = 9
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="ShopPanel/Margin/Layout/Body/Upgrades/CoolerCard/Margin/Row"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
custom_minimum_size = Vector2(88, 88)
|
||||
layout_mode = 2
|
||||
texture = ExtResource("6_cooler")
|
||||
expand_mode = 1
|
||||
|
|
|
|||
241
ui/game_ui.gd
|
|
@ -12,6 +12,7 @@ const PlayerMenuType = preload("res://ui/player_menu.gd")
|
|||
const PlayerType = preload("res://player/player.gd")
|
||||
const PlayerWalletType = preload("res://economy/player_wallet.gd")
|
||||
const ItemCatalogType = preload("res://items/item_catalog.gd")
|
||||
const ItemDataType = preload("res://items/item_data.gd")
|
||||
const PlayerBagType = preload("res://inventory/player_bag.gd")
|
||||
const PlayerHotbarType = preload("res://inventory/player_hotbar.gd")
|
||||
const HotbarUIType = preload("res://ui/hotbar.gd")
|
||||
|
|
@ -57,6 +58,12 @@ const PlayerExperienceType = preload(
|
|||
const UIReferencePresentationType = preload(
|
||||
"res://ui/ui_reference_presentation.gd"
|
||||
)
|
||||
const MAIN_BUBBLE_PROFILE: BubbleMenuProfile = preload(
|
||||
"res://ui/components/bubble_menu/bubble_menu_profile.tres"
|
||||
)
|
||||
const ACTIVE_BAIT_EMPTY_ICON: Texture2D = preload(
|
||||
"res://ui/icons/pictograms/x_dark.png"
|
||||
)
|
||||
|
||||
signal pixelation_settings_visibility_changed(is_visible: bool)
|
||||
signal crisp_reset_focus_requested
|
||||
|
|
@ -85,6 +92,9 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0
|
|||
|
||||
@onready var _status_label: Label = %StatusLabel
|
||||
@onready var _gameplay_transient_hud: Control = %GameplayTransientHUD
|
||||
@onready var _active_bait_button: Button = %ActiveBaitButton
|
||||
@onready var _active_bait_quantity_badge: Panel = %ActiveBaitQuantityBadge
|
||||
@onready var _active_bait_quantity: Label = %ActiveBaitQuantity
|
||||
@onready var _experience_presentation: Control = %ExperiencePresentation
|
||||
@onready var _catch_track: Control = %CatchTrack
|
||||
@onready var _green_catch_progress: ProgressBar = %GreenCatchProgress
|
||||
|
|
@ -101,6 +111,13 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0
|
|||
@onready var _experience_progress: ProgressBar = %ExperienceProgress
|
||||
@onready var _experience_bubble: PanelContainer = %ExperienceBubble
|
||||
@onready var _experience_bubble_label: Label = %ExperienceBubbleLabel
|
||||
const TypewriterRevealType = preload("res://ui/typewriter_reveal.gd")
|
||||
const AnimaleseVoiceType = preload("res://ui/animalese_voice.gd")
|
||||
const SHOP_ANIMALESE_VOICE_ID: String = "natural"
|
||||
const SHOP_ANIMALESE_BASE_PITCH: float = 1.08
|
||||
const SHOP_SPEECH_CHARACTERS_PER_SECOND: float = 28.0
|
||||
|
||||
|
||||
@onready var _canonical_stage: Control = %CanonicalStage
|
||||
@onready var _ui_root: Control = %UIRoot
|
||||
@onready var _player_menu: PlayerMenuType = %PlayerMenu
|
||||
|
|
@ -109,7 +126,13 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0
|
|||
@onready var _pause_menu: PauseMenuType = %PauseMenu
|
||||
@onready var _hotbar_ui: HotbarUIType = %Hotbar
|
||||
@onready var _fishing_shop: FishingShopType = %FishingShop
|
||||
@onready var _shop_prompt: PanelContainer = %ShopPrompt
|
||||
@onready var _shop_prompt: Control = %ShopPrompt
|
||||
@onready var _shop_prompt_bubble: PanelContainer = %ShopPromptBubble
|
||||
@onready var _shop_prompt_message: Label = %ShopPromptMessage
|
||||
@onready var _shop_prompt_key_badge: Panel = %ShopPromptKeyBadge
|
||||
@onready var _shop_prompt_key: Label = %ShopPromptKey
|
||||
@onready var _shop_prompt_pointer: Polygon2D = %ShopPromptPointer
|
||||
var _shop_animalese_voice: AnimaleseVoiceType
|
||||
@onready var _effect_status: Label = %EffectStatus
|
||||
@onready var _chat_ui: ChatUIType = %ChatUI
|
||||
@onready var _emote_radial_menu: EmoteRadialMenuType = %EmoteRadialMenu
|
||||
|
|
@ -129,6 +152,8 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0
|
|||
|
||||
var _showcase_active: bool = false
|
||||
var _player: PlayerType
|
||||
var _bag: PlayerBagType
|
||||
var _item_catalog: ItemCatalogType
|
||||
var _player_menu_open: bool = false
|
||||
var _gameplay_ui_enabled: bool = false
|
||||
var _fishing_spot: FishingSpotType
|
||||
|
|
@ -163,6 +188,8 @@ var _settings_manager: PlayerSettingsManagerType
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
_apply_active_bait_indicator_style()
|
||||
_refresh_active_bait_indicator()
|
||||
# Reward feedback must remain above full-screen canonical menus. Keeping the
|
||||
# overlay as the final stage child makes that ownership explicit instead of
|
||||
# relying on scene declaration order when another menu adds high-z children.
|
||||
|
|
@ -236,10 +263,27 @@ func setup(
|
|||
world_sun: DirectionalLight3D,
|
||||
) -> void:
|
||||
_player = player
|
||||
_bag = bag
|
||||
_item_catalog = item_catalog
|
||||
_settings_manager = settings_manager
|
||||
_fishing_spot = fishing_spot
|
||||
_item_effects = item_effects
|
||||
_experience = experience
|
||||
if (
|
||||
_player != null
|
||||
and not _player.active_bait_changed.is_connected(
|
||||
_on_hud_active_bait_changed
|
||||
)
|
||||
):
|
||||
_player.active_bait_changed.connect(_on_hud_active_bait_changed)
|
||||
if (
|
||||
_bag != null
|
||||
and not _bag.contents_changed.is_connected(
|
||||
_on_hud_bait_inventory_changed
|
||||
)
|
||||
):
|
||||
_bag.contents_changed.connect(_on_hud_bait_inventory_changed)
|
||||
_refresh_active_bait_indicator()
|
||||
if (
|
||||
_experience != null
|
||||
and not _experience.experience_awarded.is_connected(
|
||||
|
|
@ -1174,6 +1218,88 @@ func get_pause_menu() -> PauseMenuType:
|
|||
return _pause_menu
|
||||
|
||||
|
||||
func _apply_active_bait_indicator_style() -> void:
|
||||
var normal_style: StyleBoxFlat = MAIN_BUBBLE_PROFILE.make_normal_style()
|
||||
var hover_style: StyleBoxFlat = MAIN_BUBBLE_PROFILE.make_hover_style()
|
||||
var pressed_style: StyleBoxFlat = MAIN_BUBBLE_PROFILE.make_pressed_style()
|
||||
var disabled_style: StyleBoxFlat = MAIN_BUBBLE_PROFILE.make_disabled_style()
|
||||
for style: StyleBoxFlat in [
|
||||
normal_style,
|
||||
hover_style,
|
||||
pressed_style,
|
||||
disabled_style,
|
||||
]:
|
||||
style.set_corner_radius_all(36)
|
||||
style.content_margin_left = 13.5
|
||||
style.content_margin_top = 13.5
|
||||
style.content_margin_right = 13.5
|
||||
style.content_margin_bottom = 13.5
|
||||
_active_bait_button.add_theme_stylebox_override("normal", normal_style)
|
||||
_active_bait_button.add_theme_stylebox_override("hover", hover_style)
|
||||
_active_bait_button.add_theme_stylebox_override("focus", hover_style)
|
||||
_active_bait_button.add_theme_stylebox_override("pressed", pressed_style)
|
||||
_active_bait_button.add_theme_stylebox_override("disabled", disabled_style)
|
||||
for state: StringName in [
|
||||
&"icon_normal_color",
|
||||
&"icon_hover_color",
|
||||
&"icon_focus_color",
|
||||
&"icon_pressed_color",
|
||||
]:
|
||||
_active_bait_button.add_theme_color_override(state, Color.WHITE)
|
||||
var badge_style := StyleBoxFlat.new()
|
||||
badge_style.bg_color = Color("0b5558")
|
||||
badge_style.set_corner_radius_all(12)
|
||||
badge_style.anti_aliasing = false
|
||||
_active_bait_quantity_badge.add_theme_stylebox_override(
|
||||
"panel",
|
||||
badge_style,
|
||||
)
|
||||
|
||||
|
||||
func _refresh_active_bait_indicator() -> void:
|
||||
if not is_node_ready():
|
||||
return
|
||||
var item: ItemDataType
|
||||
if (
|
||||
_player != null
|
||||
and _item_catalog != null
|
||||
and not _player.active_bait_id.is_empty()
|
||||
):
|
||||
item = _item_catalog.get_item_by_id(_player.active_bait_id)
|
||||
var has_active_bait: bool = item != null and item.is_bait()
|
||||
_active_bait_button.icon = (
|
||||
item.icon
|
||||
if has_active_bait and item.icon != null
|
||||
else ACTIVE_BAIT_EMPTY_ICON
|
||||
)
|
||||
_active_bait_quantity_badge.visible = has_active_bait
|
||||
if not has_active_bait:
|
||||
_active_bait_button.tooltip_text = "no bait selected"
|
||||
return
|
||||
var quantity: int = (
|
||||
_bag.get_quantity(item.item_id)
|
||||
if _bag != null
|
||||
else 0
|
||||
)
|
||||
_active_bait_quantity.text = str(quantity)
|
||||
_active_bait_quantity.add_theme_font_size_override(
|
||||
"font_size",
|
||||
13 if quantity >= 100 else 15,
|
||||
)
|
||||
_active_bait_button.tooltip_text = "%s ×%d" % [
|
||||
item.display_name,
|
||||
quantity,
|
||||
]
|
||||
|
||||
|
||||
func _on_hud_active_bait_changed(_item_id: StringName) -> void:
|
||||
_refresh_active_bait_indicator()
|
||||
|
||||
|
||||
func _on_hud_bait_inventory_changed() -> void:
|
||||
_refresh_active_bait_indicator()
|
||||
|
||||
|
||||
func set_gameplay_ui_enabled(enabled: bool) -> void:
|
||||
_gameplay_ui_enabled = enabled
|
||||
_gameplay_transient_hud.visible = enabled and not _player_menu_open
|
||||
|
|
@ -1231,7 +1357,12 @@ func get_fishing_shop() -> FishingShopType:
|
|||
return _fishing_shop
|
||||
|
||||
|
||||
func set_shop_prompt_visible(is_visible: bool) -> void:
|
||||
func set_shop_prompt_visible(
|
||||
is_visible: bool,
|
||||
world_anchor: Vector3 = Vector3(0.0, INF, 0.0),
|
||||
) -> void:
|
||||
_apply_shop_prompt_style()
|
||||
var was_visible := _shop_prompt.visible
|
||||
_shop_prompt.visible = (
|
||||
is_visible
|
||||
and _gameplay_ui_enabled
|
||||
|
|
@ -1239,6 +1370,112 @@ func set_shop_prompt_visible(is_visible: bool) -> void:
|
|||
and not _player_menu_open
|
||||
and not _shop_open
|
||||
)
|
||||
if _shop_prompt.visible:
|
||||
if not was_visible:
|
||||
_ensure_shop_animalese_voice()
|
||||
TypewriterRevealType.start(
|
||||
_shop_prompt_message,
|
||||
SHOP_SPEECH_CHARACTERS_PER_SECOND,
|
||||
)
|
||||
_shop_animalese_voice.speak_text(
|
||||
_shop_prompt_message,
|
||||
_shop_prompt_message.text,
|
||||
"shopkeeper",
|
||||
SHOP_ANIMALESE_VOICE_ID,
|
||||
SHOP_SPEECH_CHARACTERS_PER_SECOND,
|
||||
)
|
||||
if world_anchor.is_finite():
|
||||
_position_shop_prompt(world_anchor)
|
||||
|
||||
|
||||
func _ensure_shop_animalese_voice() -> void:
|
||||
if _shop_animalese_voice != null:
|
||||
return
|
||||
_shop_animalese_voice = AnimaleseVoiceType.new()
|
||||
_shop_animalese_voice.name = "ShopAnimaleseVoice"
|
||||
_shop_animalese_voice.base_pitch = SHOP_ANIMALESE_BASE_PITCH
|
||||
add_child(_shop_animalese_voice)
|
||||
|
||||
|
||||
func _apply_shop_prompt_style() -> void:
|
||||
if _shop_prompt.has_meta(&"shop_prompt_styled"):
|
||||
return
|
||||
_shop_prompt.set_meta(&"shop_prompt_styled", true)
|
||||
var bubble_style := StyleBoxFlat.new()
|
||||
bubble_style.bg_color = Color(UtilityPageStyle.OCEAN_PANEL_MID, 0.96)
|
||||
bubble_style.set_border_width_all(0)
|
||||
bubble_style.set_corner_radius_all(12)
|
||||
bubble_style.anti_aliasing = false
|
||||
_shop_prompt_bubble.add_theme_stylebox_override("panel", bubble_style)
|
||||
var badge_style := StyleBoxFlat.new()
|
||||
badge_style.bg_color = Color("0b5558")
|
||||
badge_style.set_border_width_all(0)
|
||||
badge_style.set_corner_radius_all(12)
|
||||
badge_style.anti_aliasing = false
|
||||
_shop_prompt_key_badge.add_theme_stylebox_override("panel", badge_style)
|
||||
for label: Label in [_shop_prompt_message, _shop_prompt_key]:
|
||||
label.add_theme_font_override("font", UtilityPageStyle.TuffyFont)
|
||||
label.add_theme_color_override(
|
||||
"font_color",
|
||||
UtilityPageStyle.OCEAN_TEXT_PRIMARY,
|
||||
)
|
||||
_shop_prompt_pointer.color = Color(
|
||||
UtilityPageStyle.OCEAN_PANEL_MID,
|
||||
0.96,
|
||||
)
|
||||
|
||||
|
||||
func _position_shop_prompt(world_anchor: Vector3) -> void:
|
||||
if _player == null:
|
||||
_shop_prompt.hide()
|
||||
return
|
||||
var camera: Camera3D = _player.get_gameplay_camera()
|
||||
if camera == null or camera.is_position_behind(world_anchor):
|
||||
_shop_prompt.hide()
|
||||
return
|
||||
var camera_viewport_size := camera.get_viewport().get_visible_rect().size
|
||||
var ui_viewport_size: Vector2 = _canonical_stage.size
|
||||
if camera_viewport_size.x <= 0.0 or camera_viewport_size.y <= 0.0:
|
||||
_shop_prompt.hide()
|
||||
return
|
||||
var screen_position := (
|
||||
camera.unproject_position(world_anchor)
|
||||
* ui_viewport_size
|
||||
/ camera_viewport_size
|
||||
)
|
||||
if (
|
||||
screen_position.x < -80.0
|
||||
or screen_position.x > ui_viewport_size.x + 80.0
|
||||
or screen_position.y < -80.0
|
||||
or screen_position.y > ui_viewport_size.y + 80.0
|
||||
):
|
||||
_shop_prompt.hide()
|
||||
return
|
||||
var pointer_height := 10.0
|
||||
var desired := screen_position - Vector2(
|
||||
_shop_prompt.size.x * 0.5,
|
||||
_shop_prompt.size.y + pointer_height,
|
||||
)
|
||||
_shop_prompt.position = Vector2(
|
||||
clampf(
|
||||
desired.x,
|
||||
8.0,
|
||||
ui_viewport_size.x - _shop_prompt.size.x - 8.0,
|
||||
),
|
||||
clampf(
|
||||
desired.y,
|
||||
8.0,
|
||||
ui_viewport_size.y - _shop_prompt.size.y - pointer_height - 8.0,
|
||||
),
|
||||
)
|
||||
_shop_prompt_pointer.position = Vector2(
|
||||
clampf(
|
||||
screen_position.x - _shop_prompt.position.x,
|
||||
20.0,
|
||||
_shop_prompt.size.x - 20.0,
|
||||
),
|
||||
_shop_prompt.size.y - 1.0,
|
||||
)
|
||||
|
||||
|
||||
func get_screen_fade() -> ScreenFade:
|
||||
|
|
|
|||
131
ui/game_ui.tscn
|
|
@ -82,6 +82,71 @@ grow_horizontal = 2
|
|||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="ActiveBaitIndicator" type="Control" parent="UIRoot/CanonicalStage/GameplayTransientHUD"]
|
||||
unique_name_in_owner = true
|
||||
z_index = 54
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -88.0
|
||||
offset_top = -88.0
|
||||
offset_right = -16.0
|
||||
offset_bottom = -16.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
mouse_filter = 2
|
||||
theme = ExtResource("3_theme")
|
||||
|
||||
[node name="ActiveBaitButton" type="Button" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ActiveBaitIndicator"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
focus_mode = 0
|
||||
texture_filter = 1
|
||||
expand_icon = true
|
||||
alignment = 1
|
||||
icon_alignment = 1
|
||||
vertical_icon_alignment = 1
|
||||
|
||||
[node name="ActiveBaitQuantityBadge" type="Panel" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ActiveBaitIndicator"]
|
||||
unique_name_in_owner = true
|
||||
z_index = 2
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -27.0
|
||||
offset_top = 3.0
|
||||
offset_right = -3.0
|
||||
offset_bottom = 27.0
|
||||
grow_horizontal = 0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="ActiveBaitQuantity" type="Label" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ActiveBaitIndicator/ActiveBaitQuantityBadge"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 1.0
|
||||
offset_right = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
theme_override_colors/font_color = Color(0.905882, 0.960784, 0.956863, 1)
|
||||
theme_override_font_sizes/font_size = 15
|
||||
text = "0"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ExperiencePresentation" type="Control" parent="UIRoot/CanonicalStage"]
|
||||
unique_name_in_owner = true
|
||||
z_index = 200
|
||||
|
|
@ -333,35 +398,67 @@ unique_name_in_owner = true
|
|||
[node name="QuickRadialMenu" parent="UIRoot/CanonicalStage" instance=ExtResource("12_quick")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="ShopPrompt" type="PanelContainer" parent="UIRoot/CanonicalStage/GameplayTransientHUD"]
|
||||
[node name="ShopPrompt" type="Control" parent="UIRoot/CanonicalStage/GameplayTransientHUD"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
z_index = 55
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -150.0
|
||||
offset_top = -284.0
|
||||
offset_right = 150.0
|
||||
offset_bottom = -246.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 72.0
|
||||
mouse_filter = 2
|
||||
theme = ExtResource("3_theme")
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt"]
|
||||
[node name="ShopPromptBubble" type="PanelContainer" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt/ShopPromptBubble"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 7
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 7
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="Label" type="Label" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt/Margin"]
|
||||
[node name="ShopPromptMessage" type="Label" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt/ShopPromptBubble/Margin"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "press e to open fishing shop"
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Hey, if you've got any fish I've got cash! OwO"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="ShopPromptKeyBadge" type="Panel" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_left = 282.0
|
||||
offset_top = -8.0
|
||||
offset_right = 306.0
|
||||
offset_bottom = 16.0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="ShopPromptKey" type="Label" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt/ShopPromptKeyBadge"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
theme_override_font_sizes/font_size = 15
|
||||
text = "E"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ShopPromptPointer" type="Polygon2D" parent="UIRoot/CanonicalStage/GameplayTransientHUD/ShopPrompt"]
|
||||
unique_name_in_owner = true
|
||||
polygon = PackedVector2Array(-8, 0, 8, 0, 0, 10)
|
||||
|
||||
[node name="FishingShop" parent="UIRoot/CanonicalStage" instance=ExtResource("8_shop")]
|
||||
unique_name_in_owner = true
|
||||
|
|
|
|||
BIN
ui/icons/pictograms/arrow_dark_down_full.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/arrow_dark_down_full.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d4aah3j5brkij"
|
||||
path="res://.godot/imported/arrow_dark_down_full.png-0e7bb59c41a81c0bd02261d6a7b319ef.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_dark_down_full.png"
|
||||
dest_files=["res://.godot/imported/arrow_dark_down_full.png-0e7bb59c41a81c0bd02261d6a7b319ef.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/arrow_dark_up_full.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/arrow_dark_up_full.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d34x31jx5p5ll"
|
||||
path="res://.godot/imported/arrow_dark_up_full.png-907f3a8653cf6bf8b6ba95ad31b18e0d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_dark_up_full.png"
|
||||
dest_files=["res://.godot/imported/arrow_dark_up_full.png-907f3a8653cf6bf8b6ba95ad31b18e0d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/arrow_light_down_more.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/arrow_light_down_more.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cmc7sguttrl2o"
|
||||
path="res://.godot/imported/arrow_light_down_more.png-a02fb5d09f2022507ddb6c06e3f22732.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_light_down_more.png"
|
||||
dest_files=["res://.godot/imported/arrow_light_down_more.png-a02fb5d09f2022507ddb6c06e3f22732.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/arrow_light_left_more.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
40
ui/icons/pictograms/arrow_light_left_more.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b3lx64prsccyk"
|
||||
path="res://.godot/imported/arrow_light_left_more.png-a92f7c96dbcafd9c1b2cb612e94fef44.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_light_left_more.png"
|
||||
dest_files=["res://.godot/imported/arrow_light_left_more.png-a92f7c96dbcafd9c1b2cb612e94fef44.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/arrow_light_right_more.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/arrow_light_right_more.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cedstrt57et53"
|
||||
path="res://.godot/imported/arrow_light_right_more.png-56d3df49848f9fee268e5c4b6c279828.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_light_right_more.png"
|
||||
dest_files=["res://.godot/imported/arrow_light_right_more.png-56d3df49848f9fee268e5c4b6c279828.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/arrow_light_up_more.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/arrow_light_up_more.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dqu71oklbvofk"
|
||||
path="res://.godot/imported/arrow_light_up_more.png-7e8472cc9f410835ab24173229e09c9b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/arrow_light_up_more.png"
|
||||
dest_files=["res://.godot/imported/arrow_light_up_more.png-7e8472cc9f410835ab24173229e09c9b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/check_mark_dark.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
40
ui/icons/pictograms/check_mark_dark.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://3x5tryb721th"
|
||||
path="res://.godot/imported/check_mark_dark.png-d9abda15f33a6a8f8c29c5f148cda086.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/check_mark_dark.png"
|
||||
dest_files=["res://.godot/imported/check_mark_dark.png-d9abda15f33a6a8f8c29c5f148cda086.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/check_mark_light.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
40
ui/icons/pictograms/check_mark_light.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dtibvrik7ug0j"
|
||||
path="res://.godot/imported/check_mark_light.png-83417416d6580b7b5eb41987b7af5ccf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/check_mark_light.png"
|
||||
dest_files=["res://.godot/imported/check_mark_light.png-83417416d6580b7b5eb41987b7af5ccf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/online_dark.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
40
ui/icons/pictograms/online_dark.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://uxkgiwd7py03"
|
||||
path="res://.godot/imported/online_dark.png-081123db8a385b31ed626b7c95b20c3c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/online_dark.png"
|
||||
dest_files=["res://.godot/imported/online_dark.png-081123db8a385b31ed626b7c95b20c3c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/save_dark.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
40
ui/icons/pictograms/save_dark.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b71gds1q8ny61"
|
||||
path="res://.godot/imported/save_dark.png-6dbadbfe5b8057ede23f77629e3c1226.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/save_dark.png"
|
||||
dest_files=["res://.godot/imported/save_dark.png-6dbadbfe5b8057ede23f77629e3c1226.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/settings_dark.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
40
ui/icons/pictograms/settings_dark.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ul28xl5qed55"
|
||||
path="res://.godot/imported/settings_dark.png-7196550e6c3f5a58c1402ab0ccc9c9d0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/settings_dark.png"
|
||||
dest_files=["res://.godot/imported/settings_dark.png-7196550e6c3f5a58c1402ab0ccc9c9d0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/undo_dark.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
40
ui/icons/pictograms/undo_dark.png.import
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://deux1h722j33u"
|
||||
path="res://.godot/imported/undo_dark.png-652c08d6b38e19b70b66927ecfc6222c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui/icons/pictograms/undo_dark.png"
|
||||
dest_files=["res://.godot/imported/undo_dark.png-652c08d6b38e19b70b66927ecfc6222c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
BIN
ui/icons/pictograms/undo_light.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |