WIP: resolving a bunch of issues with gamepad behavior in Board

This commit is contained in:
betalars 2025-08-18 20:59:47 +02:00
parent aeb72d7a9f
commit e1be319306
3 changed files with 205 additions and 52 deletions

View File

@ -49,8 +49,8 @@ var dropzone_size: Vector2
@onready var sticky_note_container = $HBoxContainer/ScrollContainer/VBoxContainer @onready var sticky_note_container = $HBoxContainer/ScrollContainer/VBoxContainer
@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()
@ -102,14 +102,21 @@ var mementos_collected: int = 0:
@onready var current_sticky_note_id: int = 0: @onready var current_sticky_note_id: int = 0:
set(new_id): set(new_id):
if is_node_ready(): if is_node_ready():
if sticky_note_container.get_child_count() <= 1: return if sticky_note_container.get_child_count() < 1: return
elif 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 > 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
elif sticky_note_container.get_child(new_id).invalid:
if sticky_note_container.get_child_count() == 1: return
if new_id+1 == sticky_note_container.get_child_count():
current_sticky_note_id = new_id-1
else:
current_sticky_note_id = new_id+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: elif focus_stickies:
if sticky_note_container.get_child(current_sticky_note_id).get_child_count() == 1: if sticky_note_container.get_child(current_sticky_note_id).get_child_count() == 1:
currently_active_node = sticky_note_container.get_child(current_sticky_note_id).get_child(0) currently_active_node = sticky_note_container.get_child(current_sticky_note_id).get_child(0)
else: else:
@ -286,7 +293,7 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act
func _return_sticky_notes_to_panels(): func _return_sticky_notes_to_panels():
return #FIXME this is an early return to prevent race conditions. Check if it is save to be removed. if not (current_context == ASSIGN and focus_stickies): return #FIXME this is an early return to prevent race conditions. Check if it is save to be removed.
for panel:StickyNotePanel in sticky_note_container.get_children(): for panel:StickyNotePanel in sticky_note_container.get_children():
panel.reclaim_sticky_note() panel.reclaim_sticky_note()
@ -366,9 +373,10 @@ func handle_hover(to_handle: Area2D):
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 (current_context == ASSIGN and not currently_active_node.is_dragged): #Prevent Mouse input from messing up directional control selections
current_dropzone_id = dropzone.get_children().find(to_handle) if not (to_handle is StickyNote and !to_handle.on_board):
focus_stickies = false current_dropzone_id = dropzone.get_children().find(to_handle)
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
@ -413,70 +421,143 @@ func _input(event):
return return
if current_context != DRAG: if current_context != DRAG:
var selection_position: Vector2
if current_context == ASSIGN:
selection_position = dropzone.get_child( current_dropzone_id ).global_position
else:
selection_position = currently_active_node.global_position
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 if not try_select_nearest_card(selection_position, Vector2.UP):
current_dropzone_id -= 1
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
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 if not try_select_nearest_card(selection_position, Vector2.DOWN):
current_dropzone_id += 1
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
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 try_select_nearest_card(selection_position, Vector2.RIGHT, true):
if current_context == NAVIGATE: if not focus_stickies:
focus_stickies = true if current_context == NAVIGATE:
elif current_context == ASSIGN: focus_stickies = true
current_context = NAVIGATE elif current_context == ASSIGN:
get_viewport().set_input_as_handled() sticky_note_container.get_children()[current_sticky_note_id].reclaim_sticky_note()
current_context = NAVIGATE
get_viewport().set_input_as_handled()
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
print(try_select_nearest_card(selection_position, Vector2.LEFT))
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
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
elif event.is_action_pressed("ui_accept"): # select the selected note it elif event.is_action_pressed("ui_accept"): # select the selected note it
if dropzone.get_child(current_dropzone_id) is Card: if current_context == ASSIGN:
if not dropzone.get_child(current_dropzone_id) is Card: return
var card:Card = dropzone.get_child(current_dropzone_id) var card:Card = dropzone.get_child(current_dropzone_id)
if current_context == ASSIGN: # to assign it to a card var sticky: StickyNote = currently_active_node if not focus_stickies else sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note
if card.has_sticky_note_attached():
currently_active_node = card.exchange_sticky_note_with(currently_active_node) if card.has_sticky_note_attached():
current_dropzone_id = find_first_free_card() currently_active_node = card.exchange_sticky_note_with(sticky)
else:
card.attach_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note)
current_context = NAVIGATE
current_sticky_note_id += 1
current_dropzone_id = find_first_free_card()
check_board_comnpletion()
else:
if !focus_stickies and card.has_sticky_note_attached():
currently_active_node = card.remove_sticky_note()
add_sticky_note(currently_active_node)
current_dropzone_id = -1
else: current_dropzone_id = find_first_free_card()
current_context = ASSIGN
focus_stickies = !focus_stickies
if focus_stickies:
current_sticky_note_id = current_sticky_note_id
else:
current_dropzone_id = current_dropzone_id
elif dropzone.get_child(current_dropzone_id) is StickyNote:
if currently_active_node is StickyNote:
currently_active_node = dropzone.get_child(current_dropzone_id)
focus_stickies = false focus_stickies = false
if not try_select_nearest_empty_card(currently_active_node.global_position):
current_dropzone_id = find_first_free_card()
else:
card.attach_sticky_note(sticky)
current_context = NAVIGATE
for panel: StickyNotePanel in sticky_note_container.get_children():
panel.clear_if_empty()
if not try_select_nearest_empty_card(currently_active_node.global_position):
current_dropzone_id = find_first_free_card()
check_board_comnpletion()
if focus_stickies:
focus_stickies = false
current_dropzone_id = current_dropzone_id
else:
focus_stickies = true
current_sticky_note_id -= 1
elif current_context == NAVIGATE:
if focus_stickies:
# this is kind of redundant, but a safety feature to avoid active node and index misaligning.
currently_active_node = sticky_note_container.get_children()[current_sticky_note_id].get_child(0)
current_context = ASSIGN current_context = ASSIGN
current_dropzone_id += 1 focus_stickies = false
currently_active_node.is_dragable = false if not try_select_nearest_empty_card(currently_active_node.global_position):
currently_active_node.z_index = 1 current_dropzone_id = find_first_free_card()
else:
if currently_active_node is StickyNote:
add_sticky_note(currently_active_node)
current_sticky_note_id = sticky_note_container.get_child_count()-1
current_context = ASSIGN
focus_stickies = false
if currently_active_node is Card:
if currently_active_node.has_sticky_note_attached():
currently_active_node = currently_active_node.remove_sticky_note()
add_sticky_note(currently_active_node)
current_sticky_note_id = sticky_note_container.get_child_count()-1
focus_stickies = true
else:
if not is_board_complete():
current_context = ASSIGN
focus_stickies = true
current_sticky_note_id = current_sticky_note_id
#
# else:
# if current_context == ASSIGN:
# if not dropzone.get_child(current_dropzone_id) is Card: return
# var card:Card = dropzone.get_child(current_dropzone_id)
#
# if dropzone.get_child(current_dropzone_id) is Card:
# var card:Card = dropzone.get_child(current_dropzone_id)
# if current_context == ASSIGN: # to assign it to a card
# if card.has_sticky_note_attached():
# currently_active_node = card.exchange_sticky_note_with(currently_active_node)
# if not try_select_nearest_empty_card(currently_active_node.global_position):
# current_dropzone_id = find_first_free_card()
# else:
# card.attach_sticky_note(sticky_note_container.get_child(current_sticky_note_id).attached_sticky_note)
# current_context = NAVIGATE
# for panel: StickyNotePanel in sticky_note_container.get_children():
# panel.clear_if_empty()
# focus_stickies = not focus_stickies
# if not try_select_nearest_empty_card(currently_active_node.global_position):
# current_dropzone_id = find_first_free_card()
# check_board_comnpletion()
# return
# else:
# if !focus_stickies and card.has_sticky_note_attached():
# pass
# else:
# if not try_select_nearest_empty_card(currently_active_node.global_position):
# current_dropzone_id = find_first_free_card()
#
# current_context = ASSIGN
# focus_stickies = !focus_stickies
# if focus_stickies:
# current_sticky_note_id = current_sticky_note_id
# else:
# current_dropzone_id = current_dropzone_id
# elif dropzone.get_child(current_dropzone_id) is StickyNote:
# if currently_active_node is StickyNote:
# currently_active_node = dropzone.get_child(current_dropzone_id)
# focus_stickies = false
# current_context = ASSIGN
# current_dropzone_id += 1
# currently_active_node.is_dragable = false
# currently_active_node.z_index = 1
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
# 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
@ -496,9 +577,14 @@ func find_first_free_card() -> int:
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(at_id: int):
if current_sticky_note_id == sticky_note_container.get_child_count() - 1: if current_sticky_note_id == at_id:
current_sticky_note_id -= 1 current_sticky_note_id += 1
if current_sticky_note_id == sticky_note_container.get_child_count()-1:
if current_sticky_note_id-1 != at_id:
current_sticky_note_id -= 1
else:
current_sticky_note_id += 1
func get_save_dict() -> Dictionary: func get_save_dict() -> Dictionary:
var cards: Dictionary = {} var cards: Dictionary = {}
@ -633,3 +719,64 @@ func validate_card(card: Card) -> CardBoard.Error:
if not card.owner == self: if not card.owner == self:
return Error.ILLEGAL_STATE return Error.ILLEGAL_STATE
return CardBoard.Error.OK return CardBoard.Error.OK
func try_select_nearest_card(from: Vector2, towards: Vector2, include_stickies: bool = false) -> bool:
var selection_transform = Transform2D(0, from).looking_at(from+towards)
var scores: Dictionary[int, Area2D] = {-1: null}
for child:Area2D in dropzone.get_children():
if not (child is StickyNote and current_context == ASSIGN):
scores[get_distance_score(child.global_position, selection_transform)] = child
scores.erase(-1)
scores.sort()
if include_stickies:
var panel_scores: Dictionary[int, StickyNotePanel] = {-1: null}
for child:StickyNotePanel in sticky_note_container.get_children():
if not child.is_empty():
panel_scores[get_distance_score(child.attached_sticky_note.global_position, selection_transform)] = child
panel_scores.erase(-1)
panel_scores.sort()
if panel_scores != {}:
if scores != {}:
if panel_scores.keys()[0] < scores.keys()[0]:
if current_context == ASSIGN: return false
current_sticky_note_id = sticky_note_container.get_children().find(panel_scores.values()[0])
focus_stickies = true
return true
else:
if current_context == ASSIGN: return false
current_sticky_note_id = sticky_note_container.get_children().find(panel_scores.values()[0])
focus_stickies = true
return true
if scores != {}:
current_dropzone_id = dropzone.get_children().find(scores.values()[0])
return true
return false
func try_select_nearest_empty_card(from: Vector2) -> bool:
var scores: Dictionary[int, Area2D] = {}
for card in dropzone.get_children():
if card is Card:
if not card.has_sticky_note_attached():
scores[int((from-card.global_position).length())] = card
scores.sort()
if scores != {}:
current_dropzone_id = dropzone.get_children().find(scores.values()[0])
return true
return false
func get_distance_score(from: Vector2, to: Transform2D) -> int:
var diff = from * to
var dir = diff.normalized()
if dir.x > 0.5 and diff.length() > 0:
return int((abs(dir.y) + 0.5) * diff.length())
else:
return -1

