Compare commits
No commits in common. "bc91204aa27e1bce2b9673a0a3da35757ca96311" and "1b8d556929b353f2a4b08f77188dd706b0c7b2ff" have entirely different histories.
bc91204aa2
...
1b8d556929
|
|
@ -1,73 +1,13 @@
|
||||||
# Godot 4+ specific ignores
|
*md.backup
|
||||||
.godot/
|
src/.godot/
|
||||||
.nomedia
|
*.blend1
|
||||||
|
result
|
||||||
|
src/addons/godot-jolt
|
||||||
|
*png~
|
||||||
|
*~lock*
|
||||||
|
*_recovered*
|
||||||
|
|
||||||
# Godot-specific ignores
|
builds/
|
||||||
.import/
|
|
||||||
export.cfg
|
|
||||||
export_credentials.cfg
|
|
||||||
*.tmp
|
|
||||||
|
|
||||||
# Imported translations (automatically generated from CSV files)
|
|
||||||
*.translation
|
|
||||||
|
|
||||||
# Mono-specific ignores
|
|
||||||
.mono/
|
|
||||||
data_*/
|
|
||||||
mono_crash.*.json
|
|
||||||
|
|
||||||
|
|
||||||
# IDE Clutter
|
|
||||||
|
|
||||||
# VS Code
|
|
||||||
# https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
||||||
/builds
|
|
||||||
.idea
|
.idea
|
||||||
.vscode/*
|
knowledge.md
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
!.vscode/*.code-snippets
|
|
||||||
!*.code-workspace
|
|
||||||
|
|
||||||
# Built Visual Studio Code Extensions
|
|
||||||
*.vsix
|
|
||||||
AGENTS.md
|
|
||||||
CHANGELOG.md
|
|
||||||
ISSUES.md
|
|
||||||
|
|
||||||
**/.idea
|
|
||||||
**/.DS_Store
|
|
||||||
|
|
||||||
**/.gradle
|
|
||||||
**/*.iml
|
|
||||||
|
|
||||||
**/obj
|
|
||||||
**/bin
|
|
||||||
|
|
||||||
# Jetbrains
|
|
||||||
# https://github.com/JetBrains/godot-support/blob/master/.gitignore
|
|
||||||
rider/.intellijPlatform
|
|
||||||
rider/build
|
|
||||||
rider/protocol/build
|
|
||||||
rider/classes
|
|
||||||
rider/nuget
|
|
||||||
|
|
||||||
gdscript/.intellijPlatform
|
|
||||||
gdscript/build
|
|
||||||
gdscript/protocol/build
|
|
||||||
gdscript/classes
|
|
||||||
|
|
||||||
community/.intellijPlatform
|
|
||||||
community/build
|
|
||||||
community/protocol/build
|
|
||||||
community/classes
|
|
||||||
community/nuget
|
|
||||||
|
|
||||||
*generated*
|
|
||||||
*Generated*
|
|
||||||
|
|
||||||
NuGet.Config
|
|
||||||
|
|
||||||
*.hprof
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to Frame of Mind since commit `c75348845a5136379ce9ab09d2ff64b7bec90f12`.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- New interactable system with action prompts that can play scenes
|
||||||
|
- Added new interactables to youth room with repositioned layout
|
||||||
|
- Interactable prompts now update dynamically based on collected state (shows \"read again\" after collection)
|
||||||
|
- Type-safe interactive handling for player
|
||||||
|
- Room loading system implementation
|
||||||
|
- Basic room start logic
|
||||||
|
- Room play functionality
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
#### Interactables & Positioning
|
||||||
|
- Small improvements to positioning
|
||||||
|
- Sorting function was not according to spec
|
||||||
|
|
||||||
|
#### Save System
|
||||||
|
- Save game parsing failure no longer crashes the game
|
||||||
|
- Save game directory creation on first load
|
||||||
|
- Fixed race condition with settings initialization
|
||||||
|
- New save game only creates once (reduced from multiple duplicates)
|
||||||
|
- Save game picker layout improvements
|
||||||
|
|
||||||
|
#### UI & Menus
|
||||||
|
- Fixed markdown not loading nonexistent resources
|
||||||
|
- Markdown now uses application theme
|
||||||
|
- Fixed masking on loading indicator
|
||||||
|
- Fixed loading spinner animation states
|
||||||
|
- Fixed screenshot size (was 261, corrected to 216 height)
|
||||||
|
- Nav UI in accessibility settings is now accessible again
|
||||||
|
- Card picker input propagation fixed
|
||||||
|
- Card picker now closes properly
|
||||||
|
- Cards now derived from prefab scene
|
||||||
|
- Text updates now forced to deferred
|
||||||
|
- Skip buttons work via mouse
|
||||||
|
- Cardboard can now be clicked and opened
|
||||||
|
|
||||||
|
#### Player & Controls
|
||||||
|
- Player crouching on leaving bed fixed
|
||||||
|
- Line renderer errors due to zero magnitude axis fixed
|
||||||
|
- Climb volume now automatically crouches the player
|
||||||
|
- Player raising and crouching stabilized
|
||||||
|
- Removed annoying half-second wait
|
||||||
|
- Player controller cleanup
|
||||||
|
|
||||||
|
#### Rooms & Scenes
|
||||||
|
- Theme files reconstructed
|
||||||
|
- Regenerated missing UIDs in theme files
|
||||||
|
- Resaved various scenes to fix UIDs
|
||||||
|
- Removed forced preload of all 3 base rooms
|
||||||
|
- Fixed various path and hierarchy issues in youth room
|
||||||
|
- Viewport children no longer break
|
||||||
|
- Found and fixed many broken/orphaned viewports in youth room
|
||||||
|
- Main scene is no longer a Control (fixed input issues)
|
||||||
|
- Removed broken LightmapGI node that was causing scene to be dirtied on every load
|
||||||
|
|
||||||
|
#### Story & Playables
|
||||||
|
- Story playables no longer destroy their own serialized text
|
||||||
|
- Reinstated accidentally deleted paragraph length data
|
||||||
|
- Fixed Draven/Draeven naming inconsistencies
|
||||||
|
- Manual scroll enable on Draven and Voice fixed
|
||||||
|
- Story playables now control their own canvas layer visibility
|
||||||
|
- Board now correctly identifies itself
|
||||||
|
|
||||||
|
#### Code Quality
|
||||||
|
- Fixed hardcoded localization load (en) removed from scene player
|
||||||
|
- Fixed settings panel refactoring path
|
||||||
|
- Fixed shadowing issues in card-board
|
||||||
|
- Fixed syntax errors
|
||||||
|
- Removed all warnings
|
||||||
|
- Fixed untyped variables throughout codebase
|
||||||
|
- Fixed unknown fields issues
|
||||||
|
|
||||||
|
### Refactored
|
||||||
|
- New interactable system replaces old interactive_sprite.gd system
|
||||||
|
- Interactable now has separate `_update_caption()` and `_update_prompt()` methods
|
||||||
|
- Renamed `collectable.gd` to `interactive_sprite.gd`
|
||||||
|
- Moved various embedded scripts to their own `.gd` files
|
||||||
|
- Focus system refactored
|
||||||
|
- Removed deprecated sequencing calls
|
||||||
|
- Removed deprecated signals and `is_board`
|
||||||
|
- Stage system refactored, dead code cleared
|
||||||
|
- Collectable logic refactored
|
||||||
|
- Renamed `SaveGameHandle` to `SaveGameList`
|
||||||
|
- Renamed `scnees` folder to `scenes`
|
||||||
|
- Menu animations moved to tweens/subscenes
|
||||||
|
- Better inheritance and render order for mementos
|
||||||
|
- New direct interactable system
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Replaced all bare `print()` statements with `print_debug()`
|
||||||
|
- Game window set to 1600x900 for better testing/debugging
|
||||||
|
- Explicit search index layout
|
||||||
|
- Main scene changed from Control to different node type
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
- Added player tests for crouching and raiser functionality
|
||||||
|
- Raiser now uses AnimatableBody3D
|
||||||
|
|
||||||
|
### Chores
|
||||||
|
- Generated missing .import files
|
||||||
|
- Added IDE configuration files
|
||||||
|
- Fixed button/Button filename case issues
|
||||||
|
- Cleaned up project structure
|
||||||
|
- Updated .gitignore files
|
||||||
|
|
@ -51,8 +51,7 @@ var current_room_path: String:
|
||||||
@export var is_demo: bool = OS.has_feature("Demo")
|
@export var is_demo: bool = OS.has_feature("Demo")
|
||||||
@export var is_empty: bool = true:
|
@export var is_empty: bool = true:
|
||||||
get():
|
get():
|
||||||
return not FileAccess.file_exists(filepath) or (current_room == State.rooms.NULL)
|
return not FileAccess.file_exists("%s.json:" % filepath)
|
||||||
|
|
||||||
@export var save_manually: bool = false:
|
@export var save_manually: bool = false:
|
||||||
set(val):
|
set(val):
|
||||||
if val: save_to_file(thumbnail)
|
if val: save_to_file(thumbnail)
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,3 @@ func pick_cards(id: Scenes.id, repeat: bool):
|
||||||
|
|
||||||
await cards_picked
|
await cards_picked
|
||||||
hide()
|
hide()
|
||||||
await get_tree().process_frame
|
|
||||||
State.room.save_room()
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,9 @@ var interaction_ui : Control = null
|
||||||
@onready var frame: Sprite3D = $Frame
|
@onready var frame: Sprite3D = $Frame
|
||||||
@onready var canvas_layer: CanvasLayer = $CanvasLayer
|
@onready var canvas_layer: CanvasLayer = $CanvasLayer
|
||||||
|
|
||||||
@onready var note: Node3D = $View/Sprite3D
|
|
||||||
@onready var caption : Label3D = %Caption
|
@onready var caption : Label3D = %Caption
|
||||||
@onready var prompt : Label3D = %Prompt
|
@onready var prompt : Label3D = %Prompt
|
||||||
|
|
||||||
|
|
||||||
@export var billboard : bool = true
|
@export var billboard : bool = true
|
||||||
|
|
||||||
var active : bool = true
|
var active : bool = true
|
||||||
|
|
@ -26,7 +24,6 @@ var collected : bool = false:
|
||||||
var tween: Tween = null
|
var tween: Tween = null
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
assert(note and frame and canvas_layer, "Interactable must have views and frame attached")
|
|
||||||
view.scale = Vector3.ZERO
|
view.scale = Vector3.ZERO
|
||||||
frame.modulate.a = 0
|
frame.modulate.a = 0
|
||||||
if interaction:
|
if interaction:
|
||||||
|
|
@ -47,29 +44,21 @@ func _player_active(value: bool) -> void:
|
||||||
|
|
||||||
func expand() -> void:
|
func expand() -> void:
|
||||||
shown = true
|
shown = true
|
||||||
|
view.scale = Vector3.ZERO
|
||||||
if tween and tween.is_valid():
|
frame.modulate = Color.TRANSPARENT
|
||||||
tween.kill()
|
view.rotation.z = -PI*0.5 # Godot angle wrapping is ... something
|
||||||
else:
|
if tween: tween.kill()
|
||||||
view.scale = Vector3.ZERO
|
|
||||||
note.rotation.z = -PI*0.5 # Godot angle wrapping is ... something
|
|
||||||
frame.modulate = Color.TRANSPARENT
|
|
||||||
frame.scale = Vector3(1.5, 1.5, 1.5)
|
|
||||||
|
|
||||||
tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
||||||
tween.parallel().tween_property(view, "scale", Vector3.ONE, 1.0).set_delay(0.5)
|
tween.parallel().tween_property(view, "scale", Vector3.ONE, 1.0).set_delay(0.5)
|
||||||
tween.parallel().tween_property(note, "rotation:z", 0, 0.8).set_delay(0.5)
|
tween.parallel().tween_property(view, "rotation:z", 0, 0.8).set_delay(0.5)
|
||||||
tween.parallel().tween_property(frame, "modulate:a", 1.0, 2.0).set_trans(Tween.TRANS_QUAD)
|
tween.parallel().tween_property(frame, "modulate:a", 1.0, 2.0)
|
||||||
tween.parallel().tween_property(frame, "scale", Vector3.ONE, 1.0).set_trans(Tween.TRANS_QUART)
|
|
||||||
|
|
||||||
|
|
||||||
func collapse() -> void:
|
func collapse() -> void:
|
||||||
shown = false
|
shown = false
|
||||||
if tween and tween.is_valid(): tween.kill()
|
if tween: tween.kill()
|
||||||
tween = create_tween().set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_BACK)
|
tween = create_tween().set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_BACK)
|
||||||
tween.parallel().tween_property(view, "scale", Vector3.ZERO, 0.3)
|
tween.parallel().tween_property(view, "scale", Vector3.ZERO, 0.3)
|
||||||
tween.parallel().tween_property(frame, "modulate:a", 0, 0.5).set_trans(Tween.TRANS_QUAD)
|
tween.parallel().tween_property(frame, "modulate:a", 0, 0.6)
|
||||||
tween.parallel().tween_property(frame, "scale", Vector3.ONE * 2.0, 1.0).set_trans(Tween.TRANS_QUAD)
|
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
_process_billboard()
|
_process_billboard()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
class_name SaveGameDisplay extends Button
|
class_name SaveGameDisplay extends Button
|
||||||
|
|
||||||
signal delete_requested
|
|
||||||
|
|
||||||
var _is_built: bool = false
|
var _is_built: bool = false
|
||||||
|
|
||||||
@export var save: SaveGame:
|
@export var save: SaveGame:
|
||||||
|
|
@ -55,7 +53,7 @@ func rebuild():
|
||||||
|
|
||||||
match TranslationServer.get_locale():
|
match TranslationServer.get_locale():
|
||||||
"de":
|
"de":
|
||||||
localised_weekday = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]
|
localised_weekday = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]
|
||||||
localised_date_time = "%s, %d.%d.%d um %d:%02d" % [localised_weekday[date_time["weekday"]],
|
localised_date_time = "%s, %d.%d.%d um %d:%02d" % [localised_weekday[date_time["weekday"]],
|
||||||
date_time["day"],
|
date_time["day"],
|
||||||
date_time["month"],
|
date_time["month"],
|
||||||
|
|
@ -64,7 +62,7 @@ func rebuild():
|
||||||
date_time["minute"]
|
date_time["minute"]
|
||||||
]
|
]
|
||||||
_:
|
_:
|
||||||
localised_weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
localised_weekday = ["Monday", "Tuseday", "Wensday", "Thursday", "Friday", "Saturday", "Sunday"]
|
||||||
localised_date_time = "%s, %d/%d/%d - %d:%02d (%s)" % [localised_weekday[date_time["weekday"]],
|
localised_date_time = "%s, %d/%d/%d - %d:%02d (%s)" % [localised_weekday[date_time["weekday"]],
|
||||||
date_time["day"],
|
date_time["day"],
|
||||||
date_time["month"],
|
date_time["month"],
|
||||||
|
|
@ -77,7 +75,6 @@ func rebuild():
|
||||||
time_label.text = localised_date_time if not save.current_room == State.rooms.NULL else "Start new game"
|
time_label.text = localised_date_time if not save.current_room == State.rooms.NULL else "Start new game"
|
||||||
|
|
||||||
var info:= VBoxContainer.new()
|
var info:= VBoxContainer.new()
|
||||||
info.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
||||||
base_container.add_child(info)
|
base_container.add_child(info)
|
||||||
|
|
||||||
info.add_child(heading_split)
|
info.add_child(heading_split)
|
||||||
|
|
@ -112,16 +109,6 @@ func rebuild():
|
||||||
info.add_child(state)
|
info.add_child(state)
|
||||||
info.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
info.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||||
|
|
||||||
# Delete button anchored to bottom right
|
|
||||||
var delete_button := Button.new()
|
|
||||||
delete_button.text = "Delete"
|
|
||||||
delete_button.size_flags_vertical = Control.SIZE_SHRINK_END
|
|
||||||
delete_button.pressed.connect(func():
|
|
||||||
delete_requested.emit()
|
|
||||||
get_viewport().set_input_as_handled()
|
|
||||||
)
|
|
||||||
base_container.add_child(delete_button)
|
|
||||||
|
|
||||||
theme_type_variation = "SaveButton"
|
theme_type_variation = "SaveButton"
|
||||||
|
|
||||||
call_deferred("resize")
|
call_deferred("resize")
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ var save_buttons: Array[SaveGameDisplay]
|
||||||
_load_games()
|
_load_games()
|
||||||
|
|
||||||
@onready var list_container: VBoxContainer = %ListContainer
|
@onready var list_container: VBoxContainer = %ListContainer
|
||||||
@onready var back_button: Button = $MarginContainer/VBoxContainer/HBoxContainer/Button
|
|
||||||
|
|
||||||
func _validate_property(property: Dictionary) -> void:
|
func _validate_property(property: Dictionary) -> void:
|
||||||
if property.name == "saves":
|
if property.name == "saves":
|
||||||
|
|
@ -22,7 +21,6 @@ func _ready() -> void:
|
||||||
_load_games()
|
_load_games()
|
||||||
hide()
|
hide()
|
||||||
set_process_input(false)
|
set_process_input(false)
|
||||||
back_button.pressed.connect(cancel)
|
|
||||||
|
|
||||||
func _ensure_directory() -> void:
|
func _ensure_directory() -> void:
|
||||||
var dir := DirAccess.open(State.user_saves_path)
|
var dir := DirAccess.open(State.user_saves_path)
|
||||||
|
|
@ -44,10 +42,7 @@ func _load_games():
|
||||||
|
|
||||||
for path in filepaths:
|
for path in filepaths:
|
||||||
if path is String and path.ends_with(".json"):
|
if path is String and path.ends_with(".json"):
|
||||||
var save := SaveGame.new("%s/%s" % [State.user_saves_path, path.get_basename()])
|
saves.append(SaveGame.new("%s/%s" % [State.user_saves_path, path.get_basename()]))
|
||||||
# HACK: Skip empty saves (we decide later what to do with them)
|
|
||||||
if not save.is_empty:
|
|
||||||
saves.append(save)
|
|
||||||
|
|
||||||
_sort_saves()
|
_sort_saves()
|
||||||
_rebuild_buttons()
|
_rebuild_buttons()
|
||||||
|
|
@ -72,34 +67,11 @@ func _rebuild_buttons() -> void:
|
||||||
save_box.add_child(new_button)
|
save_box.add_child(new_button)
|
||||||
save_buttons.append(new_button)
|
save_buttons.append(new_button)
|
||||||
new_button.pressed.connect(_on_game_picked.bind(i))
|
new_button.pressed.connect(_on_game_picked.bind(i))
|
||||||
new_button.delete_requested.connect(_on_delete_requested.bind(i))
|
|
||||||
|
|
||||||
|
|
||||||
func _on_game_picked(id: int) -> void:
|
func _on_game_picked(id: int) -> void:
|
||||||
_picked.emit(saves[id])
|
_picked.emit(saves[id])
|
||||||
|
|
||||||
func _on_delete_requested(id: int) -> void:
|
|
||||||
var save_to_delete := saves[id]
|
|
||||||
var save_path := save_to_delete.filepath
|
|
||||||
var thumbnail_path := "%s/thumbnails/%s.png" % [save_path.get_base_dir(), save_to_delete.unique_save_name]
|
|
||||||
|
|
||||||
# Delete the save file
|
|
||||||
if FileAccess.file_exists(save_path):
|
|
||||||
DirAccess.remove_absolute(save_path)
|
|
||||||
print_debug("Deleted save file: %s" % save_path)
|
|
||||||
|
|
||||||
# Delete the thumbnail
|
|
||||||
if FileAccess.file_exists(thumbnail_path):
|
|
||||||
DirAccess.remove_absolute(thumbnail_path)
|
|
||||||
print_debug("Deleted thumbnail: %s" % thumbnail_path)
|
|
||||||
|
|
||||||
# Reload the save list
|
|
||||||
_load_games()
|
|
||||||
|
|
||||||
# Refocus on a valid button if any exist
|
|
||||||
if save_buttons.size() > 0:
|
|
||||||
var focus_index := mini(id, save_buttons.size() - 1)
|
|
||||||
save_buttons[focus_index].grab_focus()
|
|
||||||
|
|
||||||
func get_most_recent_save() -> SaveGame:
|
func get_most_recent_save() -> SaveGame:
|
||||||
_sort_saves()
|
_sort_saves()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue