moving on

This commit is contained in:
betalars 2024-09-15 11:30:31 +02:00
parent 79c8abc6e7
commit 2e52c8d0c1
27 changed files with 1654 additions and 1655 deletions

View File

@ -3,169 +3,169 @@ extends MeshInstance3D
class_name LineRenderer3D class_name LineRenderer3D
@export var points: Array[Vector3] = [Vector3(0,0,0),Vector3(0,5,0)]: @export var points: Array[Vector3] = [Vector3(0,0,0),Vector3(0,5,0)]:
set(new_points): points = new_points set(new_points): points = new_points
@export var start_thickness:float = 0.1: @export var start_thickness:float = 0.1:
set(new_start_thickness): start_thickness = new_start_thickness set(new_start_thickness): start_thickness = new_start_thickness
@export var end_thickness:float = 0.1: @export var end_thickness:float = 0.1:
set(new_end_thickness): end_thickness = new_end_thickness set(new_end_thickness): end_thickness = new_end_thickness
@export var corner_resolution:int = 5: @export var corner_resolution:int = 5:
set(new_corner_resolution): corner_resolution = new_corner_resolution set(new_corner_resolution): corner_resolution = new_corner_resolution
@export var cap_resolution:int = 5: @export var cap_resolution:int = 5:
set(new_cap_resolution): cap_resolution = new_cap_resolution set(new_cap_resolution): cap_resolution = new_cap_resolution
@export var draw_caps:bool = true: @export var draw_caps:bool = true:
set(new_draw_caps): draw_caps = new_draw_caps set(new_draw_caps): draw_caps = new_draw_caps
@export var draw_crners:bool = true: @export var draw_crners:bool = true:
set(new_draw_crners): draw_crners = new_draw_crners set(new_draw_crners): draw_crners = new_draw_crners
@export var use_global_coords:bool = true: @export var use_global_coords:bool = true:
set(new_use_global_coords): use_global_coords = new_use_global_coords set(new_use_global_coords): use_global_coords = new_use_global_coords
@export var tile_texture:bool = true: @export var tile_texture:bool = true:
set(new_tile_texture): tile_texture = new_tile_texture set(new_tile_texture): tile_texture = new_tile_texture
var camera : Camera3D var camera : Camera3D
var cameraOrigin : Vector3 var cameraOrigin : Vector3
func _enter_tree(): func _enter_tree():
mesh = ImmediateMesh.new() mesh = ImmediateMesh.new()
func _ready(): func _ready():
pass pass
func _process(_delta): func _process(_delta):
if points.size() < 2: if points.size() < 2:
return return
camera = get_viewport().get_camera_3d() camera = get_viewport().get_camera_3d()
if camera == null: if camera == null:
return return
cameraOrigin = to_local(camera.get_global_transform().origin) cameraOrigin = to_local(camera.get_global_transform().origin)
var progressStep:float = 1.0 / points.size(); var progressStep:float = 1.0 / points.size();
var progress:float = 0; var progress:float = 0;
var thickness:float = lerp(start_thickness, end_thickness, progress); var thickness:float = lerp(start_thickness, end_thickness, progress);
var nextThickness:float = lerp(start_thickness, end_thickness, progress + progressStep); var nextThickness:float = lerp(start_thickness, end_thickness, progress + progressStep);
var surface:SurfaceTool = SurfaceTool.new() var surface:SurfaceTool = SurfaceTool.new()
surface.begin(Mesh.PRIMITIVE_TRIANGLES) surface.begin(Mesh.PRIMITIVE_TRIANGLES)
for i in range(points.size() - 1): for i in range(points.size() - 1):
var A:Vector3 = points[i] var A:Vector3 = points[i]
var B:Vector3 = points[i+1] var B:Vector3 = points[i+1]
if use_global_coords: if use_global_coords:
A = to_local(A) A = to_local(A)
B = to_local(B) B = to_local(B)
var AB:Vector3 = B - A; var AB:Vector3 = B - A;
var orthogonalABStart:Vector3 = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * thickness; var orthogonalABStart:Vector3 = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * thickness;
var orthogonalABEnd:Vector3 = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * nextThickness; var orthogonalABEnd:Vector3 = (cameraOrigin - ((A + B) / 2)).cross(AB).normalized() * nextThickness;
var AtoABStart:Vector3 = A + orthogonalABStart var AtoABStart:Vector3 = A + orthogonalABStart
var AfromABStart:Vector3 = A - orthogonalABStart var AfromABStart:Vector3 = A - orthogonalABStart
var BtoABEnd:Vector3 = B + orthogonalABEnd var BtoABEnd:Vector3 = B + orthogonalABEnd
var BfromABEnd:Vector3 = B - orthogonalABEnd var BfromABEnd:Vector3 = B - orthogonalABEnd
if i == 0: if i == 0:
if draw_caps: if draw_caps:
cap(surface, A, B, thickness, cap_resolution) cap(surface, A, B, thickness, cap_resolution)
if tile_texture: if tile_texture:
var ABLen = AB.length() var ABLen = AB.length()
var ABFloor = floor(ABLen) var ABFloor = floor(ABLen)
var ABFrac = ABLen - ABFloor var ABFrac = ABLen - ABFloor
surface.set_uv(Vector2(ABFloor, 0)) surface.set_uv(Vector2(ABFloor, 0))
surface.add_vertex(AtoABStart) surface.add_vertex(AtoABStart)
surface.set_uv(Vector2(-ABFrac, 0)) surface.set_uv(Vector2(-ABFrac, 0))
surface.add_vertex(BtoABEnd) surface.add_vertex(BtoABEnd)
surface.set_uv(Vector2(ABFloor, 1)) surface.set_uv(Vector2(ABFloor, 1))
surface.add_vertex(AfromABStart) surface.add_vertex(AfromABStart)
surface.set_uv(Vector2(-ABFrac, 0)) surface.set_uv(Vector2(-ABFrac, 0))
surface.add_vertex(BtoABEnd) surface.add_vertex(BtoABEnd)
surface.set_uv(Vector2(-ABFrac, 1)) surface.set_uv(Vector2(-ABFrac, 1))
surface.add_vertex(BfromABEnd) surface.add_vertex(BfromABEnd)
surface.set_uv(Vector2(ABFloor, 1)) surface.set_uv(Vector2(ABFloor, 1))
surface.add_vertex(AfromABStart) surface.add_vertex(AfromABStart)
else: else:
surface.set_uv(Vector2(1, 0)) surface.set_uv(Vector2(1, 0))
surface.add_vertex(AtoABStart) surface.add_vertex(AtoABStart)
surface.set_uv(Vector2(0, 0)) surface.set_uv(Vector2(0, 0))
surface.add_vertex(BtoABEnd) surface.add_vertex(BtoABEnd)
surface.set_uv(Vector2(1, 1)) surface.set_uv(Vector2(1, 1))
surface.add_vertex(AfromABStart) surface.add_vertex(AfromABStart)
surface.set_uv(Vector2(0, 0)) surface.set_uv(Vector2(0, 0))
surface.add_vertex(BtoABEnd) surface.add_vertex(BtoABEnd)
surface.set_uv(Vector2(0, 1)) surface.set_uv(Vector2(0, 1))
surface.add_vertex(BfromABEnd) surface.add_vertex(BfromABEnd)
surface.set_uv(Vector2(1, 1)) surface.set_uv(Vector2(1, 1))
surface.add_vertex(AfromABStart) surface.add_vertex(AfromABStart)
if i == points.size() - 2: if i == points.size() - 2:
if draw_caps: if draw_caps:
cap(surface, B, A, nextThickness, cap_resolution) cap(surface, B, A, nextThickness, cap_resolution)
else: else:
if draw_crners: if draw_crners:
var C = points[i+2] var C = points[i+2]
if use_global_coords: if use_global_coords:
C = to_local(C) C = to_local(C)
var BC = C - B; var BC = C - B;
var orthogonalBCStart = (cameraOrigin - ((B + C) / 2)).cross(BC).normalized() * nextThickness; var orthogonalBCStart = (cameraOrigin - ((B + C) / 2)).cross(BC).normalized() * nextThickness;
var angleDot = AB.dot(orthogonalBCStart) var angleDot = AB.dot(orthogonalBCStart)
if angleDot > 0 and not angleDot == 1: if angleDot > 0 and not angleDot == 1:
corner(surface, B, BtoABEnd, B + orthogonalBCStart, corner_resolution) corner(surface, B, BtoABEnd, B + orthogonalBCStart, corner_resolution)
elif angleDot < 0 and not angleDot == -1: elif angleDot < 0 and not angleDot == -1:
corner(surface, B, B - orthogonalBCStart, BfromABEnd, corner_resolution) corner(surface, B, B - orthogonalBCStart, BfromABEnd, corner_resolution)
progress += progressStep; progress += progressStep;
thickness = lerp(start_thickness, end_thickness, progress); thickness = lerp(start_thickness, end_thickness, progress);
nextThickness = lerp(start_thickness, end_thickness, progress + progressStep); nextThickness = lerp(start_thickness, end_thickness, progress + progressStep);
surface.generate_normals() surface.generate_normals()
surface.generate_tangents() surface.generate_tangents()
mesh = surface.commit() mesh = surface.commit()
func cap(surface: SurfaceTool, center:Vector3, pivot:Vector3, thickness:float, cap_resolution:int): func cap(surface: SurfaceTool, center:Vector3, pivot:Vector3, thickness:float, cap_resolution:int):
var orthogonal:Vector3 = (cameraOrigin - center).cross(center - pivot).normalized() * thickness; var orthogonal:Vector3 = (cameraOrigin - center).cross(center - pivot).normalized() * thickness;
var axis:Vector3 = (center - cameraOrigin).normalized(); var axis:Vector3 = (center - cameraOrigin).normalized();
var vertex_array:Array = [] var vertex_array:Array = []
for i in range(cap_resolution + 1): for i in range(cap_resolution + 1):
vertex_array.append(Vector3(0,0,0)) vertex_array.append(Vector3(0,0,0))
vertex_array[0] = center + orthogonal; vertex_array[0] = center + orthogonal;
vertex_array[cap_resolution] = center - orthogonal; vertex_array[cap_resolution] = center - orthogonal;
for i in range(1, cap_resolution): for i in range(1, cap_resolution):
vertex_array[i] = center + (orthogonal.rotated(axis, lerp(0.0, PI, float(i) / cap_resolution))); vertex_array[i] = center + (orthogonal.rotated(axis, lerp(0.0, PI, float(i) / cap_resolution)));
for i in range(1, cap_resolution + 1): for i in range(1, cap_resolution + 1):
surface.set_uv(Vector2(0, (i - 1) / cap_resolution)) surface.set_uv(Vector2(0, (i - 1) / cap_resolution))
surface.add_vertex(vertex_array[i - 1]); surface.add_vertex(vertex_array[i - 1]);
surface.set_uv(Vector2(0, (i - 1) / cap_resolution)) surface.set_uv(Vector2(0, (i - 1) / cap_resolution))
surface.add_vertex(vertex_array[i]); surface.add_vertex(vertex_array[i]);
surface.set_uv(Vector2(0.5, 0.5)) surface.set_uv(Vector2(0.5, 0.5))
surface.add_vertex(center); surface.add_vertex(center);
func corner(surface: SurfaceTool, center:Vector3, start:Vector3, end:Vector3, cap_resolution:int): func corner(surface: SurfaceTool, center:Vector3, start:Vector3, end:Vector3, cap_resolution:int):
var vertex_array:Array = [] var vertex_array:Array = []
for i in range(cap_resolution + 1): for i in range(cap_resolution + 1):
vertex_array.append(Vector3(0,0,0)) vertex_array.append(Vector3(0,0,0))
vertex_array[0] = start; vertex_array[0] = start;
vertex_array[cap_resolution] = end; vertex_array[cap_resolution] = end;
var axis:Vector3 = start.cross(end).normalized() var axis:Vector3 = start.cross(end).normalized()
var offset:Vector3 = start - center var offset:Vector3 = start - center
var angle:float = offset.angle_to(end - center) var angle:float = offset.angle_to(end - center)
for i in range(1, cap_resolution): for i in range(1, cap_resolution):
vertex_array[i] = center + offset.rotated(axis, lerp(0.0, angle, float(i) / cap_resolution)); vertex_array[i] = center + offset.rotated(axis, lerp(0.0, angle, float(i) / cap_resolution));
for i in range(1, cap_resolution + 1): for i in range(1, cap_resolution + 1):
surface.set_uv(Vector2(0, (i - 1) / cap_resolution)) surface.set_uv(Vector2(0, (i - 1) / cap_resolution))
surface.add_vertex(vertex_array[i - 1]); surface.add_vertex(vertex_array[i - 1]);
surface.set_uv(Vector2(0, (i - 1) / cap_resolution)) surface.set_uv(Vector2(0, (i - 1) / cap_resolution))
surface.add_vertex(vertex_array[i]); surface.add_vertex(vertex_array[i]);
surface.set_uv(Vector2(0.5, 0.5)) surface.set_uv(Vector2(0.5, 0.5))
surface.add_vertex(center); surface.add_vertex(center);

View File

@ -5,40 +5,40 @@ extends Area3D
@onready var ui = $UiWrapper/UiSprite/SubViewport.get_child(0) @onready var ui = $UiWrapper/UiSprite/SubViewport.get_child(0)
var revealed: bool = false: var revealed: bool = false:
set(reveal): set(reveal):
revealed = reveal revealed = reveal
if reveal: if reveal:
wrapper.show() wrapper.show()
ui.show() ui.show()
else: else:
ui.hide() ui.hide()
await get_tree().create_timer(1).timeout await get_tree().create_timer(1).timeout
wrapper.hide() wrapper.hide()
var has_mouse: bool = false var has_mouse: bool = false
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
connect("mouse_entered", Callable(self, "_on_mouse_entered")) connect("mouse_entered", Callable(self, "_on_mouse_entered"))
func _on_mouse_entered(): func _on_mouse_entered():
if not State.focus_locked: if not State.focus_locked:
input_ray_pickable = false input_ray_pickable = false
ui.collapsed = false ui.collapsed = false
has_mouse = true has_mouse = true
func _on_mouse_exited(): func _on_mouse_exited():
print("mouse_exited") print("mouse_exited")
input_ray_pickable = true input_ray_pickable = true
ui.collapsed = true ui.collapsed = true
has_mouse = false has_mouse = false
func reveal(): func reveal():
revealed = true revealed = true
await get_tree().create_timer(5).timeout await get_tree().create_timer(5).timeout
if not has_mouse: if not has_mouse:
revealed = false revealed = false
func collapse(): func collapse():
_on_mouse_exited() _on_mouse_exited()
revealed = false revealed = false

View File

@ -2,11 +2,11 @@ extends Node3D
# Referencing the current State of the Scene. # Referencing the current State of the Scene.
enum Modes { enum Modes {
FREEZE, FREEZE,
WALKING, WALKING,
COLLECTING, COLLECTING,
LISTENING, LISTENING,
SORTING SORTING
} }
signal freeze signal freeze
@ -15,35 +15,35 @@ signal ini_room
signal resume_room signal resume_room
var current_mode: int = Modes.FREEZE: var current_mode: int = Modes.FREEZE:
set(new_mode): set(new_mode):
if not current_mode == new_mode: if not current_mode == new_mode:
current_mode = _update_scene(new_mode) current_mode = _update_scene(new_mode)
func start(): func start():
$logic/PlayerController.process_mode = Node.PROCESS_MODE_INHERIT $logic/PlayerController.process_mode = Node.PROCESS_MODE_INHERIT
emit_signal("ini_room") emit_signal("ini_room")
current_mode = Modes.WALKING current_mode = Modes.WALKING
func _update_scene(new_mode) -> int: func _update_scene(new_mode) -> int:
if current_mode == Modes.FREEZE: if current_mode == Modes.FREEZE:
emit_signal("freeze") emit_signal("freeze")
elif new_mode == Modes.FREEZE: elif new_mode == Modes.FREEZE:
emit_signal("freeze") emit_signal("freeze")
return new_mode return new_mode
func is_self(node: Node) -> bool: func is_self(node: Node) -> bool:
return self == node return self == node
func get_ready(): func get_ready():
self.show() self.show()
$sfx/distant_rain.play() $sfx/distant_rain.play()
$"sfx/rain on window".play() $"sfx/rain on window".play()
await get_tree().create_timer(0.1).timeout await get_tree().create_timer(0.1).timeout
$logic/UI/board.hide() $logic/UI/board.hide()
func _ready(): func _ready():
if get_parent() == get_tree().root: if get_parent() == get_tree().root:
get_ready() get_ready()
start() start()

View File

