diff --git a/src/dev-util/devs_board.gd b/src/dev-util/devs_board.gd index 35aa091..dc14a30 100644 --- a/src/dev-util/devs_board.gd +++ b/src/dev-util/devs_board.gd @@ -1,5 +1,6 @@ extends Control +# used to display cards during picking func get_cards_by_scene_id(id: int) -> Array: var output:Array @@ -18,6 +19,7 @@ func get_cards_by_scene_id(id: int) -> Array: return output +# used to put cards on the dev board func get_cards_by_name_array(names: Array) -> Dictionary: var output:Dictionary = { "cards": [], diff --git a/src/logic-scenes/board/card-board.gd b/src/logic-scenes/board/card-board.gd index 1a07d71..450d279 100644 --- a/src/logic-scenes/board/card-board.gd +++ b/src/logic-scenes/board/card-board.gd @@ -1,12 +1,12 @@ class_name CardBoard extends PanelContainer -#var area_dict = { -# "dropzone_content": [], -# "cards": [], -# "sticky_notes_in_list": [], -# "sticky_note_panels": [] -#} enum {NAVIGATE, ASSIGN, DRAG} +enum Error { + OK, + OUT_OF_BOUNDS, + ILLEGAL_STATE, + MISSING +} var focus_stickies:bool = true: set(stickies): @@ -57,6 +57,7 @@ var dropzone_size: Vector2 # pass current_context = context @onready var instructions = $instructions_panel/HBoxContainer/cards_remaining +@onready var timer: Timer = $Timer var mementos_collected: int = 0: set(mementos): @@ -110,7 +111,8 @@ var mementos_collected: int = 0: if sticky_note_container.get_child(i).get_child_count() == 1: currently_active_node = sticky_note_container.get_child(i).get_child(0) -var cache: Array = [] +var last_save_dict: Dictionary +var text_recovery: Dictionary signal board_completed @@ -128,6 +130,12 @@ func _ready(): has_stage = has_stage get_viewport().gui_focus_changed.connect(reclaim_lost_focus) + + timer.timeout.connect(validate_board) + timer.start() + + await get_tree().process_frame + last_save_dict = get_save_dict() func reclaim_lost_focus(): @@ -212,9 +220,10 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act return else: area.attach_sticky_note(to_handle) - sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() + if sticky_note_container.get_child_count() > 0: + sticky_note_container.get_child(current_sticky_note_id).clear_if_empty() current_context = NAVIGATE - if is_board_complete(): emit_signal("board_completed") + if is_board_complete(): board_completed.emit() return else: var i: int = 0 @@ -234,7 +243,10 @@ func handle_mouse_button(input: InputEventMouseButton, to_handle = currently_act ## Dropping Cards and Sticky Notes not causing a return condition above. if not (to_handle is StickyNote and to_handle.is_sticky_note_attached()): - insert_area(dropzone, to_handle) + if to_handle.get_parent() is Card: + insert_area(to_handle.get_parent().remove_sticky_note(), to_handle) + else: + insert_area(dropzone, to_handle) current_context = NAVIGATE focus_stickies = false current_dropzone_id = dropzone.get_children().find(to_handle) @@ -294,6 +306,9 @@ func insert_area(parent: Control, node: Area2D): while children[i].global_position.y < node.global_position.y and i+1 < children.size(): i+=1 parent.move_child(node, i) + + if node is StickyNote: + node.attached_to = self # Takes the inputs for control inputs func _input(event): @@ -389,7 +404,6 @@ func on_sticky_panel_cleared(): if current_sticky_note_id == sticky_note_container.get_child_count() - 1: current_sticky_note_id -= 1 - func get_save_dict() -> Dictionary: var cards: Dictionary = {} var stickies: Dictionary = {} @@ -410,10 +424,15 @@ func get_save_dict() -> Dictionary: "stickies": stickies } if cards != {} and stickies != {} else {} + func initialise_from_save(savegame: SaveGame): + last_save_dict = savegame.board_state.duplicate() if savegame.board_state == {}: return - var cards: Dictionary = savegame.board_state["cards"] - var stickies: Dictionary = savegame.board_state["stickies"] + rebuild_from_savedict(savegame.board_state) + +func rebuild_from_savedict(board_state:Dictionary): + var cards: Dictionary = board_state["cards"] + var stickies: Dictionary = board_state["stickies"] var card_pile = board_of_devs.get_cards_by_name_array(cards.keys() + (stickies.keys())) @@ -421,7 +440,9 @@ func initialise_from_save(savegame: SaveGame): add_card(card) card.transform.origin = cards[card.name] cards[card.name] = card + text_recovery[card.name] = card.text for sticky:StickyNote in card_pile["sticky_notes"]: + text_recovery[sticky.name] = sticky.text if stickies[sticky.name] == -1: add_sticky_note(sticky) if stickies[sticky.name] is String: @@ -429,3 +450,69 @@ func initialise_from_save(savegame: SaveGame): else: insert_area(dropzone, sticky) sticky.transform.origin = stickies[sticky.name] + +func validate_board(): + if current_context == NAVIGATE: + + var needs_rebuild = false + for node in dropzone.get_children(): + if node is Card: + match validate_card(node): + Error.OUT_OF_BOUNDS: + node.position = last_save_dict[node.name] + Error.ILLEGAL_STATE: + needs_rebuild = true + if node is StickyNote: + match validate_sticky(node): + Error.OUT_OF_BOUNDS: + node.position = last_save_dict[node.name] + Error.ILLEGAL_STATE: + needs_rebuild = true + for panel:StickyNotePanel in sticky_note_container.get_children(): + if panel.attached_sticky_note != null: + match validate_sticky(panel.attached_sticky_note): + Error.OUT_OF_BOUNDS: + panel.attached_sticky_note.position = panel.ancor_position + Error.ILLEGAL_STATE: + needs_rebuild = true + + # FIXME: currently, illegal temporary state exists a lot and needs to be rectified before this can be trusted. + if needs_rebuild and false: + remove_child(board_of_devs) + + for child in dropzone.get_children(): child.free() + for child in sticky_note_container.get_children(): child.free() + + board_of_devs = preload("res://dev-util/board of devs.tscn").instantiate() + add_child(board_of_devs) + rebuild_from_savedict(last_save_dict) + + current_dropzone_id = 0 + current_sticky_note_id = 0 + focus_stickies = false + current_context = NAVIGATE + else: + last_save_dict = get_save_dict() + +func validate_sticky(note: StickyNote) -> CardBoard.Error: + if not get_viewport_rect().has_point(note.get_global_transform().origin): + return Error.OUT_OF_BOUNDS + if note.attached_to is StickyNotePanel: + if note.position != note.attached_to.ancor_position: + return Error.OUT_OF_BOUNDS + if (note.on_board and not is_in_dropzone(note)): + return Error.ILLEGAL_STATE + if not ((note.attached_to == self and dropzone.get_children().has(note)) or note.attached_to == note.get_parent()) or note.shift_tween != null: + return Error.ILLEGAL_STATE + + return Error.OK + +func validate_card(card: Card) -> CardBoard.Error: + if not is_in_dropzone(card): + return Error.OUT_OF_BOUNDS + if card.get_attached_sticky_note() != card.current_sticky_note: + #push_error("Card %s claims to have %s as current sticky note but has %s attached." % [card.name, card.current_sticky_note, card.get_attached_sticky_note()]) + return Error.ILLEGAL_STATE + if not card.owner == self: + return Error.ILLEGAL_STATE + return CardBoard.Error.OK diff --git a/src/logic-scenes/board/card.gd b/src/logic-scenes/board/card.gd index e0201ee..163c908 100644 --- a/src/logic-scenes/board/card.gd +++ b/src/logic-scenes/board/card.gd @@ -212,7 +212,7 @@ func remove_sticky_note() -> StickyNote: former_child.reparent(get_parent()) former_child.owner = self.owner former_child.on_board = true - former_child.attached_to = null + former_child.attached_to = owner return former_child func exchange_sticky_note_with(new_note: StickyNote) -> StickyNote: diff --git a/src/logic-scenes/board/physics-board.tscn b/src/logic-scenes/board/physics-board.tscn index 2032b98..6083d18 100644 --- a/src/logic-scenes/board/physics-board.tscn +++ b/src/logic-scenes/board/physics-board.tscn @@ -132,3 +132,5 @@ vertical_alignment = 1 [node name="VSeparator" type="VSeparator" parent="instructions_panel/HBoxContainer"] custom_minimum_size = Vector2(15, 0) layout_mode = 2 + +[node name="Timer" type="Timer" parent="."]