234 lines
6.7 KiB
GDScript
234 lines
6.7 KiB
GDScript
class_name MainMenuController
|
|
extends RefCounted
|
|
|
|
const UiMotionScript := preload("res://scripts/ui/common/ui_motion.gd")
|
|
|
|
const ACTION_SHOP := "shop"
|
|
const ACTION_WAREHOUSE := "warehouse"
|
|
const ACTION_FRIEND := "friend"
|
|
const HOME_POSITION := Vector2(24.0, 34.0)
|
|
const HOME_SIZE := Vector2(155.0, 145.0)
|
|
const WAVE_CENTER := Vector2(77.5, 72.5)
|
|
const WAVE_RADIUS := 155.0
|
|
const HIDDEN_POSITION := Vector2(1000.0, 1000.0)
|
|
|
|
var _owner: Control
|
|
var _menu: Control
|
|
var _home_art: TextureRect
|
|
var _home_texture: Texture2D
|
|
var _item_textures: Dictionary = {}
|
|
var _style_menu_title: Callable
|
|
var _hide_selection: Callable
|
|
var _action_pressed: Callable
|
|
var _dismiss_button: Button
|
|
var _home_hit: Button
|
|
var _buttons: Array[TextureButton] = []
|
|
var _tween: Tween
|
|
var _open := false
|
|
|
|
|
|
func setup(owner: Control, menu: Control, home_art: TextureRect, home_texture: Texture2D, item_textures: Dictionary, style_menu_title: Callable, hide_selection: Callable, action_pressed: Callable) -> void:
|
|
_owner = owner
|
|
_menu = menu
|
|
_home_art = home_art
|
|
_home_texture = home_texture
|
|
_item_textures = item_textures
|
|
_style_menu_title = style_menu_title
|
|
_hide_selection = hide_selection
|
|
_action_pressed = action_pressed
|
|
_setup()
|
|
|
|
|
|
func toggle() -> void:
|
|
if _open:
|
|
hide(true)
|
|
return
|
|
if _hide_selection.is_valid():
|
|
_hide_selection.call()
|
|
show()
|
|
|
|
|
|
func hide(animated := false) -> void:
|
|
if _menu == null:
|
|
return
|
|
if not _open and not animated:
|
|
_finish_hide()
|
|
return
|
|
if _tween != null:
|
|
_tween.kill()
|
|
_open = false
|
|
if animated:
|
|
for button in _buttons:
|
|
button.disabled = true
|
|
_tween = _owner.create_tween()
|
|
_tween.tween_method(Callable(self, "_apply_wave_angle"), 275.0, 135.0, 0.35)
|
|
_tween.tween_callback(_finish_hide)
|
|
return
|
|
_finish_hide()
|
|
|
|
|
|
func is_open() -> bool:
|
|
return _open
|
|
|
|
|
|
func handle_direct_hit(screen_position: Vector2) -> bool:
|
|
if _menu == null:
|
|
return false
|
|
if _control_contains(_home_hit, screen_position):
|
|
toggle()
|
|
return true
|
|
if not _open:
|
|
return false
|
|
for button in _buttons:
|
|
if button == null or not button.visible or button.disabled:
|
|
continue
|
|
if _control_contains(button, screen_position):
|
|
_on_item_pressed(str(button.get_meta("action", "")))
|
|
return true
|
|
hide(true)
|
|
return true
|
|
|
|
|
|
func _setup() -> void:
|
|
if _owner == null or _menu == null:
|
|
return
|
|
if _home_art != null:
|
|
_home_art.texture = _home_texture
|
|
_home_art.size = HOME_SIZE
|
|
_home_art.pivot_offset = HOME_SIZE * 0.5
|
|
_home_art.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
_dismiss_button = Button.new()
|
|
_dismiss_button.name = "MainMenuDismissHit"
|
|
_dismiss_button.set_anchors_preset(Control.PRESET_FULL_RECT)
|
|
_dismiss_button.focus_mode = Control.FOCUS_NONE
|
|
_dismiss_button.text = ""
|
|
_dismiss_button.visible = false
|
|
UiMotionScript.apply_empty_button_style(_dismiss_button)
|
|
_dismiss_button.pressed.connect(func() -> void: hide(true))
|
|
_owner.add_child(_dismiss_button)
|
|
_owner.move_child(_dismiss_button, _owner.get_child_count() - 1)
|
|
_owner.move_child(_menu, _owner.get_child_count() - 1)
|
|
|
|
_create_item(ACTION_SHOP, _item_textures.get(ACTION_SHOP), 0)
|
|
_create_item(ACTION_WAREHOUSE, _item_textures.get(ACTION_WAREHOUSE), 1)
|
|
_create_item(ACTION_FRIEND, _item_textures.get(ACTION_FRIEND), 3)
|
|
_finish_hide()
|
|
|
|
_home_hit = Button.new()
|
|
_home_hit.name = "HomeMenuHit"
|
|
_home_hit.position = HOME_POSITION
|
|
_home_hit.size = HOME_SIZE
|
|
_home_hit.focus_mode = Control.FOCUS_NONE
|
|
_home_hit.text = ""
|
|
UiMotionScript.apply_empty_button_style(_home_hit)
|
|
_home_hit.pressed.connect(toggle)
|
|
if _home_art != null:
|
|
_home_hit.button_down.connect(func() -> void: UiMotionScript.play_press_scale(_owner, _home_art))
|
|
_home_hit.button_up.connect(func() -> void: UiMotionScript.play_release_scale(_owner, _home_art))
|
|
_menu.add_child(_home_hit)
|
|
|
|
|
|
func _create_item(action: String, texture: Texture2D, wave_index: int) -> void:
|
|
if texture == null:
|
|
return
|
|
var button := TextureButton.new()
|
|
button.name = "MainMenu%s" % action.capitalize()
|
|
button.texture_normal = texture
|
|
button.size = texture.get_size()
|
|
button.pivot_offset = button.size * 0.5
|
|
button.focus_mode = Control.FOCUS_NONE
|
|
button.visible = false
|
|
button.disabled = true
|
|
button.position = HIDDEN_POSITION
|
|
button.set_meta("wave_index", wave_index)
|
|
button.set_meta("action", action)
|
|
button.pressed.connect(_on_item_pressed.bind(action))
|
|
button.button_down.connect(func() -> void: UiMotionScript.play_press_scale(_owner, button))
|
|
button.button_up.connect(func() -> void: UiMotionScript.play_release_scale(_owner, button))
|
|
_add_item_title(button, action)
|
|
_menu.add_child(button)
|
|
_buttons.append(button)
|
|
|
|
|
|
func _add_item_title(button: TextureButton, action: String) -> void:
|
|
var title_text := _item_title(action)
|
|
if title_text.is_empty():
|
|
return
|
|
var title := Label.new()
|
|
title.name = "Title"
|
|
title.text = title_text
|
|
var label_width := 118.0 if action == ACTION_WAREHOUSE else 98.0
|
|
title.position = Vector2((button.size.x - label_width) * 0.5, button.size.y - 27.0)
|
|
title.size = Vector2(label_width, 30.0)
|
|
title.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
title.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
title.clip_text = false
|
|
if _style_menu_title.is_valid():
|
|
_style_menu_title.call(title, 18 if action == ACTION_WAREHOUSE else 20)
|
|
button.add_child(title)
|
|
|
|
|
|
func _item_title(action: String) -> String:
|
|
match action:
|
|
ACTION_SHOP:
|
|
return "Store"
|
|
ACTION_WAREHOUSE:
|
|
return "Storage"
|
|
ACTION_FRIEND:
|
|
return "Friends"
|
|
_:
|
|
return ""
|
|
|
|
|
|
func show() -> void:
|
|
if _menu == null:
|
|
return
|
|
if _tween != null:
|
|
_tween.kill()
|
|
_open = true
|
|
if _dismiss_button != null:
|
|
_dismiss_button.visible = true
|
|
for button in _buttons:
|
|
button.visible = true
|
|
button.disabled = false
|
|
button.scale = Vector2.ONE
|
|
button.modulate = Color.WHITE
|
|
_apply_wave_angle(180.0)
|
|
_tween = _owner.create_tween()
|
|
_tween.tween_method(Callable(self, "_apply_wave_angle"), 180.0, 280.0, 0.25)
|
|
|
|
|
|
func _finish_hide() -> void:
|
|
if _dismiss_button != null:
|
|
_dismiss_button.visible = false
|
|
for button in _buttons:
|
|
button.visible = false
|
|
button.disabled = true
|
|
button.position = HIDDEN_POSITION
|
|
button.scale = Vector2.ONE
|
|
button.modulate = Color.WHITE
|
|
|
|
|
|
func _apply_wave_angle(angle: float) -> void:
|
|
for button in _buttons:
|
|
var wave_index := int(button.get_meta("wave_index", 0))
|
|
var radians := deg_to_rad(angle - 36.0 * float(wave_index))
|
|
button.position = Vector2(
|
|
WAVE_RADIUS * cos(radians) + WAVE_CENTER.x,
|
|
WAVE_RADIUS * sin(radians) + WAVE_CENTER.y
|
|
)
|
|
|
|
|
|
func _on_item_pressed(action: String) -> void:
|
|
if action.is_empty():
|
|
return
|
|
hide(true)
|
|
if _action_pressed.is_valid():
|
|
_action_pressed.call(action)
|
|
|
|
|
|
func _control_contains(control: Control, screen_position: Vector2) -> bool:
|
|
return control != null and control.is_visible_in_tree() and control.get_global_rect().has_point(screen_position)
|