@ -3,107 +3,107 @@ extends CenterContainer
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
$cards/card_1/AnimationPlayer.play("select") $cards/card_1/AnimationPlayer.play("select")
await $cards/card_1/AnimationPlayer.animation_finished await $cards/card_1/AnimationPlayer.animation_finished
$cards/card_1/AnimationPlayer.play("deselect") $cards/card_1/AnimationPlayer.play("deselect")
$cards/card_2/AnimationPlayer.play("select") $cards/card_2/AnimationPlayer.play("select")
await $cards/card_1/AnimationPlayer.animation_finished await $cards/card_1/AnimationPlayer.animation_finished
$cards/card_2/AnimationPlayer.play("deselect") $cards/card_2/AnimationPlayer.play("deselect")
$cards/card_3/AnimationPlayer.play("select") $cards/card_3/AnimationPlayer.play("select")
await $cards/card_2/AnimationPlayer.animation_finished await $cards/card_2/AnimationPlayer.animation_finished
$cards/card_3/AnimationPlayer.play("deselect") $cards/card_3/AnimationPlayer.play("deselect")
await $cards/card_3/AnimationPlayer.animation_finished await $cards/card_3/AnimationPlayer.animation_finished
$cards/card_1/AnimationPlayer.play("select") $cards/card_1/AnimationPlayer.play("select")
await $cards/card_1/AnimationPlayer.animation_finished await $cards/card_1/AnimationPlayer.animation_finished
$cards/card_1/AnimationPlayer.play("take") $cards/card_1/AnimationPlayer.play("take")
$cards/card_2/AnimationPlayer.play("unshuffle") $cards/card_2/AnimationPlayer.play("unshuffle")
$cards/card_3/AnimationPlayer.play("shuffle") $cards/card_3/AnimationPlayer.play("shuffle")
await $cards/card_3/AnimationPlayer.animation_finished await $cards/card_3/AnimationPlayer.animation_finished
for card in $cards.get_children(): for card in $cards.get_children():
card.get_child(1).play("RESET") card.get_child(1).play("RESET")
$cards/card_2/AnimationPlayer.queue("select") $cards/card_2/AnimationPlayer.queue("select")
await $cards/card_2/AnimationPlayer.animation_finished await $cards/card_2/AnimationPlayer.animation_finished
$cards/card_2/AnimationPlayer.play("take") $cards/card_2/AnimationPlayer.play("take")
$cards/card_3/AnimationPlayer.play("unshuffle") $cards/card_3/AnimationPlayer.play("unshuffle")
$cards/card_1/AnimationPlayer.play("shuffle") $cards/card_1/AnimationPlayer.play("shuffle")
await $cards/card_1/AnimationPlayer.animation_finished await $cards/card_1/AnimationPlayer.animation_finished
for card in $cards.get_children(): for card in $cards.get_children():
card.get_child(1).play("RESET") card.get_child(1).play("RESET")
$cards/card_3/AnimationPlayer.queue("select") $cards/card_3/AnimationPlayer.queue("select")
await $cards/card_3/AnimationPlayer.animation_finished await $cards/card_3/AnimationPlayer.animation_finished
$cards/card_3/AnimationPlayer.play("take") $cards/card_3/AnimationPlayer.play("take")
$cards/card_1/AnimationPlayer.play("unshuffle") $cards/card_1/AnimationPlayer.play("unshuffle")
$cards/card_2/AnimationPlayer.play("shuffle") $cards/card_2/AnimationPlayer.play("shuffle")
await $cards/card_2/AnimationPlayer.animation_finished await $cards/card_2/AnimationPlayer.animation_finished
$sticky_notes.show() $sticky_notes.show()
for card in $sticky_notes.get_children(): for card in $sticky_notes.get_children():
card.get_child(1).play("post") card.get_child(1).play("post")
await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_1/AnimationPlayer.play("select") $sticky_notes/sticky_note_1/AnimationPlayer.play("select")
await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_1/AnimationPlayer.play("deselect") $sticky_notes/sticky_note_1/AnimationPlayer.play("deselect")
$sticky_notes/sticky_note_2/AnimationPlayer.play("select") $sticky_notes/sticky_note_2/AnimationPlayer.play("select")
await $sticky_notes/sticky_note_2/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_2/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_2/AnimationPlayer.play("deselect") $sticky_notes/sticky_note_2/AnimationPlayer.play("deselect")
$sticky_notes/sticky_note_3/AnimationPlayer.play("select") $sticky_notes/sticky_note_3/AnimationPlayer.play("select")
await $sticky_notes/sticky_note_3/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_3/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_3/AnimationPlayer.play("deselect") $sticky_notes/sticky_note_3/AnimationPlayer.play("deselect")
$sticky_notes/sticky_note_4/AnimationPlayer.play("select") $sticky_notes/sticky_note_4/AnimationPlayer.play("select")
await $sticky_notes/sticky_note_4/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_4/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_4/AnimationPlayer.play("deselect") $sticky_notes/sticky_note_4/AnimationPlayer.play("deselect")
$sticky_notes/sticky_note_1/AnimationPlayer.play("select") $sticky_notes/sticky_note_1/AnimationPlayer.play("select")
await get_tree().create_timer(1).timeout await get_tree().create_timer(1).timeout
$sticky_notes/sticky_note_1/AnimationPlayer.play("pick") $sticky_notes/sticky_note_1/AnimationPlayer.play("pick")
$sticky_notes/sticky_note_2/AnimationPlayer.play("shuffle") $sticky_notes/sticky_note_2/AnimationPlayer.play("shuffle")
$sticky_notes/sticky_note_3/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_3/AnimationPlayer.play("unshuffle")
$sticky_notes/sticky_note_4/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_4/AnimationPlayer.play("unshuffle")
await $sticky_notes/sticky_note_2/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_2/AnimationPlayer.animation_finished
for card in $sticky_notes.get_children(): for card in $sticky_notes.get_children():
card.get_child(1).play("post") card.get_child(1).play("post")
await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_2/AnimationPlayer.play("select") $sticky_notes/sticky_note_2/AnimationPlayer.play("select")
await get_tree().create_timer(1).timeout await get_tree().create_timer(1).timeout
$sticky_notes/sticky_note_2/AnimationPlayer.play("pick") $sticky_notes/sticky_note_2/AnimationPlayer.play("pick")
$sticky_notes/sticky_note_3/AnimationPlayer.play("shuffle") $sticky_notes/sticky_note_3/AnimationPlayer.play("shuffle")
$sticky_notes/sticky_note_4/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_4/AnimationPlayer.play("unshuffle")
$sticky_notes/sticky_note_1/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_1/AnimationPlayer.play("unshuffle")
await $sticky_notes/sticky_note_3/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_3/AnimationPlayer.animation_finished
for card in $sticky_notes.get_children(): for card in $sticky_notes.get_children():
card.get_child(1).play("post") card.get_child(1).play("post")
await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_3/AnimationPlayer.play("select") $sticky_notes/sticky_note_3/AnimationPlayer.play("select")
await get_tree().create_timer(1).timeout await get_tree().create_timer(1).timeout
$sticky_notes/sticky_note_3/AnimationPlayer.play("pick") $sticky_notes/sticky_note_3/AnimationPlayer.play("pick")
$sticky_notes/sticky_note_4/AnimationPlayer.play("shuffle") $sticky_notes/sticky_note_4/AnimationPlayer.play("shuffle")
$sticky_notes/sticky_note_1/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_1/AnimationPlayer.play("unshuffle")
$sticky_notes/sticky_note_2/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_2/AnimationPlayer.play("unshuffle")
await $sticky_notes/sticky_note_4/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_4/AnimationPlayer.animation_finished
for card in $sticky_notes.get_children(): for card in $sticky_notes.get_children():
card.get_child(1).play("post") card.get_child(1).play("post")
await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished await $sticky_notes/sticky_note_1/AnimationPlayer.animation_finished
$sticky_notes/sticky_note_4/AnimationPlayer.play("select") $sticky_notes/sticky_note_4/AnimationPlayer.play("select")
await get_tree().create_timer(1).timeout await get_tree().create_timer(1).timeout
$sticky_notes/sticky_note_4/AnimationPlayer.play("pick") $sticky_notes/sticky_note_4/AnimationPlayer.play("pick")
$sticky_notes/sticky_note_1/AnimationPlayer.play("shuffle") $sticky_notes/sticky_note_1/AnimationPlayer.play("shuffle")
$sticky_notes/sticky_note_2/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_2/AnimationPlayer.play("unshuffle")
$sticky_notes/sticky_note_3/AnimationPlayer.play("unshuffle") $sticky_notes/sticky_note_3/AnimationPlayer.play("unshuffle")

View File

@ -5,35 +5,35 @@ extends Area3D
@onready var viewport: SubViewport = $UiSprite/SubViewport @onready var viewport: SubViewport = $UiSprite/SubViewport
func _process(_delta): func _process(_delta):
if billboard: if billboard:
var camera = get_viewport().get_camera_3d() var camera = get_viewport().get_camera_3d()
var up = (camera.global_position - global_position) var up = (camera.global_position - global_position)
up = up.cross(Vector3.UP).cross(up) up = up.cross(Vector3.UP).cross(up)
look_at(global_position - (camera.global_position - global_position), up) look_at(global_position - (camera.global_position - global_position), up)
func _unhandled_input(event): func _unhandled_input(event):
viewport.push_input(event) viewport.push_input(event)
func _on_input_event(_camera: Camera3D, event: InputEvent, pos: Vector3, _normal: Vector3, _shape_idx: int): func _on_input_event(_camera: Camera3D, event: InputEvent, pos: Vector3, _normal: Vector3, _shape_idx: int):
if not State.focus_locked: if not State.focus_locked:
# Position of the event in Sprite3D local coordinates. # Position of the event in Sprite3D local coordinates.
var texture_3d_position = sprite.get_global_transform().affine_inverse() * pos var texture_3d_position = sprite.get_global_transform().affine_inverse() * pos
#if !is_zero_approx(texture_3d_position.z): #if !is_zero_approx(texture_3d_position.z):
# # Discard event because event didn't happen on the side of the Sprite3D. # # Discard event because event didn't happen on the side of the Sprite3D.
# return # return
# Position of the event relative to the texture. # Position of the event relative to the texture.
var texture_position: Vector2 = Vector2(texture_3d_position.x, -texture_3d_position.y) / sprite.pixel_size - sprite.get_item_rect().position var texture_position: Vector2 = Vector2(texture_3d_position.x, -texture_3d_position.y) / sprite.pixel_size - sprite.get_item_rect().position
# Send mouse event. # Send mouse event.
var e: InputEvent = event.duplicate() var e: InputEvent = event.duplicate()
if e is InputEventMouse: if e is InputEventMouse:
e.set_position(texture_position) e.set_position(texture_position)
e.set_global_position(texture_position) e.set_global_position(texture_position)
viewport.push_input(e) viewport.push_input(e)
func _on_button_pressed(): func _on_button_pressed():
print("Button pressed") print("Button pressed")
func _on_line_edit_text_submitted(new_text): func _on_line_edit_text_submitted(new_text):
print("Text submitted: ", new_text) print("Text submitted: ", new_text)

View File

@ -2,26 +2,26 @@
extends Button extends Button
func hide(): func hide():
if visible == true: if visible == true:
var tween:Tween = create_tween() var tween:Tween = create_tween()
custom_minimum_size = get_minimum_size() custom_minimum_size = get_minimum_size()
var tmp = text var tmp = text
text = "" text = ""
tween.tween_property(self, "custom_minimum_size", Vector2(size.x, 0), 0.2) tween.tween_property(self, "custom_minimum_size", Vector2(size.x, 0), 0.2)
update_minimum_size() update_minimum_size()
await tween.finished await tween.finished
visible = false visible = false
text = tmp text = tmp
update_minimum_size() update_minimum_size()
func show(): func show():
if visible == false: if visible == false:
var tmp = text var tmp = text
var tween:Tween = create_tween() var tween:Tween = create_tween()
tween.tween_property(self, "custom_minimum_size", get_minimum_size(), 0.2) tween.tween_property(self, "custom_minimum_size", get_minimum_size(), 0.2)
text = "" text = ""
update_minimum_size() update_minimum_size()
visible = true visible = true
await tween.finished await tween.finished
text = tmp text = tmp

View File

@ -1,40 +1,40 @@
extends Control extends Control
func get_cards_by_scene_id(id: int) -> Array: func get_cards_by_scene_id(id: int) -> Array:
var output:Array var output:Array
var scene = get_child(id) var scene = get_child(id)
for i in range(scene.get_child_count()): for i in range(scene.get_child_count()):
output.append(scene.get_child(i)) output.append(scene.get_child(i))
for note in output[i].get_children(): for note in output[i].get_children():
if note is StickyNote: if note is StickyNote:
output[i].remove_child(note) output[i].remove_child(note)
for card in output: for card in output:
card.transform = Transform3D() card.transform = Transform3D()
for sticky_note in card.own_sticky_notes: for sticky_note in card.own_sticky_notes:
sticky_note.transform = Transform3D() sticky_note.transform = Transform3D()
return output return output
func get_cards_by_name_array(names: Array) -> Dictionary: func get_cards_by_name_array(names: Array) -> Dictionary:
var output:Dictionary = { var output:Dictionary = {
"cards": [], "cards": [],
"sticky_notes": [] "sticky_notes": []
} }
for scene in get_children(): for scene in get_children():
for card in scene.get_children(): for card in scene.get_children():
for sticky_note in card.get_children(): for sticky_note in card.get_children():
if names.has(sticky_note.name): if names.has(sticky_note.name):
sticky_note.transform = Transform3D() sticky_note.transform = Transform3D()
output['sticky_notes'].append(sticky_note) output['sticky_notes'].append(sticky_note)
if names.has(card.name): if names.has(card.name):
card.transform = Transform3D() card.transform = Transform3D()
output['cards'].append(card) output['cards'].append(card)
for child in card.get_children(): for child in card.get_children():
if child is StickyNote: if child is StickyNote:
child.reparent(self) child.reparent(self)
return output return output

1
src/dev-util/savegame.gd Normal file
View File

@ -0,0 +1 @@
extends Node

View File

@ -0,0 +1,6 @@
extends Node
func _ready() -> void:
var initialize_response: Dictionary = steamInitEx( true, 480 )
print("Did Steam initialize?: %s " % initialize_response)

View File

