frame-of-mind/src/logic-scenes/board/card-board.gd

372 lines
16 KiB
GDScript3
Raw Normal View History

extends PanelContainer
var area_dict = {
"dropzone_content": [],
"cards": [],
"post_its_in_list": [],
"post_it_panels": []
}
2023-07-02 13:10:33 +00:00
enum ui_context {DROPZONE, POST_IT_LIST, ASSIGN_POST_IT}
var has_stage = false:
2023-07-11 13:04:46 +00:00
set(focus):
if focus:
has_stage = true
self.mouse_filter = Control.MOUSE_FILTER_PASS
else:
has_stage = false
self.mouse_filter = Control.MOUSE_FILTER_IGNORE
if is_node_ready():
for child in area_dict["dropzone_content"]+area_dict["post_its_in_list"]:
if focus:
child.process_mode = Node.PROCESS_MODE_INHERIT
else:
child.process_mode = Node.PROCESS_MODE_DISABLED
2023-07-11 13:04:46 +00:00
@onready var dropzone = $HBoxContainer/dropzone
@onready var postit_container = $HBoxContainer/ScrollContainer/VBoxContainer
@onready var board_of_devs = $"board of devs"
@onready var base_postit_panel = $HBoxContainer/ScrollContainer/VBoxContainer/Panel
2023-07-02 13:10:33 +00:00
@onready var active_context = ui_context.DROPZONE # 0 = dropzone, 1 = post it list
var currently_selected_node: Area2D = null
2023-07-02 13:10:33 +00:00
var currently_selected_card_for_assigning: Area2D = null
var is_area_dragged: bool = false
var currently_dragged_area: Area2D
2023-07-02 13:10:33 +00:00
var selected_dropzone_element: int = -1
var selected_postit_list_element: int = 0
var selected_card_for_assignment
# Called when the node enters the scene tree for the first time.
func _ready():
2023-07-02 13:10:33 +00:00
#var test_arr = ["c_Joy","p_effort","c_backlash","c_body","c_hit","p_slut","p_worried_mother","p_cross_friend"]
#var test_arr = ["c_Joy","c_body","c_hit"]
#populate_board(test_arr)
#reorder_areas("dropzone_content")
2023-07-02 13:10:33 +00:00
active_context = ui_context.DROPZONE
has_stage = has_stage
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# Reset information about Areas being dragged, if the mouse is not longer pressed.
# Needed because otherwise it can happen that the areas don't register it if you stop clicking on them.
if has_stage and !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and is_area_dragged:
currently_dragged_area.is_dragged = false
is_area_dragged = false
currently_dragged_area = null
# we should maybe consider moving this to _input() for consistency
if Input.is_action_just_pressed("ui_cancel"):
populate_board(["c_Joy","p_effort","c_backlash","c_body","c_hit","p_slut","p_worried_mother","p_cross_friend"])
2023-07-02 13:10:33 +00:00
# Will be used later to spawn Cards and Post-Its and remember them in the dictionary
func populate_board(card_names: Array):
var all_cards = Array()
var all_postits = Array()
# to remember panel positions
area_dict["post_it_panels"] = [base_postit_panel]
# check how many post-it panels we need
var amount = -1 # starting with -1 to compensate for the base panel
for card_name in card_names:
if "p_" in card_name:
amount += 1
while amount > 0: # creating panels up to the number of post-its
var new_panel = base_postit_panel.duplicate()
postit_container.add_child(new_panel)
new_panel.set_owner(self)
area_dict["post_it_panels"].push_back(new_panel)
amount -= 1
# get all the cards and post-its from the board of devs
for child in board_of_devs.get_children():
for child_2 in child.get_children(): # put all cards in all_cards array
all_cards.push_back(child_2)
for child_3 in child_2.get_children(): # put all post-its in all_postits array
if "p_" in child_3.name: # post-its are currently children of cards.
all_postits.push_back(child_3) # If this changes, this logic needs to be adjusted.
# spawning the cards and adding them to the dictionary
for card_name in card_names:
if "c_" in card_name: # spawning a card
var new_card = _find_area_by_string(all_cards, card_name).duplicate()
for child in new_card.get_children(): # We need to clear all the post-its from the cards on the dev-board
if "p_" in child.name:
new_card.remove_child(child) # dev-board has post-its attached to the cards, which need to be removed
new_card.position = Vector2(randi_range(0, dropzone.size.x), randi_range(0, dropzone.size.y))
dropzone.add_child(new_card)
new_card.set_owner(self)
area_dict["dropzone_content"].push_back(new_card)
area_dict["cards"].push_back(new_card)
#new_card.position = Vector2(randf_range(new_card.diameter, dropzone.size.x), randf_range(new_card.diameter, dropzone.size.y)) - Vector2(new_card.diameter/2, new_card.diameter/2)
new_card.is_dragable = true
if "p_" in card_name: # spawning a post-it
var new_postit = _find_area_by_string(all_postits, card_name).duplicate()
for panel in area_dict["post_it_panels"]: # still mad I can't use the return_postit-func for this...
if panel.get_child_count() == 1:
panel.add_child(new_postit)
new_postit.set_owner(self)
area_dict["post_its_in_list"].push_back(new_postit)
new_postit.position = panel.get_child(0).position
new_postit.is_dragable = true
break
currently_selected_node = area_dict["dropzone_content"][0] # set first Card as currently selected node by default
reorder_areas("dropzone_content")
reorder_areas("cards")
reorder_areas("post_its_in_list")
2023-07-02 13:10:33 +00:00
# Handy function to filter an array of areas by the name of a card
func _find_area_by_string(area_arr: Array, name: String) -> Area2D:
for area in area_arr:
if area.name == name:
return area
return null
# Checks if a Node is currently inside the dropzone
func is_in_dropzone(to_check: Node) -> bool:
2023-07-02 13:10:33 +00:00
if (dropzone.size.x < to_check.global_position.x or dropzone.size.y < to_check.global_position.y):
return false
2023-07-02 13:10:33 +00:00
elif (to_check.global_position.x < 0 or to_check.global_position.y < 0):
return false
else:
return true
# called if a mouse button is pressed
func handle_mouse_button(to_handle: Area2D, input: InputEvent):
# No two areas can be dragged at the same time.
# Make sure that only the same area is dragged.
# Otherwise overlapping areas are dragged at the same time.
if currently_dragged_area != null and to_handle != currently_dragged_area:
return
currently_selected_node = to_handle # update currently selected
currently_dragged_area = to_handle
to_handle.is_dragged = input.pressed
is_area_dragged = input.pressed
# TODO: We need a better way to recognize whether "to_handle" is a Card or a Post-It.
# (Tried checking for a script, didn't work, because script has no name attached.
# Alternative might be to check for specific values within the script ("is_card" f.e))
match to_handle.get_meta("type"):
"card": # 1 = Card
2023-07-02 13:10:33 +00:00
active_context = ui_context.DROPZONE
if input.is_pressed():
reorder_areas("dropzone_content")
reorder_areas("cards")
else:
dropzone.move_child(currently_dragged_area, -1)
currently_dragged_area = null
"post-it": # 2 = PostIt
if input.is_pressed():
to_handle.reparent(dropzone)
to_handle.set_owner(self) # needs to be here otherwise the owner disappears
area_dict["post_its_in_list"].erase(to_handle)
area_dict["dropzone_content"].push_back(to_handle)
# TODO (if needed): Add function to rearrange the array based on positions in the dropzone
else:
2023-07-01 14:03:22 +00:00
if is_in_dropzone(to_handle):
2023-07-02 13:10:33 +00:00
if to_handle.has_overlapping_areas():
for area in to_handle.get_overlapping_areas():
if area.get_meta("type") == "card":
if !area.has_postit_attached():
attach_postit_to_card(to_handle, area)
else:
to_handle.rotation = to_handle.base_rotation
to_handle.scale = to_handle.base_scale
2023-07-02 13:10:33 +00:00
else:
active_context = ui_context.POST_IT_LIST
_return_postit_to_panels(to_handle)
currently_dragged_area = null
2023-07-02 13:10:33 +00:00
# Logic for attaching a postit to a card. Also reset postit positions if the card cannot be attached
func attach_postit_to_card(postit: Area2D, card: Area2D, update_dict = false):
if card.has_postit_attached():
if active_context == ui_context.ASSIGN_POST_IT:
_return_postit_to_panels(postit) # don't attach if card has already a post-it attached
return
2023-07-02 13:10:33 +00:00
postit.reparent(card)
postit.set_owner(self)
postit.position = card.get_child(3).position
if update_dict:
area_dict["post_its_in_list"].erase(postit)
area_dict["dropzone_content"].push_back(postit)
2023-07-02 13:10:33 +00:00
reorder_areas("dropzone_content")
reorder_areas("cards")
2023-07-02 13:10:33 +00:00
reorder_areas("post_its_in_list")
# Mark area that was hovered over as currently selected
func handle_hover(to_handle: Area2D):
if to_handle != currently_selected_node:
currently_selected_node.highlighted = false
currently_selected_node = to_handle
2023-07-02 13:10:33 +00:00
if is_in_dropzone(to_handle):
selected_dropzone_element = area_dict["dropzone_content"].find(to_handle)
active_context = ui_context.DROPZONE
else:
selected_postit_list_element = area_dict["post_its_in_list"].find(to_handle)
active_context = ui_context.POST_IT_LIST
# Reorders the areas in any of the dictionaries entries
# Pass the entry's key in order to reorder it
func reorder_areas(reorder: String):
var old_order = area_dict[reorder]
var new_order = Array()
for obj in old_order:
var i = 0
if !new_order.is_empty():
for obj_2 in new_order:
if obj_2.global_position.y < obj.global_position.y:
i += 1
new_order.insert(i, obj)
area_dict[reorder] = new_order
2023-07-02 13:10:33 +00:00
# Takes the inputs for control inputs
func _input(event):
# 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_selected_node): return
2023-07-02 13:10:33 +00:00
if event.is_action_pressed("ui_up"): # up to select an element above
match active_context:
ui_context.DROPZONE:
selected_dropzone_element -= 1
ui_context.POST_IT_LIST:
selected_postit_list_element -= 1
ui_context.ASSIGN_POST_IT:
selected_card_for_assignment -= 1
elif event.is_action_pressed("ui_down"): # down to select an element beneath
match active_context:
ui_context.DROPZONE:
selected_dropzone_element += 1
ui_context.POST_IT_LIST:
selected_postit_list_element += 1
ui_context.ASSIGN_POST_IT:
selected_card_for_assignment += 1
elif event.is_action_pressed("ui_left"): # left to switch context to the left
active_context -= 1
if active_context < -1:
2023-07-02 13:10:33 +00:00
active_context = ui_context.POST_IT_LIST
elif event.is_action_pressed("ui_right"): # right to switch context to the right
active_context += 1
if active_context > 1:
2023-07-02 13:10:33 +00:00
active_context = ui_context.DROPZONE
elif event.is_action_pressed("ui_accept"): # select the selected post it
2023-07-02 13:10:33 +00:00
if active_context == ui_context.ASSIGN_POST_IT: # to assign it to a card
attach_postit_to_card(currently_selected_node,
currently_selected_card_for_assigning, false)
2023-07-02 13:10:33 +00:00
_leave_assignment_context()
else:
_enter_assignment_context()
# TODO: I forgor the HECKING RIGHT-CLICK!!!!111 AAAAAAAAAAAAAAAAAAAA
2023-07-02 13:10:33 +00:00
# do some adjustments to loop elements (after last element, select first one etc.)
if selected_dropzone_element < 0:
selected_dropzone_element = area_dict["dropzone_content"].size()-1
elif selected_dropzone_element > area_dict["dropzone_content"].size()-1:
selected_dropzone_element = 0
if selected_postit_list_element < 0:
selected_postit_list_element = area_dict["post_its_in_list"].size()-1
elif selected_postit_list_element > area_dict["post_its_in_list"].size()-1:
selected_postit_list_element = 0
if active_context == ui_context.ASSIGN_POST_IT: # skip this if we're not in assign post it context
if selected_card_for_assignment < 0:
selected_card_for_assignment = area_dict["cards"].size()-1
elif selected_card_for_assignment > area_dict["cards"].size()-1:
2023-07-02 13:10:33 +00:00
selected_card_for_assignment = 0
# highlight the selected element
match active_context:
ui_context.DROPZONE:
currently_selected_node.highlighted = false
currently_selected_node = area_dict["dropzone_content"][selected_dropzone_element]
currently_selected_node.highlighted = true
ui_context.POST_IT_LIST:
currently_selected_node.highlighted = false
currently_selected_node = area_dict["post_its_in_list"][selected_postit_list_element]
currently_selected_node.highlighted = true
ui_context.ASSIGN_POST_IT:
currently_selected_card_for_assigning.highlighted = false
currently_selected_card_for_assigning = area_dict["cards"][selected_card_for_assignment]
2023-07-02 13:10:33 +00:00
currently_selected_card_for_assigning.highlighted = true
_select_card_for_assigning(currently_selected_node, currently_selected_card_for_assigning)
2023-07-02 13:10:33 +00:00
# update dictiornary orders
reorder_areas("dropzone_content")
reorder_areas("post_its_in_list")
# Sets everything up to enter the context where postits can be assigned via button controls
func _enter_assignment_context():
# cards are currently not moved, only post its. Exit function if a card should be moved.
if currently_selected_node == null or currently_selected_node.get_meta("type") != "post-it" : return
# if the postit is already attached, remove it and return it to the post it panels
if currently_selected_node.is_postit_attached():
_return_postit_to_panels(currently_selected_node)
active_context = ui_context.POST_IT_LIST
return
# adjust everything for the post it to select its attach-target
active_context = ui_context.ASSIGN_POST_IT
selected_card_for_assignment = 0
currently_selected_node.reparent(dropzone) # reparent to make it visible
currently_selected_node.set_owner(self)
area_dict["post_its_in_list"].erase(currently_selected_node)
area_dict["dropzone_content"].push_back(currently_selected_node)
2023-07-02 13:10:33 +00:00
currently_selected_card_for_assigning = area_dict["dropzone_content"][0]
currently_selected_card_for_assigning.highlighted = true
# move the post it so it floats next to the card where it should be attached
func _select_card_for_assigning(post_it: Area2D, card: Area2D):
post_it.tween_transform_to(card.get_child(3).global_position + Vector2(0, 50))
2023-07-02 13:10:33 +00:00
# leaves the context for assigning postit via button controls
func _leave_assignment_context():
currently_selected_node.highlighted = false
active_context = ui_context.DROPZONE
currently_selected_node = currently_selected_card_for_assigning
# handles everything to return a post it to the panels
func _return_postit_to_panels(post_it: Area2D):
2023-07-02 13:10:33 +00:00
for panel in area_dict["post_it_panels"]:
if panel.get_child_count() == 1:
area_dict["dropzone_content"].erase(post_it)
area_dict["post_its_in_list"].push_back(post_it)
post_it.tween_transform_to(panel.get_child(0).position)
post_it.rotation = post_it.base_rotation
post_it.scale = post_it.base_scale
post_it.reparent(panel)
post_it.set_owner(self)
2023-07-02 13:10:33 +00:00
reorder_areas("dropzone_content")
reorder_areas("post_its_in_list")
break