diff --git a/src/logic-scenes/board/card-board.gd b/src/logic-scenes/board/card-board.gd index 738b58f..56e62b1 100644 --- a/src/logic-scenes/board/card-board.gd +++ b/src/logic-scenes/board/card-board.gd @@ -49,8 +49,8 @@ var dropzone_size: Vector2 @onready var sticky_note_container = $HBoxContainer/ScrollContainer/VBoxContainer @onready var current_context:int = NAVIGATE: set(context): - if current_context == ASSIGN and !context == ASSIGN: - sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() + #if current_context == ASSIGN and !context == ASSIGN: + # sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() #match context: # NAVIGATE: # _return_sticky_notes_to_panels() @@ -102,14 +102,21 @@ var mementos_collected: int = 0: @onready var current_sticky_note_id: int = 0: set(new_id): 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 < 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 if current_context == ASSIGN: _return_sticky_notes_to_panels() 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: currently_active_node = sticky_note_container.get_child(current_sticky_note_id).get_child(0) else: @@ -286,7 +293,7 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act 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(): panel.reclaim_sticky_note() @@ -366,9 +373,10 @@ func handle_hover(to_handle: Area2D): currently_active_node = to_handle if is_in_dropzone(to_handle) or to_handle is Card: - if not (to_handle is StickyNote and !to_handle.on_board): - current_dropzone_id = dropzone.get_children().find(to_handle) - focus_stickies = false + if not (current_context == ASSIGN and not currently_active_node.is_dragged): #Prevent Mouse input from messing up directional control selections + if not (to_handle is StickyNote and !to_handle.on_board): + current_dropzone_id = dropzone.get_children().find(to_handle) + focus_stickies = false else: current_sticky_note_id = sticky_note_container.get_children().find(to_handle.attached_to) focus_stickies = true @@ -413,70 +421,143 @@ func _input(event): return 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 focus_stickies: current_sticky_note_id -= 1 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() elif event.is_action_pressed("ui_down"): # down to select an element beneath if focus_stickies: current_sticky_note_id += 1 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() elif event.is_action_pressed("ui_right"): # left to switch context to the left - if not focus_stickies: - if current_context == NAVIGATE: - focus_stickies = true - elif current_context == ASSIGN: - current_context = NAVIGATE - get_viewport().set_input_as_handled() + if not try_select_nearest_card(selection_position, Vector2.RIGHT, true): + if not focus_stickies: + if current_context == NAVIGATE: + focus_stickies = true + elif current_context == ASSIGN: + 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 + print(try_select_nearest_card(selection_position, Vector2.LEFT)) if focus_stickies: if current_context == NAVIGATE: focus_stickies = false elif current_context == ASSIGN: 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 - 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) - 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) - 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 - 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) + 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(sticky) 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_dropzone_id += 1 - currently_active_node.is_dragable = false - currently_active_node.z_index = 1 + focus_stickies = false + if not try_select_nearest_empty_card(currently_active_node.global_position): + 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() # 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 -1 -func on_sticky_panel_cleared(): - if current_sticky_note_id == sticky_note_container.get_child_count() - 1: - current_sticky_note_id -= 1 +func on_sticky_panel_cleared(at_id: int): + if current_sticky_note_id == at_id: + 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: var cards: Dictionary = {} @@ -633,3 +719,64 @@ func validate_card(card: Card) -> CardBoard.Error: if not card.owner == self: return Error.ILLEGAL_STATE 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 diff --git a/src/logic-scenes/board/card.gd b/src/logic-scenes/board/card.gd index 528ada1..d2eccdd 100644 --- a/src/logic-scenes/board/card.gd +++ b/src/logic-scenes/board/card.gd @@ -280,11 +280,13 @@ func preview_sticky_note(sticky_note: StickyNote): func attach_sticky_note(sticky_note: StickyNote) -> bool: if has_sticky_note_attached(): return false + sticky_note.reparent(self) sticky_note.position = sticky_note_position sticky_note.on_board = false sticky_note.is_dragable = false current_sticky_note = sticky_note + var former_parent = sticky_note.attached_to sticky_note.attached_to = self if name == "c_hit" and sticky_note.name == "c_effort" and Steamworks.has_initialized: diff --git a/src/logic-scenes/board/empty_sticky_note_panel.gd b/src/logic-scenes/board/empty_sticky_note_panel.gd index e0946d7..03573d5 100644 --- a/src/logic-scenes/board/empty_sticky_note_panel.gd +++ b/src/logic-scenes/board/empty_sticky_note_panel.gd @@ -72,6 +72,7 @@ func collapse_gap(): func reclaim_sticky_note() -> bool: if is_empty() and attached_sticky_note.attached_to != Card: + is_attatching = true attached_sticky_note.on_board = false attached_sticky_note.tween_transform_to(Transform2D(0, get_screen_position() + ancor_position)) await attached_sticky_note.transform_tween_finished @@ -79,16 +80,19 @@ func reclaim_sticky_note() -> bool: attached_sticky_note.reparent(self) attached_sticky_note.attached_to = self attached_sticky_note.owner = self.owner + is_attatching = false return true return false - + +var invalid: bool = false func clear_if_empty(): if !is_empty(): return + invalid = true if attached_sticky_note.attached_to == self: attached_sticky_note.attached_to = null var height_tween: Tween = create_tween() height_tween.tween_property(self, "custom_minimum_size", Vector2.ZERO, 0.3) await height_tween.finished - owner.on_sticky_panel_cleared() + owner.on_sticky_panel_cleared(get_parent().get_children().find(self)) self.queue_free() func replace_sticky_note_with(new_sticky_note: StickyNote):