@ -4,69 +4,69 @@ const dev_board_pre = preload("res://dev-util/board of devs.tscn")
var dev_board: Control var dev_board: Control
func _ready(): func _ready():
dev_board = dev_board_pre.instantiate() dev_board = dev_board_pre.instantiate()
if $cards.get_child_count(false) > 0: if $cards.get_child_count(false) > 0:
$cards.get_children(false)[0].grab_focus() $cards.get_children(false)[0].grab_focus()
# Testing code # Testing code
for item in dev_board.find_children("*"): for item in dev_board.find_children("*"):
if item is Card: if item is Card:
spawn_card((item as Card).duplicate()) spawn_card((item as Card).duplicate())
elif item is StickyNote: elif item is StickyNote:
spawn_sticky_note((item as StickyNote).duplicate()) spawn_sticky_note((item as StickyNote).duplicate())
func _process(delta: float): func _process(delta: float):
pass pass
func spawn_card(card: Card): func spawn_card(card: Card):
$cards.add_child(card) $cards.add_child(card)
if $cards.get_child_count(false) == 1: if $cards.get_child_count(false) == 1:
$cards.get_children(false)[0].grab_focus() $cards.get_children(false)[0].grab_focus()
populate_focus_neighbors() populate_focus_neighbors()
func spawn_sticky_note(sticky_note: StickyNote): func spawn_sticky_note(sticky_note: StickyNote):
$sticky_notes.add_child(sticky_note) $sticky_notes.add_child(sticky_note)
populate_focus_neighbors() populate_focus_neighbors()
func populate_focus_neighbors(): func populate_focus_neighbors():
# TODO reorder cards based on position # TODO reorder cards based on position
if $cards.get_child_count(false) <= 0: if $cards.get_child_count(false) <= 0:
return return
var first_card = $cards.get_children(false)[0] var first_card = $cards.get_children(false)[0]
var first_sticky_note = $sticky_notes.get_children(false)[0] if $sticky_notes.get_child_count(false) > 0 else first_card var first_sticky_note = $sticky_notes.get_children(false)[0] if $sticky_notes.get_child_count(false) > 0 else first_card
var first_board_card = $mindmap.get_children(false)[0] if $mindmap.get_child_count(false) > 0 else first_card var first_board_card = $mindmap.get_children(false)[0] if $mindmap.get_child_count(false) > 0 else first_card
var cards = $cards.get_children(false) as Array[Card] var cards = $cards.get_children(false) as Array[Card]
for i in cards.size(): for i in cards.size():
var card = cards[i] var card = cards[i]
if card == first_card or not (card is Card): if card == first_card or not (card is Card):
continue continue
card.focus_neighbor_right = first_board_card # FIXME should be a valid focusable object, but it refuses card.focus_neighbor_right = first_board_card # FIXME should be a valid focusable object, but it refuses
card.focus_neighbor_left = first_sticky_note card.focus_neighbor_left = first_sticky_note
card.focus_neighbor_up = cards[(i - 1) % cards.size()] card.focus_neighbor_up = cards[(i - 1) % cards.size()]
card.focus_neighbor_down = cards[(i + 1) % cards.size()] card.focus_neighbor_down = cards[(i + 1) % cards.size()]
var sticky_notes = $sticky_notes.get_children(false) as Array[StickyNote] var sticky_notes = $sticky_notes.get_children(false) as Array[StickyNote]
for i in sticky_notes.size(): for i in sticky_notes.size():
var sticky_note = sticky_notes[i] var sticky_note = sticky_notes[i]
if not (sticky_note is StickyNote): if not (sticky_note is StickyNote):
continue continue
sticky_note.focus_neighbor_right = first_card sticky_note.focus_neighbor_right = first_card
sticky_note.focus_neighbor_left = first_board_card sticky_note.focus_neighbor_left = first_board_card
sticky_note.focus_neighbor_up = sticky_notes[(i - 1) % sticky_notes.size()] sticky_note.focus_neighbor_up = sticky_notes[(i - 1) % sticky_notes.size()]
sticky_note.focus_neighbor_down = sticky_notes[(i + 1) % sticky_notes.size()] sticky_note.focus_neighbor_down = sticky_notes[(i + 1) % sticky_notes.size()]
var board_items = $mindmap.get_children(false) as Array var board_items = $mindmap.get_children(false) as Array
for i in board_items.size(): for i in board_items.size():
var board_item = board_items[i] var board_item = board_items[i]
board_item.focus_neighbor_right = first_sticky_note board_item.focus_neighbor_right = first_sticky_note
board_item.focus_neighbor_left = first_card board_item.focus_neighbor_left = first_card
board_item.focus_neighbor_up = board_items[(i - 1) % board_items.size()] board_item.focus_neighbor_up = board_items[(i - 1) % board_items.size()]
board_item.focus_neighbor_down = board_items[(i + 1) % board_items.size()] board_item.focus_neighbor_down = board_items[(i + 1) % board_items.size()]

View File

@ -6,12 +6,12 @@ extends Area2D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
pass # Replace with function body. pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta): func _process(delta):
if get_overlapping_areas().size() > 0: if get_overlapping_areas().size() > 0:
for area in get_overlapping_areas(): for area in get_overlapping_areas():
var diff:Vector2 = position - area.position var diff:Vector2 = position - area.position
position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60)) position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60))

View File

@ -3,4 +3,3 @@ extends Area2D
var is_dragged: bool = false var is_dragged: bool = false
@export var direction: Vector2 = Vector2.ZERO @export var direction: Vector2 = Vector2.ZERO

View File

@ -9,30 +9,30 @@ extends PanelContainer
enum {NAVIGATE, ASSIGN, DRAG} enum {NAVIGATE, ASSIGN, DRAG}
var focus_stickies:bool = true: var focus_stickies:bool = true:
set(stickies): set(stickies):
if stickies and sticky_note_container.get_child_count() == 0: return if stickies and sticky_note_container.get_child_count() == 0: return
focus_stickies = stickies focus_stickies = stickies
if not current_context == ASSIGN: if not current_context == ASSIGN:
if stickies: if stickies:
current_sticky_note_id = current_sticky_note_id current_sticky_note_id = current_sticky_note_id
else: else:
current_dropzone_id = current_dropzone_id current_dropzone_id = current_dropzone_id
var has_stage = false: var has_stage = false:
set(focus): set(focus):
if focus: if focus:
has_stage = true has_stage = true
get_tree().call_group("interactables", "collapse") get_tree().call_group("interactables", "collapse")
else: else:
has_stage = false has_stage = false
if is_node_ready(): if is_node_ready():
if focus: if focus:
process_mode = Node.PROCESS_MODE_INHERIT process_mode = Node.PROCESS_MODE_INHERIT
else: else:
process_mode = Node.PROCESS_MODE_DISABLED process_mode = Node.PROCESS_MODE_DISABLED
visible = has_stage visible = has_stage
@onready var dropzone = $HBoxContainer/dropzone @onready var dropzone = $HBoxContainer/dropzone
var dropzone_size: Vector2 var dropzone_size: Vector2
@ -41,63 +41,63 @@ var dropzone_size: Vector2
@onready var board_of_devs = $"board of devs" @onready var board_of_devs = $"board of devs"
var base_sticky_note_panel: Panel var base_sticky_note_panel: Panel
@onready var current_context:int = NAVIGATE: @onready var current_context:int = NAVIGATE:
set(context): set(context):
if current_context == ASSIGN and !context == ASSIGN: if current_context == ASSIGN and !context == ASSIGN:
sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() sticky_note_container.get_child(current_sticky_note_id).clear_if_empty()
#match context: #match context:
# NAVIGATE: # NAVIGATE:
# _return_sticky_notes_to_panels() # _return_sticky_notes_to_panels()
# DRAG: # DRAG:
# pass # pass
# ASSIGN: # ASSIGN:
# pass # pass
current_context = context current_context = context
@onready var instructions = $instructions_panel/HBoxContainer/cards_remaining @onready var instructions = $instructions_panel/HBoxContainer/cards_remaining
var mementos_collected: int = 0: var mementos_collected: int = 0:
set(mementos): set(mementos):
mementos_collected = mementos mementos_collected = mementos
match mementos: match mementos:
1: 1:
instructions.text = "There are three Mementos left to find." instructions.text = "There are three Mementos left to find."
2: 2:
instructions.text = "You have collected half of the mementos." instructions.text = "You have collected half of the mementos."
3: 3:
instructions.text = "Find the last Memento to complete the Board." instructions.text = "Find the last Memento to complete the Board."
4: 4:
instructions.text = "Combine cards to order your thoughts." instructions.text = "Combine cards to order your thoughts."
@onready var currently_active_node: Area2D = null: @onready var currently_active_node: Area2D = null:
set(new_node): set(new_node):
if not currently_active_node == null: if not currently_active_node == null:
currently_active_node.highlighted = false currently_active_node.highlighted = false
currently_active_node = new_node currently_active_node = new_node
if not currently_active_node == null: if not currently_active_node == null:
currently_active_node.highlighted = true currently_active_node.highlighted = true
@onready var current_dropzone_id: int = 0: @onready var current_dropzone_id: int = 0:
set(new_id): set(new_id):
if new_id > dropzone.get_child_count() - 1: current_dropzone_id = 0 if new_id > dropzone.get_child_count() - 1: current_dropzone_id = 0
elif new_id < 0: current_dropzone_id = dropzone.get_child_count() - 1 elif new_id < 0: current_dropzone_id = dropzone.get_child_count() - 1
else: current_dropzone_id = new_id else: current_dropzone_id = new_id
if current_context == ASSIGN: if current_context == ASSIGN:
while not dropzone.get_child(current_dropzone_id) is Card: current_dropzone_id = (current_dropzone_id + 1) % dropzone.get_child_count() while not dropzone.get_child(current_dropzone_id) is Card: current_dropzone_id = (current_dropzone_id + 1) % dropzone.get_child_count()
dropzone.get_child(current_dropzone_id).preview_sticky_note(currently_active_node) dropzone.get_child(current_dropzone_id).preview_sticky_note(currently_active_node)
elif not focus_stickies: elif not focus_stickies:
currently_active_node = dropzone.get_child(current_dropzone_id) currently_active_node = dropzone.get_child(current_dropzone_id)
@onready var current_sticky_note_id: int = 0: @onready var current_sticky_note_id: int = 0:
set(new_id): set(new_id):
if sticky_note_container.get_child_count() <= 1: return if sticky_note_container.get_child_count() <= 1: return
elif new_id > sticky_note_container.get_child_count() - 1: current_sticky_note_id = 0 elif new_id > sticky_note_container.get_child_count() - 1: current_sticky_note_id = 0
elif new_id < 0: current_sticky_note_id = sticky_note_container.get_child_count() - 1 elif new_id < 0: current_sticky_note_id = sticky_note_container.get_child_count() - 1
else: current_sticky_note_id = new_id else: current_sticky_note_id = new_id
if current_context == ASSIGN: if current_context == ASSIGN:
_return_sticky_notes_to_panels() _return_sticky_notes_to_panels()
currently_active_node.preview_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note) currently_active_node.preview_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note)
else: else:
currently_active_node = sticky_note_container.get_child(current_sticky_note_id).get_child(1) currently_active_node = sticky_note_container.get_child(current_sticky_note_id).get_child(1)
var cache: Array = [] var cache: Array = []
@ -105,17 +105,17 @@ signal board_completed
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
base_sticky_note_panel = $HBoxContainer/ScrollContainer/VBoxContainer/Panel base_sticky_note_panel = $HBoxContainer/ScrollContainer/VBoxContainer/Panel
sticky_note_container.remove_child(base_sticky_note_panel) sticky_note_container.remove_child(base_sticky_note_panel)
dropzone_size = get_viewport_rect().size - Vector2(dropzone_padding + base_sticky_note_panel.custom_minimum_size.x, dropzone_padding) dropzone_size = get_viewport_rect().size - Vector2(dropzone_padding + base_sticky_note_panel.custom_minimum_size.x, dropzone_padding)
if get_parent() == get_tree().root: if get_parent() == get_tree().root:
populate_board(["c_void", 'c_joy', "p_wet", "p_thomas"]) populate_board(["c_void", 'c_joy', "p_wet", "p_thomas"])
populate_board(["c_fighting", 'c_hit', "p_girly", "p_vent"]) populate_board(["c_fighting", 'c_hit', "p_girly", "p_vent"])
mementos_collected = 2 mementos_collected = 2
has_stage = has_stage has_stage = has_stage
#func _process(delta): #func _process(delta):
# # drops dragged area when Mouse is no longer pressed. # # drops dragged area when Mouse is no longer pressed.
@ -124,228 +124,228 @@ func _ready():
# Will be used later to spawn Cards and Post-Its and remember them in the dictionary # Will be used later to spawn Cards and Post-Its and remember them in the dictionary
func populate_board(card_names: Array): func populate_board(card_names: Array):
mementos_collected += 1 mementos_collected += 1
var all_new:Dictionary = board_of_devs.get_cards_by_name_array(card_names) var all_new:Dictionary = board_of_devs.get_cards_by_name_array(card_names)
var new_cards:Array = all_new["cards"] var new_cards:Array = all_new["cards"]
var new_sticky_notes:Array = all_new["sticky_notes"] var new_sticky_notes:Array = all_new["sticky_notes"]
# spawning the cards and adding them to the dictionary # spawning the cards and adding them to the dictionary
for new_card in all_new["cards"]: for new_card in all_new["cards"]:
add_card(new_card) add_card(new_card)
for new_sticky_note in all_new["sticky_notes"]: # spawning a sticky note for new_sticky_note in all_new["sticky_notes"]: # spawning a sticky note
add_sticky_note(new_sticky_note) add_sticky_note(new_sticky_note)
#currently_active_node = area_dict["dropzone_content"][0] # set first Card as currently selected node by default #currently_active_node = area_dict["dropzone_content"][0] # set first Card as currently selected node by default
currently_active_node = dropzone.get_child(0) currently_active_node = dropzone.get_child(0)
func add_card(card: Card): func add_card(card: Card):
card.reparent(self) card.reparent(self)
card.position = Vector2(randi_range(dropzone_padding, dropzone_size.x), randi_range(dropzone_padding, dropzone_size.y)) card.position = Vector2(randi_range(dropzone_padding, dropzone_size.x), randi_range(dropzone_padding, dropzone_size.y))
insert_area(dropzone, card) insert_area(dropzone, card)
card.set_owner(self) card.set_owner(self)
card.is_dragable = true card.is_dragable = true
func add_sticky_note(sticky: StickyNote): func add_sticky_note(sticky: StickyNote):
var new_panel = base_sticky_note_panel.duplicate() var new_panel = base_sticky_note_panel.duplicate()
sticky_note_container.add_child(new_panel) sticky_note_container.add_child(new_panel)
new_panel.set_owner(self) new_panel.set_owner(self)
new_panel.attatch_sticky_note(sticky, false) new_panel.attatch_sticky_note(sticky, false)
# Checks if a Node is currently inside the dropzone # Checks if a Node is currently inside the dropzone
func is_in_dropzone(to_check: Node) -> bool: func is_in_dropzone(to_check: Node) -> bool:
return dropzone.get_rect().has_point(to_check.global_position) return dropzone.get_rect().has_point(to_check.global_position)
# called if a mouse button is pressed # called if a mouse button is pressed
func handle_mouse_button(to_handle: Area2D, input: InputEvent): func handle_mouse_button(to_handle: Area2D, input: InputEvent):
# No two areas can be dragged at the same time. # No two areas can be dragged at the same time.
# Make sure that only the same area is dragged. # Make sure that only the same area is dragged.
# Otherwise overlapping areas are dragged at the same time. # Otherwise overlapping areas are dragged at the same time.
if current_context == DRAG and to_handle != currently_active_node: if current_context == DRAG and to_handle != currently_active_node:
return return
currently_active_node = to_handle # update currently selected currently_active_node = to_handle # update currently selected
if input.is_action_pressed("mouse_left"): if input.is_action_pressed("mouse_left"):
to_handle.is_dragged = true to_handle.is_dragged = true
if to_handle is StickyNote: if to_handle is StickyNote:
if not to_handle.on_board: if not to_handle.on_board:
to_handle.reparent(dropzone) to_handle.reparent(dropzone)
to_handle.on_board = true to_handle.on_board = true
to_handle.owner = self to_handle.owner = self
current_context = DRAG current_context = DRAG
# when Drag stops ... # when Drag stops ...
if input.is_action_released("mouse_left"): if input.is_action_released("mouse_left"):
to_handle.is_dragged = false to_handle.is_dragged = false
if to_handle is StickyNote: if to_handle is StickyNote:
if is_in_dropzone(to_handle): if is_in_dropzone(to_handle):
if to_handle.has_overlapping_areas(): if to_handle.has_overlapping_areas():
for area in to_handle.get_overlapping_areas(): for area in to_handle.get_overlapping_areas():
if area is Card: if area is Card:
focus_stickies = false focus_stickies = false
if area.has_sticky_note_attached(): if area.has_sticky_note_attached():
to_handle = area.exchange_sticky_note_with(to_handle) to_handle = area.exchange_sticky_note_with(to_handle)
to_handle.reparent(dropzone) to_handle.reparent(dropzone)
to_handle.on_board = true to_handle.on_board = true
sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note = to_handle sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note = to_handle
to_handle.attached_to = sticky_note_container.get_child(current_sticky_note_id) to_handle.attached_to = sticky_note_container.get_child(current_sticky_note_id)
to_handle.reset_drag() to_handle.reset_drag()
current_context = NAVIGATE current_context = NAVIGATE
return return
else: else:
area.attach_sticky_note(to_handle) area.attach_sticky_note(to_handle)
if not sticky_note_container.get_child_count() == 0: if not sticky_note_container.get_child_count() == 0:
sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() sticky_note_container.get_child(current_sticky_note_id).clear_if_empty()
current_context = NAVIGATE current_context = NAVIGATE
if is_board_complete(): emit_signal("board_completed") if is_board_complete(): emit_signal("board_completed")
return return
else: else:
_return_sticky_notes_to_panels() _return_sticky_notes_to_panels()
return return
## Dropping Cards and Sticky Notes not causing a return condition above. ## Dropping Cards and Sticky Notes not causing a return condition above.
insert_area(dropzone, to_handle) insert_area(dropzone, to_handle)
current_context = NAVIGATE current_context = NAVIGATE
focus_stickies = false focus_stickies = false
current_dropzone_id = dropzone.get_children().find(to_handle) current_dropzone_id = dropzone.get_children().find(to_handle)
if to_handle is StickyNote: if to_handle is StickyNote:
to_handle.rotation = to_handle.base_rotation to_handle.rotation = to_handle.base_rotation
to_handle.scale = to_handle.base_scale to_handle.scale = to_handle.base_scale
if input.is_action_pressed("mouse_right") and current_context == DRAG: if input.is_action_pressed("mouse_right") and current_context == DRAG:
to_handle.reset_drag() to_handle.reset_drag()
func _return_sticky_notes_to_panels(): func _return_sticky_notes_to_panels():
for panel in sticky_note_container.get_children(): for panel in sticky_note_container.get_children():
panel.reclaim_sticky_note() panel.reclaim_sticky_note()
func is_board_complete() -> bool: func is_board_complete() -> bool:
if mementos_collected == 4: if mementos_collected == 4:
for card in dropzone.get_children(): for card in dropzone.get_children():
if card is Card: if card is Card:
if not card.has_sticky_note_attached(): if not card.has_sticky_note_attached():
return false return false
return true return true
return false return false
func is_board_lore() -> bool: func is_board_lore() -> bool:
for card in dropzone.get_children(): for card in dropzone.get_children():
if card.has_sticky_note_attached(): if card.has_sticky_note_attached():
if not card.current_sticky_note.is_in_group(card.name): return false if not card.current_sticky_note.is_in_group(card.name): return false
return true return true
# Mark area that was hovered over as currently selected # Mark area that was hovered over as currently selected
func handle_hover(to_handle: Area2D): func handle_hover(to_handle: Area2D):
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): return if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): return
currently_active_node = to_handle currently_active_node = to_handle
if is_in_dropzone(to_handle) or to_handle is Card: if is_in_dropzone(to_handle) or to_handle is Card:
if not (to_handle is StickyNote and !to_handle.on_board): if not (to_handle is StickyNote and !to_handle.on_board):
current_dropzone_id = dropzone.get_children().find(to_handle) current_dropzone_id = dropzone.get_children().find(to_handle)
focus_stickies = false focus_stickies = false
else: else:
current_sticky_note_id = sticky_note_container.get_children().find(to_handle.attached_to) current_sticky_note_id = sticky_note_container.get_children().find(to_handle.attached_to)
focus_stickies = true focus_stickies = true
# Adds a child at the correct child indext in an area # Adds a child at the correct child indext in an area
func insert_area(parent: Control, node: Area2D): func insert_area(parent: Control, node: Area2D):
var children:Array = parent.get_children() var children:Array = parent.get_children()
var i = 0 var i = 0
if not node in parent.get_children(): if not node in parent.get_children():
node.reparent(parent) node.reparent(parent)
if node is StickyNote: if node is StickyNote:
node.on_board = true node.on_board = true
node.owner = self node.owner = self
if children.size() > 0: if children.size() > 0:
children.erase(node) children.erase(node)
while children[i].global_position.y < node.global_position.y and i+1 < children.size(): while children[i].global_position.y < node.global_position.y and i+1 < children.size():
i+=1 i+=1
parent.move_child(node, i) parent.move_child(node, i)
# Takes the inputs for control inputs # Takes the inputs for control inputs
func _input(event): func _input(event):
if event.is_action_pressed("ui_cancel"): if event.is_action_pressed("ui_cancel"):
State.leave_stage(self) State.leave_stage(self)
# Return, if the input is a mouse event (mouse events are handled separately) # Return, if the input is a mouse event (mouse events are handled separately)
if event is InputEventMouse or !has_stage or not is_instance_valid(currently_active_node): return if event is InputEventMouse or !has_stage or not is_instance_valid(currently_active_node): return
if current_context != DRAG: if current_context != DRAG:
if event.is_action_pressed("ui_up"): if event.is_action_pressed("ui_up"):
if focus_stickies: if focus_stickies:
current_sticky_note_id -= 1 current_sticky_note_id -= 1
else: else:
current_dropzone_id -= 1 current_dropzone_id -= 1
elif event.is_action_pressed("ui_down"): # down to select an element beneath elif event.is_action_pressed("ui_down"): # down to select an element beneath
if focus_stickies: if focus_stickies:
current_sticky_note_id += 1 current_sticky_note_id += 1
else: else:
current_dropzone_id += 1 current_dropzone_id += 1
elif event.is_action_pressed("ui_right"): # left to switch context to the left elif event.is_action_pressed("ui_right"): # left to switch context to the left
if not focus_stickies: if not focus_stickies:
if current_context == NAVIGATE: if current_context == NAVIGATE:
focus_stickies = true focus_stickies = true
elif current_context == ASSIGN: elif current_context == ASSIGN:
current_context = NAVIGATE current_context = NAVIGATE
elif event.is_action_pressed("ui_left"): # right to switch context to the right elif event.is_action_pressed("ui_left"): # right to switch context to the right
if focus_stickies: if focus_stickies:
if current_context == NAVIGATE: if current_context == NAVIGATE:
focus_stickies = false focus_stickies = false
elif current_context == ASSIGN: elif current_context == ASSIGN:
current_context = NAVIGATE current_context = NAVIGATE
elif event.is_action_pressed("ui_accept"): # select the selected note it elif event.is_action_pressed("ui_accept"): # select the selected note it
var card:Card var card:Card
if dropzone.get_child(current_dropzone_id) is Card: if dropzone.get_child(current_dropzone_id) is Card:
card = dropzone.get_child(current_dropzone_id) card = dropzone.get_child(current_dropzone_id)
if current_context == ASSIGN: # to assign it to a card if current_context == ASSIGN: # to assign it to a card
if card.has_sticky_note_attached(): if card.has_sticky_note_attached():
currently_active_node = card.exchange_sticky_note_with(currently_active_node) currently_active_node = card.exchange_sticky_note_with(currently_active_node)
current_dropzone_id = find_first_free_card() current_dropzone_id = find_first_free_card()
else: else:
card.attach_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note) card.attach_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note)
current_context = NAVIGATE current_context = NAVIGATE
focus_stickies = false focus_stickies = false
if is_board_complete(): emit_signal("board_completed") if is_board_complete(): emit_signal("board_completed")
else: else:
if !focus_stickies and card.has_sticky_note_attached(): if !focus_stickies and card.has_sticky_note_attached():
currently_active_node = card.remove_sticky_note() currently_active_node = card.remove_sticky_note()
add_sticky_note(currently_active_node) add_sticky_note(currently_active_node)
current_dropzone_id = -1 current_dropzone_id = -1
else: current_dropzone_id = find_first_free_card() else: current_dropzone_id = find_first_free_card()
current_context = ASSIGN current_context = ASSIGN
focus_stickies = !focus_stickies focus_stickies = !focus_stickies
if focus_stickies: if focus_stickies:
current_sticky_note_id = current_sticky_note_id current_sticky_note_id = current_sticky_note_id
else: else:
current_dropzone_id = current_dropzone_id current_dropzone_id = current_dropzone_id
# move the note it so it floats next to the card where it should be attached # move the note it so it floats next to the card where it should be attached
func _select_card_for_assigning(sticky_note: Area2D, card: Area2D): func _select_card_for_assigning(sticky_note: Area2D, card: Area2D):
sticky_note.tween_transform_to(card.get_child(3).global_position) sticky_note.tween_transform_to(card.get_child(3).global_position)
func on_scene_skipped(i: int): func on_scene_skipped(i: int):
mementos_collected += i mementos_collected += i
func claim_focus(): func claim_focus():
State.pass_stage_to(self) State.pass_stage_to(self)
func find_first_free_card() -> int: func find_first_free_card() -> int:
for i in range(dropzone.get_child_count()): for i in range(dropzone.get_child_count()):
# start searching at the current location, use modulo to avoid getting out of array bounds # start searching at the current location, use modulo to avoid getting out of array bounds
if !dropzone.get_child((i+current_dropzone_id)%dropzone.get_child_count()).has_sticky_note_attached(): if !dropzone.get_child((i+current_dropzone_id)%dropzone.get_child_count()).has_sticky_note_attached():
return (i+current_dropzone_id)%dropzone.get_child_count() return (i+current_dropzone_id)%dropzone.get_child_count()
return -1 return -1
func on_sticky_panel_cleared(): func on_sticky_panel_cleared():
if current_sticky_note_id == sticky_note_container.get_child_count() - 1: if current_sticky_note_id == sticky_note_container.get_child_count() - 1:
current_sticky_note_id -= 1 current_sticky_note_id -= 1

