xiandie/scene/journal/journal.gd

143 lines
4.0 KiB
GDScript3
Raw Normal View History

2025-01-07 10:54:50 +00:00
@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
2025-01-07 10:54:50 +00:00
_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()