xiandie/scene/journal/journal.gd

143 lines
4.0 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@tool
extends Control
@export var locked := false:
set(val):
locked = val
if is_node_ready() and locked:
display = false
@export var display := false:
set(val):
if is_node_ready() and display != val:
_toggle_display()
display = val
@export var boundart_rect := Rect2(0, 0, 1000, 1000):
set(val):
boundart_rect = val
queue_redraw()
@export_group("Tip", "tip_")
@export var tip_content := "":
set(val):
tip_content = val
if is_node_ready():
reload()
@export var tip_font_size := 12
@export var tip_font_color := Color(1, 1, 1)
@export var tip_item_position := Vector2(220, 220)
@onready var tip_container = $Tips as GridContainer
@onready var items_root = $ItemsRoot as Node2D
var sty_box_empty := StyleBoxEmpty.new()
var item_scene := preload("res://scene/journal/journal_item.tscn")
var tip_script := preload("res://scene/journal/journal_tip.gd")
var item_script := preload("res://scene/journal/journal_item.gd")
var items_dict := {}
func _ready() -> void:
reload()
if GlobalConfig.DEBUG:
locked = false
display = true
else:
locked = true
display = false
_toggle_display(false)
func reload():
for c in tip_container.get_children():
c.queue_free()
for v in items_dict.values():
v.queue_free()
items_dict.clear()
var btn_name_prefix = "tip_btn_"
for i in range(tip_content.length()):
var tip = tip_content[i] as String
var btn_margin = MarginContainer.new()
btn_margin.set("theme_override_constants/margin_left", -5)
btn_margin.set("theme_override_constants/margin_right", -5)
btn_margin.set("theme_override_constants/margin_top", -4)
btn_margin.set("theme_override_constants/margin_bottom", -4)
var tip_btn = Button.new()
tip_btn.flat = true
tip_btn.text = tip
tip_btn.toggle_mode = true
tip_btn.set("theme_override_styles/focus", sty_box_empty)
tip_btn.set("theme_override_font_sizes/font_size", tip_font_size)
tip_btn.custom_minimum_size = Vector2(tip_font_size, tip_font_size)
tip_btn.add_theme_color_override("font_color", tip_font_color)
tip_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
tip_btn.size_flags_vertical = Control.SIZE_SHRINK_CENTER
tip_btn.set_script(tip_script)
tip_btn.toggled.connect(_on_toggle_btn.bind(tip, tip_btn))
tip_btn.name = btn_name_prefix + str(i)
btn_margin.add_child(tip_btn)
tip_container.add_child(btn_margin)
# items_dict[tip] = tip_btn
func _on_toggle_btn(toggled_on: bool, content: String, btn) -> void:
if not toggled_on and items_dict.has(btn.name):
items_dict[btn.name].queue_free()
items_dict.erase(content)
elif toggled_on:
var item = item_scene.instantiate()
item.label_text = content
item.boundart_rect = boundart_rect
item.position = tip_item_position + Vector2(randf_range(-10, 10), randf_range(-10, 10))
items_root.add_child(item)
items_dict[btn.name] = item
func _draw() -> void:
if Engine.is_editor_hint():
# draw boundart_rect frame
draw_rect(boundart_rect, Color(1, 0, 0), false, 2)
var display_tween: Tween
func _toggle_display(use_tween := true):
if display_tween and display_tween.is_running():
display_tween.kill()
if display:
if use_tween:
display_tween = create_tween()
# from bottom to top
display_tween.tween_property(self, "position:y", 0.0, 0.5).set_trans(Tween.TRANS_CUBIC)
# unlock items after display
display_tween.tween_callback(_toggle_items_lock.bind(false))
else:
position.y = 0
_toggle_items_lock(false)
else:
# lock items before hide
_toggle_items_lock(true)
if use_tween:
display_tween = create_tween()
# from top to bottom
display_tween.tween_property(self, "position:y", 320.0, 0.5).set_trans(
Tween.TRANS_CUBIC
)
else:
position.y = 320.0
func _toggle_items_lock(lock: bool) -> void:
for v in items_dict.values():
v.locked = lock
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_journal"):
if locked:
# TODO 使用 icon去重
SceneManager.pop_notification("🔒")
return
display = !display
get_viewport().set_input_as_handled()