View File

@ -12,204 +12,204 @@ var wiggle_tween
var scale_tween var scale_tween
var transfor_arr: Array[Transform2D] = [ var transfor_arr: Array[Transform2D] = [
Transform2D(0.9, Vector2(-125, -83)), Transform2D(0.9, Vector2(-125, -83)),
Transform2D(-0.3, Vector2(-126, -75)), Transform2D(-0.3, Vector2(-126, -75)),
Transform2D(-0.3, Vector2(-126, -74)), Transform2D(-0.3, Vector2(-126, -74)),
Transform2D(-0.3, Vector2(-126, -73)), Transform2D(-0.3, Vector2(-126, -73)),
Transform2D(0.5, Vector2(-126, -77)) Transform2D(0.5, Vector2(-126, -77))
] ]
@export var text: String = "" : @export var text: String = "" :
set(value): set(value):
text = value text = value
if get_children() != [] or Engine.is_editor_hint(): if get_children() != [] or Engine.is_editor_hint():
$Label.text = value $Label.text = value
var curr_frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation) var curr_frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation)
$BackgroundSprite.frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation) $BackgroundSprite.frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation)
$Label.rotation = deg_to_rad(transfor_arr[curr_frame].get_rotation()) $Label.rotation = deg_to_rad(transfor_arr[curr_frame].get_rotation())
$Label.position = transfor_arr[curr_frame].origin $Label.position = transfor_arr[curr_frame].origin
if !Engine.is_editor_hint(): if !Engine.is_editor_hint():
wiggle_pos = float(text.hash() % 100) wiggle_pos = float(text.hash() % 100)
_handle_wiggle(0) _handle_wiggle(0)
@export var wiggle_strength: float = 0.2 @export var wiggle_strength: float = 0.2
@export var wiggle_speed: float = 5 @export var wiggle_speed: float = 5
@export_range(1, 2) var scale_bump: float = 1.05 @export_range(1, 2) var scale_bump: float = 1.05
@export_range(1.0, 10.0) var bounce_speed: float = 5 @export_range(1.0, 10.0) var bounce_speed: float = 5
@export var highlighted: bool = false: @export var highlighted: bool = false:
set(highlight): set(highlight):
if highlight != highlighted: if highlight != highlighted:
highlighted = highlight highlighted = highlight
if is_inside_tree() and is_node_ready(): if is_inside_tree() and is_node_ready():
if scale_tween: scale_tween.kill() if scale_tween: scale_tween.kill()
if wiggle_tween: wiggle_tween.kill() if wiggle_tween: wiggle_tween.kill()
if highlighted: if highlighted:
scale_tween = get_tree().create_tween() scale_tween = get_tree().create_tween()
scale_tween.tween_property(self, "scale", Vector2(scale_bump, scale_bump), 0.1) scale_tween.tween_property(self, "scale", Vector2(scale_bump, scale_bump), 0.1)
wiggle_tween = get_tree().create_tween() wiggle_tween = get_tree().create_tween()
wiggle_tween.tween_property(self, "wiggle_intensity", 1, 0.2) wiggle_tween.tween_property(self, "wiggle_intensity", 1, 0.2)
else: else:
scale_tween = get_tree().create_tween() scale_tween = get_tree().create_tween()
scale_tween.tween_property(self, "scale", Vector2(1, 1), 0.3) scale_tween.tween_property(self, "scale", Vector2(1, 1), 0.3)
wiggle_tween = get_tree().create_tween() wiggle_tween = get_tree().create_tween()
wiggle_tween.tween_property(self, "wiggle_intensity", 0, 0.5) wiggle_tween.tween_property(self, "wiggle_intensity", 0, 0.5)
else: else:
if highlighted: if highlighted:
scale = Vector2(scale_bump, scale_bump) scale = Vector2(scale_bump, scale_bump)
wiggle_intensity = 1 wiggle_intensity = 1
else: else:
scale = Vector2(1,1) scale = Vector2(1,1)
wiggle_intensity = 0 wiggle_intensity = 0
@export var voice_line: AudioStream = null @export var voice_line: AudioStream = null
@export var is_dragable: bool = false @export var is_dragable: bool = false
@onready var diameter = $CollisionShape2D.shape.height @onready var diameter = $CollisionShape2D.shape.height
@onready var sticky_note_anchor: Node2D = $"sticky note anchor" @onready var sticky_note_anchor: Node2D = $"sticky note anchor"
var is_dragged: bool = false: var is_dragged: bool = false:
set(dragged): set(dragged):
is_dragged = dragged is_dragged = dragged
z_index = int(dragged) z_index = int(dragged)
var is_mouse_entered: bool = false var is_mouse_entered: bool = false
var mouse_offset: Vector2 var mouse_offset: Vector2
func _ready(): func _ready():
_handle_wiggle(0) _handle_wiggle(0)
if not Engine.is_editor_hint() and is_inside_tree(): if not Engine.is_editor_hint() and is_inside_tree():
for sticky_note in self.get_children(): for sticky_note in self.get_children():
if sticky_note is StickyNote: self.own_sticky_notes.append(sticky_note as StickyNote) if sticky_note is StickyNote: self.own_sticky_notes.append(sticky_note as StickyNote)
for sticky_note in get_tree().get_nodes_in_group(name): for sticky_note in get_tree().get_nodes_in_group(name):
if sticky_note is StickyNote: self.compatible_sticky_notes.append(sticky_note as StickyNote) if sticky_note is StickyNote: self.compatible_sticky_notes.append(sticky_note as StickyNote)
compatible_sticky_notes.append_array(own_sticky_notes) compatible_sticky_notes.append_array(own_sticky_notes)
if own_sticky_notes.size() == 2: if own_sticky_notes.size() == 2:
own_sticky_notes[0].sibling = own_sticky_notes[1] own_sticky_notes[0].sibling = own_sticky_notes[1]
own_sticky_notes[1].sibling = own_sticky_notes[0] own_sticky_notes[1].sibling = own_sticky_notes[0]
$BackgroundSprite.frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation) $BackgroundSprite.frame = text.hash() % $BackgroundSprite.sprite_frames.get_frame_count($BackgroundSprite.animation)
$Label.text = self.text $Label.text = self.text
$Label.theme = State.current_main_theme $Label.theme = State.current_main_theme
State.theme_changed.connect(func change_theme(new_theme): $Label.theme = new_theme) State.theme_changed.connect(func change_theme(new_theme): $Label.theme = new_theme)
wiggle_pos = float(text.hash() % 100) wiggle_pos = float(text.hash() % 100)
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
_handle_wiggle(0) _handle_wiggle(0)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if highlighted: if highlighted:
_handle_wiggle(delta) _handle_wiggle(delta)
if get_overlapping_areas().size() > 0 and is_dragable: if get_overlapping_areas().size() > 0 and is_dragable:
for area in get_overlapping_areas(): for area in get_overlapping_areas():
if area is Card or area is CardCollider: if area is Card or area is CardCollider:
if area is CardCollider: if area is CardCollider:
position += area.direction * delta position += area.direction * delta
elif not (area.highlighted or self.highlighted) and area.is_dragable: elif not (area.highlighted or self.highlighted) and area.is_dragable:
var diff:Vector2 = position - area.position var diff:Vector2 = position - area.position
position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60)) position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60))
_move_card() _move_card()
func get_text() -> String: func get_text() -> String:
return $Label.text return $Label.text
func _handle_wiggle(delta): func _handle_wiggle(delta):
wiggle_pos += delta * wiggle_speed * wiggle_intensity wiggle_pos += delta * wiggle_speed * wiggle_intensity
rotation = noise.get_noise_1d(wiggle_pos)*wiggle_strength rotation = noise.get_noise_1d(wiggle_pos)*wiggle_strength
## Deprecated ## Deprecated
func replace_with(card: Card): func replace_with(card: Card):
self.text = card.text self.text = card.text
self.compatible_sticky_notes = card.compatible_sticky_notes self.compatible_sticky_notes = card.compatible_sticky_notes
self.own_sticky_notes = card.own_sticky_notes self.own_sticky_notes = card.own_sticky_notes
self.voice_line = card.voice_line self.voice_line = card.voice_line
self.name = card.name self.name = card.name
func _on_focus_entered(): func _on_focus_entered():
print(self, "is focused") print(self, "is focused")
func _on_focus_exited(): func _on_focus_exited():
print(self, "is not focused") print(self, "is not focused")
func _on_mouse_entered(): func _on_mouse_entered():
is_mouse_entered = true is_mouse_entered = true
if not Input.is_action_pressed("mouse_left"): if not Input.is_action_pressed("mouse_left"):
# Do nothing if mouse hovers over sticky_note # Do nothing if mouse hovers over sticky_note
if has_sticky_note_attached(): if has_sticky_note_attached():
if get_child(-1).highlighted: if get_child(-1).highlighted:
return return
highlighted = true highlighted = true
if "handle_hover" in owner: if "handle_hover" in owner:
owner.handle_hover(self) owner.handle_hover(self)
func _on_mouse_exited(): func _on_mouse_exited():
highlighted = false highlighted = false
is_mouse_entered = false is_mouse_entered = false
func _on_input_event(viewport, event, shape_idx): func _on_input_event(viewport, event, shape_idx):
if event is InputEventMouseMotion: if event is InputEventMouseMotion:
_move_card() _move_card()
if event is InputEventMouseButton: if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT: if event.button_index == MOUSE_BUTTON_LEFT:
if "handle_mouse_button" in owner: if "handle_mouse_button" in owner:
mouse_offset = (get_viewport().get_mouse_position() - position) mouse_offset = (get_viewport().get_mouse_position() - position)
if highlighted: if highlighted:
owner.handle_mouse_button(self, event) owner.handle_mouse_button(self, event)
func _move_card(): func _move_card():
if is_dragged: if is_dragged:
position += (get_viewport().get_mouse_position() - position) - mouse_offset position += (get_viewport().get_mouse_position() - position) - mouse_offset
func has_sticky_note_attached() -> bool: func has_sticky_note_attached() -> bool:
return get_child(-1) is StickyNote return get_child(-1) is StickyNote
func preview_sticky_note(sticky_note: StickyNote): func preview_sticky_note(sticky_note: StickyNote):
sticky_note.reparent(self.get_parent()) sticky_note.reparent(self.get_parent())
sticky_note.owner = owner sticky_note.owner = owner
sticky_note.tween_transform_to(Transform2D(0, sticky_note_anchor.global_position + 0 * Vector2(sticky_note.diameter, sticky_note.diameter))) sticky_note.tween_transform_to(Transform2D(0, sticky_note_anchor.global_position + 0 * Vector2(sticky_note.diameter, sticky_note.diameter)))
func attach_sticky_note(sticky_note: StickyNote) -> bool: func attach_sticky_note(sticky_note: StickyNote) -> bool:
if has_sticky_note_attached(): if has_sticky_note_attached():
return false return false
sticky_note.reparent(self) sticky_note.reparent(self)
sticky_note.owner = self.owner sticky_note.owner = self.owner
sticky_note.position = sticky_note_anchor.position sticky_note.position = sticky_note_anchor.position
sticky_note.on_board = false sticky_note.on_board = false
current_sticky_note = sticky_note current_sticky_note = sticky_note
sticky_note.attached_to = self sticky_note.attached_to = self
return true return true
func remove_sticky_note() -> StickyNote: func remove_sticky_note() -> StickyNote:
if not is_instance_valid(current_sticky_note): return null if not is_instance_valid(current_sticky_note): return null
var former_child:StickyNote = current_sticky_note var former_child:StickyNote = current_sticky_note
current_sticky_note = null current_sticky_note = null
former_child.reparent(get_parent()) former_child.reparent(get_parent())
former_child.owner = self.owner former_child.owner = self.owner
former_child.on_board = true former_child.on_board = true
former_child.attached_to = null former_child.attached_to = null
return former_child return former_child
func exchange_sticky_note_with(new_note: StickyNote) -> StickyNote: func exchange_sticky_note_with(new_note: StickyNote) -> StickyNote:
var tmp = remove_sticky_note() var tmp = remove_sticky_note()
attach_sticky_note(new_note) attach_sticky_note(new_note)
return tmp return tmp
## TODO why does this exist? ## TODO why does this exist?
func check_hover(): func check_hover():
if is_mouse_entered: if is_mouse_entered:
_on_mouse_entered() _on_mouse_entered()
func reclaim_sticky_note(): func reclaim_sticky_note():
current_sticky_note.on_board = false current_sticky_note.on_board = false
current_sticky_note.tween_transform_to(sticky_note_anchor.global_transform) current_sticky_note.tween_transform_to(sticky_note_anchor.global_transform)
await current_sticky_note.transform_tween_finished await current_sticky_note.transform_tween_finished
current_sticky_note.reparent(self) current_sticky_note.reparent(self)
current_sticky_note.owner = self.owner current_sticky_note.owner = self.owner

