게임 안에서 바다의 하루를 정할 수 있게
메뉴 > 시간 하위 메뉴에 세 갈래를 둔다. - 실제 시각: 바깥 시계 그대로 (기본) - 빠르게: 하루를 5분으로 압축해 돌린다 - 한 시각에 멈추기: 새벽/아침/낮/저녁/밤 프리셋의 이름과 시각을 DayCycle.FIXED_PRESETS 한곳에 같이 두어, 메뉴 항목과 실제로 적용되는 시각이 어긋날 수 없게 했다. 고른 값은 window_state의 time_mode/time_hour에 저장한다. 모드를 바꿀 때 지금 보이던 시각을 먼저 잡아 둔다. mode를 먼저 바꾼 뒤 hour()를 부르면 이미 새 모드의 시계를 읽어 0시로 튀었다 -- 낮에 "빠르게"를 켜면 한밤중으로 떨어지는 버그였다. 명령줄 --hour=21은 그대로 살아 있고 FIXED 모드의 지름길이 되었다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,10 @@ const HEIGHTS := [
|
||||
const EDGE_BOTTOM := 20
|
||||
const EDGE_TOP := 21
|
||||
const SCREEN_ID_BASE := 100
|
||||
## 시간 하위 메뉴. 200 실제, 201 빠르게, 210+i 고정 프리셋.
|
||||
const TIME_REAL := 200
|
||||
const TIME_FAST := 201
|
||||
const TIME_FIXED_BASE := 210
|
||||
|
||||
## 클릭 통과 중에도 이 크기의 모서리는 계속 클릭을 받는다.
|
||||
## 이게 없으면 클릭 통과를 켠 순간 위젯으로 돌아올 방법이 없어진다.
|
||||
@@ -29,6 +33,7 @@ const ESCAPE_HATCH := Vector2(84, 56)
|
||||
@onready var hud: HUDLayer = $HUD
|
||||
@onready var shop: ShopPanel = $ShopPanel
|
||||
@onready var menu: PopupMenu = $ContextMenu
|
||||
@onready var time_menu: PopupMenu = $ContextMenu/TimeMenu
|
||||
|
||||
var _always_on_top := true
|
||||
var _click_through := false
|
||||
@@ -46,6 +51,8 @@ func _ready() -> void:
|
||||
# state는 SaveManager의 딕셔너리를 그대로 가리킨다. 아래 _apply_dock()이
|
||||
# _remember_window()로 같은 딕셔너리를 덮어쓰므로, 나중에 쓸 값은 미리 빼둔다.
|
||||
var saved_layer := int(state.get("layer", 0))
|
||||
var saved_time_mode := int(state.get("time_mode", DayCycle.Mode.REAL))
|
||||
var saved_time_hour := float(state.get("time_hour", 13.0))
|
||||
_always_on_top = bool(state.get("always_on_top", true))
|
||||
_click_through = bool(state.get("click_through", false))
|
||||
_edge_bottom = bool(state.get("edge_bottom", true))
|
||||
@@ -67,6 +74,8 @@ func _ready() -> void:
|
||||
hud.reserved_top_changed.connect(func(px: float): aquarium.grid_top = px)
|
||||
aquarium.grid_top = hud.reserved_top()
|
||||
aquarium.current_zone = saved_layer
|
||||
DayCycle.fixed_hour = saved_time_hour
|
||||
DayCycle.mode = saved_time_mode as DayCycle.Mode
|
||||
|
||||
hud.shop_pressed.connect(_toggle_shop)
|
||||
hud.menu_pressed.connect(_open_menu)
|
||||
@@ -128,6 +137,8 @@ func _remember_window() -> void:
|
||||
SaveManager.window_state["always_on_top"] = _always_on_top
|
||||
SaveManager.window_state["click_through"] = _click_through
|
||||
SaveManager.window_state["layer"] = aquarium.current_zone
|
||||
SaveManager.window_state["time_mode"] = int(DayCycle.mode)
|
||||
SaveManager.window_state["time_hour"] = DayCycle.fixed_hour
|
||||
SaveManager.window_state["edge_bottom"] = _edge_bottom
|
||||
SaveManager.window_state["height"] = _strip_height
|
||||
SaveManager.window_state["screen"] = _screen
|
||||
@@ -257,6 +268,9 @@ func _build_menu() -> void:
|
||||
menu.add_check_item("클릭 통과 (모서리로 복귀)", MenuId.CLICK_THROUGH)
|
||||
menu.add_check_item("전체화면으로 감상 (F11)", MenuId.FULLSCREEN)
|
||||
menu.add_separator()
|
||||
_build_time_menu()
|
||||
menu.add_submenu_node_item("시간", time_menu)
|
||||
menu.add_separator()
|
||||
for h in HEIGHTS:
|
||||
menu.add_radio_check_item(h.label, h.id)
|
||||
menu.add_separator()
|
||||
@@ -275,12 +289,57 @@ func _build_menu() -> void:
|
||||
_sync_menu()
|
||||
|
||||
|
||||
## 시간을 바깥 시계에 맡길지, 한 시각에 멈출지, 빠르게 돌릴지.
|
||||
func _build_time_menu() -> void:
|
||||
time_menu.clear()
|
||||
time_menu.add_radio_check_item("실제 시각", TIME_REAL)
|
||||
time_menu.add_radio_check_item(
|
||||
"빠르게 (하루 %d분)" % int(DayCycle.FAST_DAY_MINUTES), TIME_FAST)
|
||||
time_menu.add_separator("한 시각에 멈추기")
|
||||
for i in DayCycle.FIXED_PRESETS.size():
|
||||
var p: Dictionary = DayCycle.FIXED_PRESETS[i]
|
||||
time_menu.add_radio_check_item(String(p.name), TIME_FIXED_BASE + i)
|
||||
time_menu.id_pressed.connect(_on_time_menu_id)
|
||||
|
||||
|
||||
func _sync_time_menu() -> void:
|
||||
_check_in(time_menu, TIME_REAL, DayCycle.mode == DayCycle.Mode.REAL)
|
||||
_check_in(time_menu, TIME_FAST, DayCycle.mode == DayCycle.Mode.FAST)
|
||||
for i in DayCycle.FIXED_PRESETS.size():
|
||||
var fixed := DayCycle.mode == DayCycle.Mode.FIXED
|
||||
var same := is_equal_approx(
|
||||
DayCycle.fixed_hour, float(DayCycle.FIXED_PRESETS[i].hour))
|
||||
_check_in(time_menu, TIME_FIXED_BASE + i, fixed and same)
|
||||
|
||||
|
||||
func _on_time_menu_id(id: int) -> void:
|
||||
if id == TIME_REAL:
|
||||
DayCycle.mode = DayCycle.Mode.REAL
|
||||
hud.show_toast("시간을 실제 시각에 맞췄어요 · 지금 %s" % DayCycle.clock_text())
|
||||
elif id == TIME_FAST:
|
||||
DayCycle.mode = DayCycle.Mode.FAST
|
||||
hud.show_toast("하루가 %d분에 한 바퀴 돕니다" % int(DayCycle.FAST_DAY_MINUTES))
|
||||
elif id >= TIME_FIXED_BASE:
|
||||
var p: Dictionary = DayCycle.FIXED_PRESETS[id - TIME_FIXED_BASE]
|
||||
DayCycle.fixed_hour = float(p.hour)
|
||||
DayCycle.mode = DayCycle.Mode.FIXED
|
||||
hud.show_toast("%s로 멈춰 뒀어요 · %s" % [p.name, DayCycle.clock_text()])
|
||||
_sync_time_menu()
|
||||
|
||||
|
||||
func _check_in(target: PopupMenu, id: int, on: bool) -> void:
|
||||
var index := target.get_item_index(id)
|
||||
if index >= 0:
|
||||
target.set_item_checked(index, on)
|
||||
|
||||
|
||||
func _sync_menu() -> void:
|
||||
_check(MenuId.ALWAYS_ON_TOP, _always_on_top)
|
||||
_check(MenuId.CLICK_THROUGH, _click_through)
|
||||
_check(MenuId.FULLSCREEN, _fullscreen)
|
||||
for h in HEIGHTS:
|
||||
_check(h.id, _strip_height == int(h.px))
|
||||
_sync_time_menu()
|
||||
_check(EDGE_BOTTOM, _edge_bottom)
|
||||
_check(EDGE_TOP, not _edge_bottom)
|
||||
if DisplayServer.get_screen_count() > 1:
|
||||
|
||||
@@ -26,3 +26,5 @@ visible = false
|
||||
layout_mode = 1
|
||||
|
||||
[node name="ContextMenu" type="PopupMenu" parent="."]
|
||||
|
||||
[node name="TimeMenu" type="PopupMenu" parent="ContextMenu"]
|
||||
|
||||
Reference in New Issue
Block a user