View File

@ -280,11 +280,13 @@ func preview_sticky_note(sticky_note: StickyNote):
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.position = sticky_note_position sticky_note.position = sticky_note_position
sticky_note.on_board = false sticky_note.on_board = false
sticky_note.is_dragable = false sticky_note.is_dragable = false
current_sticky_note = sticky_note current_sticky_note = sticky_note
var former_parent = sticky_note.attached_to
sticky_note.attached_to = self sticky_note.attached_to = self
if name == "c_hit" and sticky_note.name == "c_effort" and Steamworks.has_initialized: if name == "c_hit" and sticky_note.name == "c_effort" and Steamworks.has_initialized:

View File

@ -72,6 +72,7 @@ func collapse_gap():
func reclaim_sticky_note() -> bool: func reclaim_sticky_note() -> bool:
if is_empty() and attached_sticky_note.attached_to != Card: if is_empty() and attached_sticky_note.attached_to != Card:
is_attatching = true
attached_sticky_note.on_board = false attached_sticky_note.on_board = false
attached_sticky_note.tween_transform_to(Transform2D(0, get_screen_position() + ancor_position)) attached_sticky_note.tween_transform_to(Transform2D(0, get_screen_position() + ancor_position))
await attached_sticky_note.transform_tween_finished await attached_sticky_note.transform_tween_finished
@ -79,16 +80,19 @@ func reclaim_sticky_note() -> bool:
attached_sticky_note.reparent(self) attached_sticky_note.reparent(self)
attached_sticky_note.attached_to = self attached_sticky_note.attached_to = self
attached_sticky_note.owner = self.owner attached_sticky_note.owner = self.owner
is_attatching = false
return true return true
return false return false
var invalid: bool = false
func clear_if_empty(): func clear_if_empty():
if !is_empty(): return if !is_empty(): return
invalid = true
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(get_parent().get_children().find(self))
self.queue_free() self.queue_free()
func replace_sticky_note_with(new_sticky_note: StickyNote): func replace_sticky_note_with(new_sticky_note: StickyNote):