View File

@ -6,46 +6,46 @@ var attached_sticky_note: StickyNote
@onready var ancor = $"sticky-note_anchor" @onready var ancor = $"sticky-note_anchor"
func _ready(): func _ready():
ancor.position = Vector2(ancor.position.x, 0) ancor.position = Vector2(ancor.position.x, 0)
custom_minimum_size = Vector2(custom_minimum_size.x, 0) custom_minimum_size = Vector2(custom_minimum_size.x, 0)
func attatch_sticky_note(attatchment: StickyNote, tween:bool = true): func attatch_sticky_note(attatchment: StickyNote, tween:bool = true):
attatchment.on_board = false attatchment.on_board = false
if tween: if tween:
var height_tween: Tween = create_tween() var height_tween: Tween = create_tween()
height_tween.tween_property(self, "custom_minimum_size", minimum_size, 0.3) height_tween.tween_property(self, "custom_minimum_size", minimum_size, 0.3)
height_tween.tween_property(ancor, "position", Vector2(ancor.position.x, minimum_size.y/2), 0.3) height_tween.tween_property(ancor, "position", Vector2(ancor.position.x, minimum_size.y/2), 0.3)
attatchment.tween_transform_to(ancor.global_position) attatchment.tween_transform_to(ancor.global_position)
await attatchment.transform_tween_finished await attatchment.transform_tween_finished
else: else:
custom_minimum_size = minimum_size custom_minimum_size = minimum_size
ancor.position = Vector2(ancor.position.x, minimum_size.y/2) ancor.position = Vector2(ancor.position.x, minimum_size.y/2)
attatchment.reparent(self) attatchment.reparent(self)
attached_sticky_note = attatchment attached_sticky_note = attatchment
attatchment.owner = self.owner attatchment.owner = self.owner
attatchment.attached_to = self attatchment.attached_to = self
attatchment.transform = ancor.transform attatchment.transform = ancor.transform
func reclaim_sticky_note(): func reclaim_sticky_note():
if is_empty() and attached_sticky_note.on_board == true: if is_empty() and attached_sticky_note.on_board == true:
attached_sticky_note.on_board = false attached_sticky_note.on_board = false
attached_sticky_note.tween_transform_to(ancor.global_transform) attached_sticky_note.tween_transform_to(ancor.global_transform)
await attached_sticky_note.transform_tween_finished await attached_sticky_note.transform_tween_finished
attached_sticky_note.reparent(self) attached_sticky_note.reparent(self)
attached_sticky_note.owner = self.owner attached_sticky_note.owner = self.owner
func clear_if_empty(): func clear_if_empty():
if !is_empty(): return if !is_empty(): return
if attached_sticky_note.attached_to == self: attached_sticky_note.attached_to = null if attached_sticky_note.attached_to == self: attached_sticky_note.attached_to = null
var height_tween: Tween = create_tween() var height_tween: Tween = create_tween()
height_tween.tween_property(self, "custom_minimum_size", Vector2.ZERO, 0.3) height_tween.tween_property(self, "custom_minimum_size", Vector2.ZERO, 0.3)
await height_tween.finished await height_tween.finished
owner.on_sticky_panel_cleared() owner.on_sticky_panel_cleared()
self.free() self.free()
func replace_sticky_note_with(new_sticky_note: StickyNote): func replace_sticky_note_with(new_sticky_note: StickyNote):
if is_empty(): if is_empty():
attached_sticky_note = new_sticky_note attached_sticky_note = new_sticky_note
func is_empty() -> bool: func is_empty() -> bool:
return get_child_count() == 1 return get_child_count() == 1

View File

@ -9,47 +9,47 @@ var modulate_tween
signal transform_tween_finished signal transform_tween_finished
@export var text: String = "" : @export var text: String = "" :
set (value): set (value):
if is_inside_tree() or Engine.is_editor_hint(): if is_inside_tree() or Engine.is_editor_hint():
$Content/Label.text = value $Content/Label.text = value
$Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation) $Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation)
text = value text = value
@export var shift_by: Vector2 = Vector2(-32, 0) @export var shift_by: Vector2 = Vector2(-32, 0)
@export_color_no_alpha var highlight_color: Color = Color(1.5, 1.5, 1.5) @export_color_no_alpha var highlight_color: Color = Color(1.5, 1.5, 1.5)
@export var highlighted: bool = false: @export var highlighted: bool = false:
set(highlight): set(highlight):
if highlight != highlighted: if highlight != highlighted:
highlighted = highlight highlighted = highlight
if is_inside_tree() and is_node_ready(): if is_inside_tree() and is_node_ready():
if modulate_tween: modulate_tween.kill() if modulate_tween: modulate_tween.kill()
if shift_tween: shift_tween.kill() if shift_tween: shift_tween.kill()
if highlighted: if highlighted:
modulate_tween = get_tree().create_tween() modulate_tween = get_tree().create_tween()
modulate_tween.tween_property(self, "modulate", highlight_color, 0.1) modulate_tween.tween_property(self, "modulate", highlight_color, 0.1)
shift_tween = get_tree().create_tween() shift_tween = get_tree().create_tween()
shift_tween.tween_property($Content, "position", shift_by, 0.2) shift_tween.tween_property($Content, "position", shift_by, 0.2)
else: else:
modulate_tween = get_tree().create_tween() modulate_tween = get_tree().create_tween()
modulate_tween.tween_property(self, "modulate", Color(1, 1, 1), 0.3) modulate_tween.tween_property(self, "modulate", Color(1, 1, 1), 0.3)
shift_tween = get_tree().create_tween() shift_tween = get_tree().create_tween()
shift_tween.tween_property($Content, "position", Vector2.ZERO, 0.5) shift_tween.tween_property($Content, "position", Vector2.ZERO, 0.5)
else: else:
if highlighted: if highlighted:
modulate = Color(1, 1, 1) modulate = Color(1, 1, 1)
else: else:
modulate = Color(1, 1, 1) modulate = Color(1, 1, 1)
@export var voice_line: AudioStream = null @export var voice_line: AudioStream = null
@export var is_dragable: bool = false @export var is_dragable: bool = false
@onready var base_rotation = rotation @onready var base_rotation = rotation
@onready var base_scale = scale @onready var base_scale = scale
var is_dragged: bool = false: var is_dragged: bool = false:
set(dragged): set(dragged):
is_dragged = dragged is_dragged = dragged
z_index = int(dragged) z_index = int(dragged)
var initial_drag_position: Vector2 var initial_drag_position: Vector2
var mouse_diff: Vector2 var mouse_diff: Vector2
@ -60,78 +60,78 @@ var on_board: bool = false
var attached_to: Node = null var attached_to: Node = null
func _ready() -> void: func _ready() -> void:
$Content/Label.text = self.text $Content/Label.text = self.text
$Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation) $Content/BackgroundSprite.frame = text.hash() % $Content/BackgroundSprite.sprite_frames.get_frame_count($Content/BackgroundSprite.animation)
$Content/Label.theme = State.current_main_theme $Content/Label.theme = State.current_main_theme
State.theme_changed.connect(func change_theme(new_theme): $Content/Label.theme = new_theme) State.theme_changed.connect(func change_theme(new_theme): $Content/Label.theme = new_theme)
func replace_with(sticky_note: StickyNote): func replace_with(sticky_note: StickyNote):
self.text = sticky_note.text self.text = sticky_note.text
self.voice_line = sticky_note.voice_line self.voice_line = sticky_note.voice_line
self.sibling = sticky_note.sibling self.sibling = sticky_note.sibling
self.name = sticky_note.name self.name = sticky_note.name
for group in self.get_groups(): for group in self.get_groups():
self.remove_from_group(group) self.remove_from_group(group)
for group in sticky_note.get_groups(): for group in sticky_note.get_groups():
self.add_to_group(group) self.add_to_group(group)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if get_overlapping_areas().size() > 0 and is_dragable and on_board: if get_overlapping_areas().size() > 0 and is_dragable and on_board:
for area in get_overlapping_areas(): for area in get_overlapping_areas():
if area is Card or area is CardCollider: if area is Card or area is CardCollider:
if area is CardCollider: if area is CardCollider:
position += area.direction * delta position += area.direction * delta
elif not area.highlighted or self.highlighted: elif not area.highlighted or self.highlighted:
var diff:Vector2 = position - area.position var diff:Vector2 = position - area.position
position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60)) position -= diff.normalized() * ((diff.length()-diameter)/diameter) * bounce_speed * (delta/(1.0/60))
_move_sticky_note() _move_sticky_note()
func _on_focus_entered(): func _on_focus_entered():
print(self, "is focused") print(self, "is focused")
func _on_focus_exited(): func _on_focus_exited():
print(self, "is not focused") print(self, "is not focused")
func _on_mouse_entered(): func _on_mouse_entered():
if not Input.is_action_pressed("mouse_left"): if not Input.is_action_pressed("mouse_left"):
highlighted = true highlighted = true
if "handle_hover" in owner: if "handle_hover" in owner:
owner.handle_hover(self) owner.handle_hover(self)
func _on_mouse_exited(): func _on_mouse_exited():
highlighted = false highlighted = false
if is_sticky_note_attached() and "check_hover" in get_parent(): if is_sticky_note_attached() and "check_hover" in get_parent():
get_parent().check_hover() get_parent().check_hover()
func _on_input_event(viewport, event, shape_idx): func _on_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton: if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT: if event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT:
if "handle_mouse_button" in owner: if "handle_mouse_button" in owner:
mouse_diff = get_viewport().get_mouse_position() mouse_diff = get_viewport().get_mouse_position()
initial_drag_position = global_position initial_drag_position = global_position
owner.handle_mouse_button(self, event) owner.handle_mouse_button(self, event)
func _move_sticky_note(): func _move_sticky_note():
if is_dragged: if is_dragged:
position = initial_drag_position + get_viewport().get_mouse_position() - mouse_diff position = initial_drag_position + get_viewport().get_mouse_position() - mouse_diff
func is_sticky_note_attached() -> bool: func is_sticky_note_attached() -> bool:
# there is probably a nicer way to do this # there is probably a nicer way to do this
return self.get_parent().get_parent() is Card return self.get_parent().get_parent() is Card
func tween_transform_to(target: Transform2D): func tween_transform_to(target: Transform2D):
var transform_tween: Tween = create_tween() var transform_tween: Tween = create_tween()
transform_tween.tween_property(self, "transform", target, 0.25) transform_tween.tween_property(self, "transform", target, 0.25)
await transform_tween.finished await transform_tween.finished
emit_signal("transform_tween_finished") emit_signal("transform_tween_finished")
func reset_drag(): func reset_drag():
if attached_to != null: if attached_to != null:
attached_to.reclaim_sticky_note() attached_to.reclaim_sticky_note()
func _enter_tree(): func _enter_tree():
print("enter_tree") print("enter_tree")

View File

@ -2,57 +2,57 @@ extends CenterContainer
#fixme INI is probably redundant. #fixme INI is probably redundant.
enum { enum {
INI, INI,
CARDS, CARDS,
CARDS_SELECTED, CARDS_SELECTED,
TRANSITION, TRANSITION,
POSTS, POSTS,
POSTS_SELECTED, POSTS_SELECTED,
DONE DONE
} }
@onready var source_board:Control = $"board of devs" @onready var source_board:Control = $"board of devs"
var has_stage = false: var has_stage = false:
set(focus): set(focus):
if not focus == has_stage: if not focus == has_stage:
if focus: if focus:
process_mode = Node.PROCESS_MODE_INHERIT process_mode = Node.PROCESS_MODE_INHERIT
self.show() self.show()
self.mouse_filter = Control.MOUSE_FILTER_PASS self.mouse_filter = Control.MOUSE_FILTER_PASS
else: else:
self.mouse_filter = Control.MOUSE_FILTER_IGNORE self.mouse_filter = Control.MOUSE_FILTER_IGNORE
self.hide() self.hide()
process_mode = Node.PROCESS_MODE_DISABLED process_mode = Node.PROCESS_MODE_DISABLED
has_stage = focus has_stage = focus
var _input_locked = true var _input_locked = true
var selection_state = INI: var selection_state = INI:
set(state): set(state):
selection_state = state selection_state = state
_input_locked = !(state == CARDS or state == POSTS) _input_locked = !(state == CARDS or state == POSTS)
if state == CARDS_SELECTED: if state == CARDS_SELECTED:
var tween = get_tree().create_tween() var tween = get_tree().create_tween()
tween.tween_property($thought_prompt, "modulate", Color(1, 1, 1, 0), 0.5) tween.tween_property($thought_prompt, "modulate", Color(1, 1, 1, 0), 0.5)
elif state == DONE: elif state == DONE:
reset() reset()
var anim_players:Array[AnimationPlayer] = [] var anim_players:Array[AnimationPlayer] = []
var curr_selection_id: int = -1: var curr_selection_id: int = -1:
set(new_id): set(new_id):
if selection_state == CARDS or selection_state == POSTS: if selection_state == CARDS or selection_state == POSTS:
if not curr_selection_id == -1: options[curr_selection_id].highlighted = false if not curr_selection_id == -1: options[curr_selection_id].highlighted = false
if new_id > options.size() -1: curr_selection_id = 0 if new_id > options.size() -1: curr_selection_id = 0
elif new_id < 0: curr_selection_id = options.size() - 1 elif new_id < 0: curr_selection_id = options.size() - 1
else: curr_selection_id = new_id else: curr_selection_id = new_id
options[curr_selection_id].highlighted = true options[curr_selection_id].highlighted = true
else: else:
curr_selection_id = new_id curr_selection_id = new_id
print(curr_selection_id) print(curr_selection_id)
var output:Array = [] var output:Array = []
var options:Array = [] var options:Array = []
@ -61,166 +61,165 @@ signal cards_picked(Array)
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
reset() reset()
func reset(): func reset():
output = [] output = []
options = [] options = []
anim_players = [] anim_players = []
var card_controls = $cards.get_children() var card_controls = $cards.get_children()
for control in card_controls: for control in card_controls:
options.append(control.get_child(1)) options.append(control.get_child(1))
anim_players.append(control.get_child(0)) anim_players.append(control.get_child(0))
curr_selection_id = 0 curr_selection_id = 0
for player in anim_players: player.play("reveal") for player in anim_players: player.play("reveal")
func fill_card_slots(id: int): func fill_card_slots(id: int):
var new_cards = source_board.get_cards_by_scene_id(id) var new_cards = source_board.get_cards_by_scene_id(id)
for i in range(new_cards.size()): for i in range(new_cards.size()):
$cards.get_child(i).remove_child($cards.get_child(i).get_child(1)) $cards.get_child(i).remove_child($cards.get_child(i).get_child(1))
var new_card = new_cards[i] var new_card = new_cards[i]
new_card.reparent($cards.get_child(i), false) new_card.reparent($cards.get_child(i), false)
new_card.owner = self new_card.owner = self
new_card.connect("mouse_entered", Callable(self, "get_highlight")) new_card.connect("mouse_entered", Callable(self, "get_highlight"))
options.append(new_card) options.append(new_card)
anim_players.append($cards.get_child(i).get_child(0)) anim_players.append($cards.get_child(i).get_child(0))
reset() reset()
func fill_post_slots(): func fill_post_slots():
var sticky_notes: Array[StickyNote] = [] var sticky_notes: Array[StickyNote] = []
for card in output: for card in output:
sticky_notes.append_array(card.own_sticky_notes) sticky_notes.append_array(card.own_sticky_notes)
sticky_notes.shuffle() sticky_notes.shuffle()
options = [] options = []
for ancor in $sticky_notes.get_children(): for ancor in $sticky_notes.get_children():
ancor.remove_child(ancor.get_child(1)) ancor.remove_child(ancor.get_child(1))
for i in range(sticky_notes.size()): for i in range(sticky_notes.size()):
options.append(sticky_notes[i]) options.append(sticky_notes[i])
$sticky_notes.get_child(i).add_child(options[i], false) $sticky_notes.get_child(i).add_child(options[i], false)
options[i].owner = self options[i].owner = self
func _input(event): func _input(event):
if event.is_action_pressed("ui_end"): if event.is_action_pressed("ui_end"):
fill_card_slots(3) fill_card_slots(3)
selection_state = CARDS selection_state = CARDS
if has_stage: if has_stage:
if !_input_locked: if !_input_locked:
if event.is_action_pressed("ui_up") or event.is_action_pressed("ui_left") or event.is_action_pressed("ui_focus_next"): if event.is_action_pressed("ui_up") or event.is_action_pressed("ui_left") or event.is_action_pressed("ui_focus_next"):
curr_selection_id -= 1 curr_selection_id -= 1
elif event.is_action_pressed("ui_down") or event.is_action_pressed("ui_right") or event.is_action_pressed("ui_focus_prev"): elif event.is_action_pressed("ui_down") or event.is_action_pressed("ui_right") or event.is_action_pressed("ui_focus_prev"):
curr_selection_id += 1 curr_selection_id += 1
if event.is_action_pressed("ui_accept"): if event.is_action_pressed("ui_accept"):
pick(curr_selection_id) pick(curr_selection_id)
elif event.is_action_pressed("skip"): elif event.is_action_pressed("skip"):
##fixme: using skip causes a lot of invalid state ##fixme: using skip causes a lot of invalid state
return return
if selection_state == CARDS_SELECTED: if selection_state == CARDS_SELECTED:
transition() transition()
show_posts() show_posts()
elif selection_state == POSTS_SELECTED: elif selection_state == POSTS_SELECTED:
transition() transition()
elif selection_state == TRANSITION: elif selection_state == TRANSITION:
show_posts() show_posts()
func pick(id: int): func pick(id: int):
print("PICK") print("PICK")
if id == -1: if id == -1:
curr_selection_id = 0 curr_selection_id = 0
return return
if selection_state == CARDS: if selection_state == CARDS:
selection_state = CARDS_SELECTED selection_state = CARDS_SELECTED
elif selection_state == POSTS: elif selection_state == POSTS:
selection_state = POSTS_SELECTED selection_state = POSTS_SELECTED
anim_players[id].play("pick") anim_players[id].play("pick")
var yield_to = anim_players[id].animation_finished var yield_to = anim_players[id].animation_finished
output.append(options[id]) output.append(options[id])
options.remove_at(id) options.remove_at(id)
anim_players.remove_at(id) anim_players.remove_at(id)
var sibling_id = -1 var sibling_id = -1
if selection_state == POSTS_SELECTED: if selection_state == POSTS_SELECTED:
sibling_id = options.find(output.back().sibling) sibling_id = options.find(output.back().sibling)
options.remove_at(sibling_id) options.remove_at(sibling_id)
anim_players[sibling_id].play("unshuffle") anim_players[sibling_id].play("unshuffle")
anim_players.remove_at(sibling_id) anim_players.remove_at(sibling_id)
print("yeet sibling ", sibling_id) print("yeet sibling ", sibling_id)
var winning_id var winning_id
print(options[1].text) print(options[1].text)
if !(options[1].text == "" and not id == 1): if !(options[1].text == "" and not id == 1):
randomize() randomize()
winning_id = randi() % options.size() winning_id = randi() % options.size()
print("Winning ID ", id) print("Winning ID ", id)
elif options[0].text == "": else:
winning_id = 1 Steam.setAchievement("FIGHT_BACK")
else: Steam.storeStats()
winning_id = 0
output.append(options.pop_at(winning_id))
output.append(options.pop_at(winning_id)) anim_players.pop_at(winning_id).play("shuffle")
anim_players.pop_at(winning_id).play("shuffle")
for anim in anim_players:
for anim in anim_players: anim.play("unshuffle")
anim.play("unshuffle")
await yield_to
await yield_to transition()
transition()
func transition(): func transition():
if selection_state == CARDS_SELECTED: if selection_state == CARDS_SELECTED:
selection_state = TRANSITION selection_state = TRANSITION
options = [] options = []
anim_players = [] anim_players = []
for control in $sticky_notes.get_children(): for control in $sticky_notes.get_children():
options.append(control.get_child(1)) options.append(control.get_child(1))
anim_players.append(control.get_child(0)) anim_players.append(control.get_child(0))
control.get_child(0).play("post") control.get_child(0).play("post")
curr_selection_id = -1 curr_selection_id = -1
fill_post_slots() fill_post_slots()
await anim_players[0].animation_finished await anim_players[0].animation_finished
show_posts() show_posts()
elif selection_state == POSTS_SELECTED: elif selection_state == POSTS_SELECTED:
var out_str:Array[String] = [] var out_str:Array[String] = []
for card in output: for card in output:
out_str.append(card.name) out_str.append(card.name)
emit_signal("cards_picked", out_str) emit_signal("cards_picked", out_str)
print(out_str) print(out_str)
selection_state = DONE selection_state = DONE
State.leave_stage(self) State.leave_stage(self)
func show_posts(): func show_posts():
selection_state = POSTS selection_state = POSTS
for player:AnimationPlayer in anim_players: for player:AnimationPlayer in anim_players:
player.play("reset") player.play("reset")
func handle_hover(new_highlight): func handle_hover(new_highlight):
if not _input_locked: if not _input_locked:
curr_selection_id = options.find(new_highlight) curr_selection_id = options.find(new_highlight)
func handle_mouse_button(new_selection: Node, button_event: InputEventMouseButton): func handle_mouse_button(new_selection: Node, button_event: InputEventMouseButton):
if not _input_locked: if not _input_locked:
if button_event.button_index == MOUSE_BUTTON_LEFT and button_event.pressed: if button_event.button_index == MOUSE_BUTTON_LEFT and button_event.pressed:
pick(options.find(new_selection)) pick(options.find(new_selection))
func scene_finished(id: int, repeat): func scene_finished(id: int, repeat):
print(name, id, repeat) print(name, id, repeat)
if not repeat: if not repeat:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
fill_card_slots(id) fill_card_slots(id)
State.transition_stage_to(self, true) State.transition_stage_to(self, true)
selection_state = CARDS selection_state = CARDS
func play_scene(_id, _repeat): func play_scene(_id, _repeat):
pass pass

View File

@ -16,151 +16,151 @@ var last_mouse_pos2D = null
func _ready(): func _ready():
node_area.connect("mouse_entered", Callable(self, "_mouse_entered_area")) node_area.connect("mouse_entered", Callable(self, "_mouse_entered_area"))
# If the material is NOT set to use billboard settings, then avoid running billboard specific code # If the material is NOT set to use billboard settings, then avoid running billboard specific code
if billboard == 0: if billboard == 0:
set_process(false) set_process(false)
func _process(_delta): func _process(_delta):
# NOTE: Remove this function if you don't plan on using billboard settings. # NOTE: Remove this function if you don't plan on using billboard settings.
rotate_area_to_billboard() rotate_area_to_billboard()
func _mouse_entered_area(): func _mouse_entered_area():
is_mouse_inside = true is_mouse_inside = true
func _unhandled_input(event): func _unhandled_input(event):
# Check if the event is a non-mouse/non-touch event # Check if the event is a non-mouse/non-touch event
var is_mouse_event = false var is_mouse_event = false
for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]: for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]:
if event is InputEventMouse: if event is InputEventMouse:
is_mouse_event = true is_mouse_event = true
break break
# If the event is a mouse/touch event and/or the mouse is either held or inside the area, then # If the event is a mouse/touch event and/or the mouse is either held or inside the area, then
# we need to do some additional processing in the handle_mouse function before passing the event to the viewport. # we need to do some additional processing in the handle_mouse function before passing the event to the viewport.
# If the event is not a mouse/touch event, then we can just pass the event directly to the viewport. # If the event is not a mouse/touch event, then we can just pass the event directly to the viewport.
if is_mouse_event and (is_mouse_inside or is_mouse_held): if is_mouse_event and (is_mouse_inside or is_mouse_held):
handle_mouse(event) handle_mouse(event)
elif not is_mouse_event: elif not is_mouse_event:
node_viewport.push_input(event) node_viewport.push_input(event)
# Handle mouse events inside Area. (Area.input_event had many issues with dragging) # Handle mouse events inside Area. (Area.input_event had many issues with dragging)
func handle_mouse(event): func handle_mouse(event):
# Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh. # Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh.
render_size = pixel_size * node_viewport.size render_size = pixel_size * node_viewport.size
# Detect mouse being held to mantain event while outside of bounds. Avoid orphan clicks # Detect mouse being held to mantain event while outside of bounds. Avoid orphan clicks
if event is InputEventMouseButton or event is InputEventScreenTouch: if event is InputEventMouseButton or event is InputEventScreenTouch:
is_mouse_held = event.pressed is_mouse_held = event.pressed
# Find mouse position in Area # Find mouse position in Area
var mouse_pos3D = find_mouse(event.global_position) var mouse_pos3D = find_mouse(event.global_position)
# Check if the mouse is outside of bounds, use last position to avoid errors # Check if the mouse is outside of bounds, use last position to avoid errors
# NOTE: mouse_exited signal was unrealiable in this situation # NOTE: mouse_exited signal was unrealiable in this situation
is_mouse_inside = mouse_pos3D != null is_mouse_inside = mouse_pos3D != null
if is_mouse_inside: if is_mouse_inside:
# Convert click_pos from world coordinate space to a coordinate space relative to the Area node. # Convert click_pos from world coordinate space to a coordinate space relative to the Area node.
# NOTE: affine_inverse accounts for the Area node's scale, rotation, and translation in the scene! # NOTE: affine_inverse accounts for the Area node's scale, rotation, and translation in the scene!
mouse_pos3D = node_area.global_transform.affine_inverse() * mouse_pos3D mouse_pos3D = node_area.global_transform.affine_inverse() * mouse_pos3D
last_mouse_pos3D = mouse_pos3D last_mouse_pos3D = mouse_pos3D
else: else:
mouse_pos3D = last_mouse_pos3D mouse_pos3D = last_mouse_pos3D
if mouse_pos3D == null: if mouse_pos3D == null:
mouse_pos3D = Vector3.ZERO mouse_pos3D = Vector3.ZERO
# TODO: adapt to bilboard mode or avoid completely # TODO: adapt to bilboard mode or avoid completely
# convert the relative event position from 3D to 2D # convert the relative event position from 3D to 2D
var mouse_pos2D = Vector2(mouse_pos3D.x, -mouse_pos3D.y) var mouse_pos2D = Vector2(mouse_pos3D.x, -mouse_pos3D.y)
# Right now the event position's range is the following: (-quad_size/2) -> (quad_size/2) # Right now the event position's range is the following: (-quad_size/2) -> (quad_size/2)
# We need to convert it into the following range: 0 -> quad_size # We need to convert it into the following range: 0 -> quad_size
mouse_pos2D += render_size / 2 mouse_pos2D += render_size / 2
# Then we need to convert it into the following range: 0 -> 1 # Then we need to convert it into the following range: 0 -> 1
mouse_pos2D = mouse_pos2D / render_size.x mouse_pos2D = mouse_pos2D / render_size.x
# Finally, we convert the position to the following range: 0 -> viewport.size # Finally, we convert the position to the following range: 0 -> viewport.size
mouse_pos2D.x = mouse_pos2D.x * node_viewport.size.x mouse_pos2D.x = mouse_pos2D.x * node_viewport.size.x
mouse_pos2D.y = mouse_pos2D.y * node_viewport.size.y mouse_pos2D.y = mouse_pos2D.y * node_viewport.size.y
# We need to do these conversions so the event's position is in the viewport's coordinate system. # We need to do these conversions so the event's position is in the viewport's coordinate system.
# Set the event's position and global position. # Set the event's position and global position.
event.position = mouse_pos2D event.position = mouse_pos2D
event.global_position = mouse_pos2D event.global_position = mouse_pos2D
# If the event is a mouse motion event... # If the event is a mouse motion event...
if event is InputEventMouseMotion: if event is InputEventMouseMotion:
# If there is not a stored previous position, then we'll assume there is no relative motion. # If there is not a stored previous position, then we'll assume there is no relative motion.
if last_mouse_pos2D == null: if last_mouse_pos2D == null:
event.relative = Vector2(0, 0) event.relative = Vector2(0, 0)
# If there is a stored previous position, then we'll calculate the relative position by subtracting # If there is a stored previous position, then we'll calculate the relative position by subtracting
# the previous position from the new position. This will give us the distance the event traveled from prev_pos # the previous position from the new position. This will give us the distance the event traveled from prev_pos
else: else:
event.relative = mouse_pos2D - last_mouse_pos2D event.relative = mouse_pos2D - last_mouse_pos2D
# Update last_mouse_pos2D with the position we just calculated. # Update last_mouse_pos2D with the position we just calculated.
last_mouse_pos2D = mouse_pos2D last_mouse_pos2D = mouse_pos2D
# Finally, send the processed input event to the viewport. # Finally, send the processed input event to the viewport.
node_viewport.push_input(event) node_viewport.push_input(event)
func find_mouse(global_position): func find_mouse(global_position):
var camera = get_viewport().get_camera_3d() var camera = get_viewport().get_camera_3d()
# From camera center to the mouse position in the Area # From camera center to the mouse position in the Area
var from = camera.project_ray_origin(global_position) var from = camera.project_ray_origin(global_position)
var dist = find_further_distance_to(camera.transform.origin) var dist = find_further_distance_to(camera.transform.origin)
var to = from + camera.project_ray_normal(global_position) * dist var to = from + camera.project_ray_normal(global_position) * dist
# Manually raycasts the are to find the mouse position # Manually raycasts the are to find the mouse position
var result = get_world_3d().direct_space_state.intersect_ray(PhysicsRayQueryParameters3D.create(from, to, node_area.collision_layer)) #for 3.1 changes var result = get_world_3d().direct_space_state.intersect_ray(PhysicsRayQueryParameters3D.create(from, to, node_area.collision_layer)) #for 3.1 changes
if result.size() > 0: if result.size() > 0:
return result.position return result.position
else: else:
return null return null
func find_further_distance_to(origin): func find_further_distance_to(origin):
# Find edges of collision and change to global positions # Find edges of collision and change to global positions
var edges = [] var edges = []
edges.append(node_area.to_global(Vector3(render_size.x / 2, render_size.y / 2, 0))) edges.append(node_area.to_global(Vector3(render_size.x / 2, render_size.y / 2, 0)))
edges.append(node_area.to_global(Vector3(render_size.x / 2, -render_size.y / 2, 0))) edges.append(node_area.to_global(Vector3(render_size.x / 2, -render_size.y / 2, 0)))
edges.append(node_area.to_global(Vector3(-render_size.x / 2, render_size.y / 2, 0))) edges.append(node_area.to_global(Vector3(-render_size.x / 2, render_size.y / 2, 0)))
edges.append(node_area.to_global(Vector3(-render_size.x / 2, -render_size.y / 2, 0))) edges.append(node_area.to_global(Vector3(-render_size.x / 2, -render_size.y / 2, 0)))
# Get the furthest distance between the camera and collision to avoid raycasting too far or too short # Get the furthest distance between the camera and collision to avoid raycasting too far or too short
var far_dist = 0 var far_dist = 0
var temp_dist var temp_dist
for edge in edges: for edge in edges:
temp_dist = origin.distance_to(edge) temp_dist = origin.distance_to(edge)
if temp_dist > far_dist: if temp_dist > far_dist:
far_dist = temp_dist far_dist = temp_dist
return far_dist return far_dist
func rotate_area_to_billboard(): func rotate_area_to_billboard():
# Try to match the area with the material's billboard setting, if enabled # Try to match the area with the material's billboard setting, if enabled
if billboard > 0: if billboard > 0:
# Get the camera # Get the camera
var camera = get_viewport().get_camera_3d() var camera = get_viewport().get_camera_3d()
# Look in the same direction as the camera # Look in the same direction as the camera
var look = camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin var look = camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin
look = node_area.position + look look = node_area.position + look
# Y-Billboard: Lock Y rotation, but gives bad results if the camera is tilted. # Y-Billboard: Lock Y rotation, but gives bad results if the camera is tilted.
if billboard == 2: if billboard == 2:
look = Vector3(look.x, 0, look.z) look = Vector3(look.x, 0, look.z)
node_area.look_at(look, Vector3.UP) node_area.look_at(look, Vector3.UP)
# Rotate in the Z axis to compensate camera tilt # Rotate in the Z axis to compensate camera tilt
node_area.rotate_object_local(Vector3.BACK, camera.rotation.z) node_area.rotate_object_local(Vector3.BACK, camera.rotation.z)

View File

@ -5,73 +5,73 @@ class_name Collectable_Ui
@export var scene = Scenes.id @export var scene = Scenes.id
@export var collapsed = true: @export var collapsed = true:
set(collapse): set(collapse):
if is_inside_tree() and not Engine.is_editor_hint(): if is_inside_tree() and not Engine.is_editor_hint():
if State.reduce_motion: if State.reduce_motion:
collapsed = false collapsed = false
return return
if collapse and not collapsed: if collapse and not collapsed:
if is_inside_tree(): if is_inside_tree():
_hide_buttons() _hide_buttons()
collapsed = collapse collapsed = collapse
elif not collapse and collapsed: elif not collapse and collapsed:
if is_inside_tree(): if is_inside_tree():
_show_buttons() _show_buttons()
collapsed = collapse collapsed = collapse
if collapse and has_stage: State.leave_stage(self) if collapse and has_stage: State.leave_stage(self)
@export var is_story: bool = false: @export var is_story: bool = false:
set(story): set(story):
is_story = story is_story = story
if not story: if not story:
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "Order Thoughts" $Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "Order Thoughts"
else: else:
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "Collect Memento" $Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "Collect Memento"
@export var has_stage: bool = false: @export var has_stage: bool = false:
set(focused): set(focused):
print("set focus of card to ", focused) print("set focus of card to ", focused)
if has_stage == focused: return if has_stage == focused: return
if focused: if focused:
has_stage = true has_stage = true
collapsed = false collapsed = false
if not visible: show() if not visible: show()
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.grab_focus() $Panel/Content/Buttons/VBoxContainer/collect_or_listen.grab_focus()
elif has_stage: elif has_stage:
has_stage = false has_stage = false
get_viewport().gui_release_focus() get_viewport().gui_release_focus()
@export var collected: bool = false: @export var collected: bool = false:
set(set_collected): set(set_collected):
collected = set_collected collected = set_collected
if set_collected: if set_collected:
$Panel/Content/Buttons/VBoxContainer/put_back.show() $Panel/Content/Buttons/VBoxContainer/put_back.show()
if is_story: if is_story:
$Panel/Content/Buttons/VBoxContainer/put_back.disabled = true $Panel/Content/Buttons/VBoxContainer/put_back.disabled = true
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "listen again" $Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "listen again"
if State.allow_skipping: if State.allow_skipping:
$Panel/Content/Buttons/VBoxContainer/skip.text = "discard cards (skip)" $Panel/Content/Buttons/VBoxContainer/skip.text = "discard cards (skip)"
else: else:
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.disabled = true $Panel/Content/Buttons/VBoxContainer/collect_or_listen.disabled = true
$Panel/Content/Buttons/VBoxContainer/put_back.show() $Panel/Content/Buttons/VBoxContainer/put_back.show()
else: else:
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.disabled = false $Panel/Content/Buttons/VBoxContainer/collect_or_listen.disabled = false
@export var skipped: bool = false @export var skipped: bool = false
@export var item_name: String = "": @export var item_name: String = "":
set(new_name): set(new_name):
item_name = new_name item_name = new_name
if is_inside_tree(): if is_inside_tree():
$Panel/Content/Name.text = new_name $Panel/Content/Name.text = new_name
@export var content_notes: String = "": @export var content_notes: String = "":
set(new_notes): set(new_notes):
content_notes = new_notes content_notes = new_notes
if is_inside_tree(): if is_inside_tree():
$Panel/Content/ContentNotes.text = new_notes $Panel/Content/ContentNotes.text = new_notes
signal card_collected signal card_collected
signal open_board signal open_board
@ -79,70 +79,70 @@ signal scene_skipped(i: int)
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
#$Panel/Content/ContentNotes.visible = State.show_content_notes #$Panel/Content/ContentNotes.visible = State.show_content_notes
#$Panel/Content/Buttons/VBoxContainer/Summary.visible = State.provide_summaries #$Panel/Content/Buttons/VBoxContainer/Summary.visible = State.provide_summaries
#$Panel/Content/Buttons/VBoxContainer/skip.visible = State.allow_skipping #$Panel/Content/Buttons/VBoxContainer/skip.visible = State.allow_skipping
if visible and not collapsed: _show_buttons() if visible and not collapsed: _show_buttons()
content_notes = content_notes content_notes = content_notes
is_story = is_story is_story = is_story
item_name = item_name item_name = item_name
func _hide_buttons(): func _hide_buttons():
if is_inside_tree(): if is_inside_tree():
if not State.reduce_motion: if not State.reduce_motion:
$AnimationPlayer.play_backwards("show_buttons") $AnimationPlayer.play_backwards("show_buttons")
func _show_buttons(): func _show_buttons():
if is_inside_tree(): if is_inside_tree():
if not State.reduce_motion: if not State.reduce_motion:
$AnimationPlayer.play("show_buttons") $AnimationPlayer.play("show_buttons")
else: else:
$AnimationPlayer.play("RESET") $AnimationPlayer.play("RESET")
else: else:
$AnimationPlayer.play("RESET") $AnimationPlayer.play("RESET")
func hide(): func hide():
if visible: if visible:
var tween = create_tween() var tween = create_tween()
tween.tween_property(self, "modulate", Color(0, 0, 0), 0.4) tween.tween_property(self, "modulate", Color(0, 0, 0), 0.4)
if not collapsed: _hide_buttons() if not collapsed: _hide_buttons()
await tween.finished await tween.finished
visible = false visible = false
if has_stage: State.leave_stage(self) if has_stage: State.leave_stage(self)
func show(): func show():
if !visible: if !visible:
$Panel/Content/ContentNotes.visible = State.show_content_notes $Panel/Content/ContentNotes.visible = State.show_content_notes
$Panel/Content/Buttons/VBoxContainer/skip.visible = State.allow_skipping and is_story and not skipped $Panel/Content/Buttons/VBoxContainer/skip.visible = State.allow_skipping and is_story and not skipped
if not collapsed: if not collapsed:
_show_buttons() _show_buttons()
modulate = Color() modulate = Color()
visible = true visible = true
var tween = create_tween() var tween = create_tween()
tween.tween_property(self, "modulate", Color(1, 1, 1), 0.4) tween.tween_property(self, "modulate", Color(1, 1, 1), 0.4)
func _yoink_focus(): func _yoink_focus():
if not has_stage: if not has_stage:
State.transition_stage_to(self) State.transition_stage_to(self)
func _on_pick_button_pressed(): func _on_pick_button_pressed():
print("card collected!") print("card collected!")
if scene != null: if scene != null:
State.leave_stage(self) State.leave_stage(self)
get_tree().call_group("animation_player", "play_scene", scene, collected) get_tree().call_group("animation_player", "play_scene", scene, collected)
if skipped: emit_signal("scene_skipped", -1) if skipped: emit_signal("scene_skipped", -1)
collected = true collected = true
else: else:
emit_signal("open_board") emit_signal("open_board")
hide() hide()
func _on_skip_pressed(): func _on_skip_pressed():
print("Scene skipped!") print("Scene skipped!")
if scene != null: if scene != null:
emit_signal("scene_skipped", 1) emit_signal("scene_skipped", 1)
skipped = true skipped = true
$Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "collect (un-skip)" $Panel/Content/Buttons/VBoxContainer/collect_or_listen.text = "collect (un-skip)"
State.leave_stage(self) State.leave_stage(self)

View File

@ -1,13 +1,13 @@
extends Panel extends Panel
@onready var has_stage = true: @onready var has_stage = true:
set(focus): set(focus):
if focus: if focus:
has_stage = State.request_focus(self) has_stage = State.request_focus(self)
else: else:
has_stage = false has_stage = false
State.drop_own_focus(self) State.drop_own_focus(self)
func _ready(): func _ready():
theme = State.current_main_theme theme = State.current_main_theme
State.theme_changed.connect(func change_theme(new_theme): theme = new_theme) State.theme_changed.connect(func change_theme(new_theme): theme = new_theme)

View File

@ -9,38 +9,38 @@ var time_pressed: float = 0
var pressed: bool var pressed: bool
func _ready(): func _ready():
owner = get_node(costum_owner) owner = get_node(costum_owner)
if owner == null: if owner == null:
owner = get_parent().get_parent() owner = get_parent().get_parent()
owner.connect("visibility_changed", Callable(self, "owner_visibility_changed")) owner.connect("visibility_changed", Callable(self, "owner_visibility_changed"))
visible = owner.visible visible = owner.visible
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta): func _process(delta):
if pressed and visible: if pressed and visible:
time_pressed += delta time_pressed += delta
progress.value = time_pressed / skip_delay progress.value = time_pressed / skip_delay
if time_pressed >= skip_delay: if time_pressed >= skip_delay:
emit_signal("skip") emit_signal("skip")
pressed = false pressed = false
time_pressed = 0 time_pressed = 0
func _input(event): func _input(event):
if visible: if visible:
if event.is_action_pressed("skip"): if event.is_action_pressed("skip"):
pressed = true pressed = true
elif event.is_action_released("skip"): elif event.is_action_released("skip"):
pressed = false pressed = false
time_pressed = 0 time_pressed = 0
func owner_visibility_changed(): func owner_visibility_changed():
visible = owner.visible visible = owner.visible
func _on_skip_button_toggled(button_pressed): func _on_skip_button_toggled(button_pressed):
if button_pressed: if button_pressed:
pressed = true pressed = true
else: else:
pressed = false pressed = false
time_pressed = 0 time_pressed = 0

View File

@ -1,32 +1,32 @@
extends RigidBody3D extends RigidBody3D
var has_stage: bool = false: var has_stage: bool = false:
set(on_stage): set(on_stage):
if has_stage != on_stage: if has_stage != on_stage:
if on_stage: if on_stage:
has_stage = true has_stage = true
if is_inside_tree(): if is_inside_tree():
camera.make_current() camera.make_current()
get_viewport().gui_release_focus() get_viewport().gui_release_focus()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
var jitter_tween: Tween = create_tween() var jitter_tween: Tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 1, 1) jitter_tween.tween_property(self, "jitter_strength", 1, 1)
if has_entered: emit_signal("ui_exited") if has_entered: emit_signal("ui_exited")
elif has_stage: elif has_stage:
camera.current = true camera.current = true
jitter_strength = 1 jitter_strength = 1
else: else:
if is_inside_tree() and has_stage: if is_inside_tree() and has_stage:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
var jitter_tween: Tween = create_tween() var jitter_tween: Tween = create_tween()
jitter_tween.tween_property(self, "jitter_strength", 0, 0.5) jitter_tween.tween_property(self, "jitter_strength", 0, 0.5)
if has_entered: emit_signal("ui_exited") if has_entered: emit_signal("ui_exited")
else: else:
jitter_strength = 0 jitter_strength = 0
has_stage = false has_stage = false
sleeping = has_stage sleeping = has_stage
@export_range (0, 10) var max_speed: float = 3 @export_range (0, 10) var max_speed: float = 3
@export_range (0, 10) var max_acceleration: float = 5 @export_range (0, 10) var max_acceleration: float = 5
@export_range (0, 20) var damp: float = 10 @export_range (0, 20) var damp: float = 10
@ -59,157 +59,157 @@ var on_crouch_cooldown:bool = false
@onready var focus_ray: RayCast3D = $Yaw/Pitch/Mount/Camera3D/RayCast3D @onready var focus_ray: RayCast3D = $Yaw/Pitch/Mount/Camera3D/RayCast3D
var zoomed: var zoomed:
set(zoom): set(zoom):
if zoomed != zoom: if zoomed != zoom:
if zoom: if zoom:
var zoom_tween = create_tween() var zoom_tween = create_tween()
zoom_tween.tween_property(camera, "fov", camera.fov*0.5, 0.5) zoom_tween.tween_property(camera, "fov", camera.fov*0.5, 0.5)
else: else:
var zoom_tween = create_tween() var zoom_tween = create_tween()
zoom_tween.tween_property(camera, "fov", camera.fov*2, 0.5) zoom_tween.tween_property(camera, "fov", camera.fov*2, 0.5)
zoomed = zoom zoomed = zoom
signal ui_entered signal ui_entered
var has_entered:bool = false var has_entered:bool = false
signal ui_exited signal ui_exited
func _ready(): func _ready():
_handle_jitter(0) _handle_jitter(0)
func _on_ini_room(): func _on_ini_room():
State.take_stage(self) State.take_stage(self)
get_tree().call_group("animation_player", "play_scene", Scenes.id.YOUTH_DRAEVEN, false) get_tree().call_group("animation_player", "play_scene", Scenes.id.YOUTH_DRAEVEN, false)
State.queue_for_stage(self) State.queue_for_stage(self)
func _process(_delta): func _process(_delta):
if focus_ray.get_collider() != null and not has_entered: if focus_ray.get_collider() != null and not has_entered:
emit_signal("ui_entered") emit_signal("ui_entered")
has_entered = true has_entered = true
focus_ray.get_collider().reveal() focus_ray.get_collider().reveal()
if has_stage: if has_stage:
if has_entered: if has_entered:
if focus_ray.get_collider() == null: if focus_ray.get_collider() == null:
emit_signal("ui_exited") emit_signal("ui_exited")
has_entered = false has_entered = false
if Input.is_action_just_pressed("ui_accept"): if Input.is_action_just_pressed("ui_accept"):
State.pass_stage_to(focus_ray.get_collider()) State.pass_stage_to(focus_ray.get_collider())
else: else:
if Input.is_action_just_pressed("zoom_in_controller"): if Input.is_action_just_pressed("zoom_in_controller"):
zoomed = true zoomed = true
elif Input.is_action_just_released("zoom_in_controller"): elif Input.is_action_just_released("zoom_in_controller"):
zoomed = false zoomed = false
func _physics_process(delta:float): func _physics_process(delta:float):
if has_stage: if has_stage:
_handle_movement(delta) _handle_movement(delta)
_handle_rotation(delta) _handle_rotation(delta)
if jitter_strength > 0 and not State.reduce_motion: _handle_jitter(delta) if jitter_strength > 0 and not State.reduce_motion: _handle_jitter(delta)
func _handle_movement(delta:float): func _handle_movement(delta:float):
var input:Vector2 = Vector2(Input.get_action_strength("player_right") - Input.get_action_strength("player_left"), var input:Vector2 = Vector2(Input.get_action_strength("player_right") - Input.get_action_strength("player_left"),
Input.get_action_strength("player_backwards")*0.8 - Input.get_action_strength("player_forwards")) Input.get_action_strength("player_backwards")*0.8 - Input.get_action_strength("player_forwards"))
if input.length()>1: if input.length()>1:
input = input.normalized() input = input.normalized()
var direction: Vector3 = Vector3(input.x, 0, input.y) var direction: Vector3 = Vector3(input.x, 0, input.y)
direction = yaw.global_transform.basis.x * direction.x + transform.basis.y * direction.y + yaw.global_transform.basis.z * direction.z direction = yaw.global_transform.basis.x * direction.x + transform.basis.y * direction.y + yaw.global_transform.basis.z * direction.z
if linear_velocity.length() > (linear_velocity + (direction*max_speed - linear_velocity)).length(): if linear_velocity.length() > (linear_velocity + (direction*max_speed - linear_velocity)).length():
direction = Vector3.ZERO direction = Vector3.ZERO
else: else:
direction *= (direction*max_speed - linear_velocity).length()*max_acceleration direction *= (direction*max_speed - linear_velocity).length()*max_acceleration
linear_damp = damp * max(0.5, 1 - input.length()) linear_damp = damp * max(0.5, 1 - input.length())
apply_central_impulse(direction*delta) apply_central_impulse(direction*delta)
func _handle_rotation(delta:float): func _handle_rotation(delta:float):
var smoothness = min(3, 60.0/Engine.get_frames_per_second()) var smoothness = min(3, 60.0/Engine.get_frames_per_second())
var input_speed = Vector2( Input.get_action_strength("look_right")-Input.get_action_strength("look_left"), Input.get_action_strength("look_up")-Input.get_action_strength("look_down")) * gamepad_response var input_speed = Vector2( Input.get_action_strength("look_right")-Input.get_action_strength("look_left"), Input.get_action_strength("look_up")-Input.get_action_strength("look_down")) * gamepad_response
if current_mouse_rotation.length()>0: if current_mouse_rotation.length()>0:
input_speed = current_mouse_rotation input_speed = current_mouse_rotation
current_mouse_rotation = Vector2.ZERO current_mouse_rotation = Vector2.ZERO
rotation_speed = rotation_speed * (1-mouse_jerk*smoothness) + input_speed * mouse_jerk * smoothness rotation_speed = rotation_speed * (1-mouse_jerk*smoothness) + input_speed * mouse_jerk * smoothness
if rotation_speed.y > 0 and pitch.rotation_degrees.x < 0: if rotation_speed.y > 0 and pitch.rotation_degrees.x < 0:
rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/-max_angle, 4) rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/-max_angle, 4)
elif rotation_speed.y < 0 and pitch.rotation_degrees.x > 0 : elif rotation_speed.y < 0 and pitch.rotation_degrees.x > 0 :
rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/max_angle, 4) rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/max_angle, 4)
yaw.rotate_y(deg_to_rad(-rotation_speed.x * delta * mouse_sensitivity.x)) yaw.rotate_y(deg_to_rad(-rotation_speed.x * delta * mouse_sensitivity.x))
pitch.rotate_x(deg_to_rad(-rotation_speed.y * delta * mouse_sensitivity.y)) pitch.rotate_x(deg_to_rad(-rotation_speed.y * delta * mouse_sensitivity.y))
func _handle_jitter(delta): func _handle_jitter(delta):
loc_noise_spot += Vector3(delta * camera_jitter_speed * location_jitter_speed) loc_noise_spot += Vector3(delta * camera_jitter_speed * location_jitter_speed)
rot_noise_spot += Vector3(delta * camera_jitter_speed * angular_jitter_speed) rot_noise_spot += Vector3(delta * camera_jitter_speed * angular_jitter_speed)
pitch.position = Vector3( pitch.position = Vector3(
noise.get_noise_1d(loc_noise_spot.x), noise.get_noise_1d(loc_noise_spot.x),
noise.get_noise_1d(loc_noise_spot.y), noise.get_noise_1d(loc_noise_spot.y),
noise.get_noise_1d(loc_noise_spot.z) noise.get_noise_1d(loc_noise_spot.z)
) * location_jitter * jitter_strength ) * location_jitter * jitter_strength
if not State.reduce_motion: mount.rotation = Vector3( if not State.reduce_motion: mount.rotation = Vector3(
noise.get_noise_1d(rot_noise_spot.x), noise.get_noise_1d(rot_noise_spot.x),
noise.get_noise_1d(rot_noise_spot.y), noise.get_noise_1d(rot_noise_spot.y),
noise.get_noise_1d(rot_noise_spot.z) noise.get_noise_1d(rot_noise_spot.z)
) * angular_jitter * jitter_strength ) * angular_jitter * jitter_strength
func _handle_mouse_input(event:InputEventMouseMotion): func _handle_mouse_input(event:InputEventMouseMotion):
if event.relative.length() < mouse_jerk_rejection: if event.relative.length() < mouse_jerk_rejection:
current_mouse_rotation = event.relative current_mouse_rotation = event.relative
func _input(event:InputEvent): func _input(event:InputEvent):
if has_stage: if has_stage:
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
_handle_mouse_input(event) _handle_mouse_input(event)
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
if event is InputEventMouseButton and event.pressed: if event is InputEventMouseButton and event.pressed:
if Input.is_action_just_pressed("zoom_in_mouse"): if Input.is_action_just_pressed("zoom_in_mouse"):
zoomed = true zoomed = true
elif Input.is_action_just_pressed("zoom_out_mouse"): elif Input.is_action_just_pressed("zoom_out_mouse"):
zoomed = false zoomed = false
else: else:
State.free_focus() State.free_focus()
get_tree().call_group("interactables", "reveal") get_tree().call_group("interactables", "reveal")
#if event.is_action_pressed("ui_accept"): #if event.is_action_pressed("ui_accept"):
# State.pass_stage_to(focus_ray.get_collider()) # State.pass_stage_to(focus_ray.get_collider())
# get_viewport().set_input_as_handled() # get_viewport().set_input_as_handled()
else: else:
if event is InputEventMouseButton: if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed: if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
if !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): if !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
State.take_stage(self, true) State.take_stage(self, true)
get_tree().call_group("interactables", "collapse") get_tree().call_group("interactables", "collapse")
func play_scene(id: int, _repeat): func play_scene(id: int, _repeat):
if id == Scenes.id.YOUTH_DRAEVEN: if id == Scenes.id.YOUTH_DRAEVEN:
var rotation_tween = create_tween() var rotation_tween = create_tween()
func scene_finished(_id, repeat: bool): func scene_finished(_id, repeat: bool):
if repeat: if repeat:
State.take_stage(self, true) State.take_stage(self, true)
func _on_bed_enter(_body): func _on_bed_enter(_body):
if not (crouched or on_crouch_cooldown): if not (crouched or on_crouch_cooldown):
$PlayerAnimationPlayer.queue("crouch") $PlayerAnimationPlayer.queue("crouch")
var tween = create_tween() var tween = create_tween()
tween.tween_property(self, "max_speed", max_speed/2, 0.3) tween.tween_property(self, "max_speed", max_speed/2, 0.3)
crouched = true crouched = true
func _on_bed_exit(_body): func _on_bed_exit(_body):
if crouched: if crouched:
crouched = false crouched = false
$PlayerAnimationPlayer.queue("stand_up") $PlayerAnimationPlayer.queue("stand_up")
var tween = create_tween() var tween = create_tween()
tween.tween_property(self, "max_speed", max_speed*2, 1) tween.tween_property(self, "max_speed", max_speed*2, 1)
on_crouch_cooldown = true on_crouch_cooldown = true
await get_tree().create_timer(1.0).timeout await get_tree().create_timer(1.0).timeout
on_crouch_cooldown = false on_crouch_cooldown = false

View File

@ -3,4 +3,4 @@ extends HSlider
@export var audio_bus_id: int = 0 @export var audio_bus_id: int = 0
func _on_value_changed(volume_lin: float): func _on_value_changed(volume_lin: float):
AudioServer.set_bus_volume_db(audio_bus_id, linear_to_db(volume_lin)) AudioServer.set_bus_volume_db(audio_bus_id, linear_to_db(volume_lin))

View File

@ -3,15 +3,15 @@ extends Node3D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
pass # Replace with function body. pass # Replace with function body.
func debug_youth(): func debug_youth():
get_child(1).hide() get_child(1).hide()
get_child(2).hide() get_child(2).hide()
get_child(3).hide() get_child(3).hide()
get_child(0).get_ready() get_child(0).get_ready()
get_child(0).start() get_child(0).start()
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta): func _process(delta):
pass pass

View File

@ -1,5 +1,5 @@
extends Node extends Node
# For Startup Scene: # For Startup Scene:
var screen_reader:bool = false # Screenreader var screen_reader:bool = false # Screenreader
var disable_rendering: bool = false # show nav button var disable_rendering: bool = false # show nav button
var simplified_navigation:bool = false # simplified controls var simplified_navigation:bool = false # simplified controls
@ -18,96 +18,90 @@ var focus_locked: bool = false
signal theme_changed signal theme_changed
var current_main_theme:Theme = preload("res://logic-scenes/themes/easy-handwriting.theme"): var current_main_theme:Theme = preload("res://logic-scenes/themes/easy-handwriting.theme"):
set(theme): set(theme):
current_main_theme = theme current_main_theme = theme
emit_signal("theme_changed", theme) emit_signal("theme_changed", theme)
func _ready(): func _ready():
for child in get_parent().get_children(): for child in get_parent().get_children():
if "has_stage" in child: if "has_stage" in child:
pass_stage_to(child) pass_stage_to(child)
# Meta: due to conflicting names with the internal focus handling of godot, a "stage-based" Metaphor is being used to refer to focus handling. # Meta: due to conflicting names with the internal focus handling of godot, a "stage-based" Metaphor is being used to refer to focus handling.
# Intented for use when an actor wants focus for itself, can reclaim focus, thus dropping the stack that focused. # Intented for use when an actor wants focus for itself, can reclaim focus, thus dropping the stack that focused.
func take_stage(actor: Object, reclaim: bool = false) -> bool: func take_stage(actor: Object, reclaim: bool = false) -> bool:
if focus_locked: return false if focus_locked: return false
if reclaim: if reclaim:
stage_list.front().has_stage = false stage_list.front().has_stage = false
if stage_list.has(actor): if stage_list.has(actor):
while stage_list.pop_front() != actor: break while stage_list.pop_front() != actor: break
actor.has_stage = true actor.has_stage = true
stage_list.push_front(actor) stage_list.push_front(actor)
return actor.has_stage return actor.has_stage
push_warning(actor, " wanted to reclaim focus, but was not on list.") push_warning(actor, " wanted to reclaim focus, but was not on list.")
return pass_stage_to(actor) return pass_stage_to(actor)
# Element no longer wants focus, if Element itself is also dropped, this option can be chosen aswell. # Element no longer wants focus, if Element itself is also dropped, this option can be chosen aswell.
func leave_stage(actor:Object, dropObject: bool = false) -> bool: func leave_stage(actor:Object, dropObject: bool = false) -> bool:
if get_tree().paused: if get_tree().paused:
push_error(actor, " wanted to drop focus while tree is paused.") push_error(actor, " wanted to drop focus while tree is paused.")
if not dropObject: actor.has_stage = false if not dropObject: actor.has_stage = false
focus_locked = false focus_locked = false
stage_list.erase(actor) stage_list.erase(actor)
if stage_list != []: if stage_list != []:
stage_list.front().has_stage = true stage_list.front().has_stage = true
else: else:
get_tree().quit() get_tree().quit()
return false return false
func get_current_actor(): return stage_list.front() func get_current_actor(): return stage_list.front()
# Used to put a new target on top of the Focus Stack. # Used to put a new target on top of the Focus Stack.
func pass_stage_to(target:Object, force = false, lock_focus = true) -> bool: func pass_stage_to(target:Object, force = false, lock_focus = true) -> bool:
if "pass_to_actor" in target: if "pass_to_actor" in target:
pass_stage_to(target.pass_to_actor) pass_stage_to(target.pass_to_actor)
if (focus_locked or get_tree().paused) and not force: if (focus_locked or get_tree().paused) and not force:
push_error(target, " requested focus while it was locked or tree is paused.") push_error(target, " requested focus while it was locked or tree is paused.")
elif !is_instance_valid(target): elif !is_instance_valid(target):
push_error("Focus instance not valid") push_error("Focus instance not valid")
elif !"has_stage" in target: elif !"has_stage" in target:
push_error(target, " has no has focus method.") push_error(target, " has no has focus method.")
else: else:
if stage_list.size() > 0: if stage_list.size() > 0:
if stage_list.front() == target: if stage_list.front() == target:
push_warning(target, " is already target. Abort passing focus.") push_warning(target, " is already target. Abort passing focus.")
return false return false
if not stage_list.size() == 0: stage_list.front().has_stage = false if not stage_list.size() == 0: stage_list.front().has_stage = false
target.has_stage = true target.has_stage = true
if target.has_stage: if target.has_stage:
stage_list.push_front(target) stage_list.push_front(target)
assert(stage_list.size() < 100) assert(stage_list.size() < 100)
return true return true
return false return false
# Currently focused element loses focus, but remains in stack. # Currently focused element loses focus, but remains in stack.
func free_focus(): func free_focus():
if focus_locked: return false if focus_locked: return false
if stage_list.size() > 0: stage_list.front().has_stage = false if stage_list.size() > 0: stage_list.front().has_stage = false
func transition_stage_to(thief: Object, lock_focus = false): func transition_stage_to(thief: Object, lock_focus = false):
focus_locked = lock_focus focus_locked = lock_focus
if stage_list.size() > 0: if stage_list.size() > 0:
if stage_list.front().has_stage: if stage_list.front().has_stage:
stage_list.pop_front().has_stage = false stage_list.pop_front().has_stage = false
return pass_stage_to(thief, true) return pass_stage_to(thief, true)
func queue_for_stage(target: Object, index: int = 1): func queue_for_stage(target: Object, index: int = 1):
stage_list.insert(index, target) stage_list.insert(index, target)
func print_settings(): func print_settings():
print_debug("Screenreader: ", screen_reader, " / ", print_debug("Screenreader: ", screen_reader, " / ",
"Disable rendering: ", disable_rendering, " / ", "Disable rendering: ", disable_rendering, " / ",
"Simplified controls: ", simplified_navigation, " / ", "Simplified controls: ", simplified_navigation, " / ",
"Show navigation buttons: ", show_navigation_buttons, " / ", "Show navigation buttons: ", show_navigation_buttons, " / ",
"Enable subtitles: ", enable_subtitles, " / ", "Enable subtitles: ", enable_subtitles, " / ",
"Enable CC: ", enable_closed_caption, " / ") "Enable CC: ", enable_closed_caption, " / ")

View File

@ -1,11 +1,11 @@
extends Node extends Node
enum id { enum id {
YOUTH_CHILDHOOD, YOUTH_CHILDHOOD,
YOUTH_VOICE_TRAINING, YOUTH_VOICE_TRAINING,
YOUTH_JUI_JUTSU, YOUTH_JUI_JUTSU,
YOUTH_DRAEVEN, YOUTH_DRAEVEN,
ADULT_DND, ADULT_DND,
ADULD_VOLUNTARY, ADULD_VOLUNTARY,
ADULD_CHRISTMAS ADULD_CHRISTMAS
} }

View File

@ -93,7 +93,7 @@ Frame of mind is
made by betalars made by betalars
They were suppored by: They were suppored by:
Adrian Schmid and tilcreator - programming Adrian Schmid and somebody that I used to know - programming
Jas Arianna - voice acting Jas Arianna - voice acting
STTLE - OST STTLE - OST