From 10910400fa9169c20bda6fa6bdf63e5450a33f4b Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 23 Sep 2023 13:08:13 -0600 Subject: [PATCH] g/j2: Fill out `game options` menu (#3003) --- common/util/FontUtils.cpp | 12 + common/util/FontUtils.h | 2 + common/util/string_util.cpp | 21 + common/util/string_util.h | 1 + decompiler/config/jak2/all-types.gc | 25 +- game/assets/jak2/temp-text-id-mapping.json | 30 ++ .../jak2/text/game_custom_text_en-US.json | 36 +- game/assets/jak2/update-text-from-jak1.py | 22 + game/kernel/common/kmachine.cpp | 31 +- goal_src/jak1/kernel/gstring.gc | 2 +- .../jak2/engine/ui/progress/progress-draw.gc | 5 + goal_src/jak2/engine/ui/text-id-h.gc | 25 +- goal_src/jak2/kernel-defs.gc | 6 +- goal_src/jak2/kernel/gstring.gc | 4 + goal_src/jak2/pc/pckernel.gc | 2 + .../pc/progress/progress-generic-draw-pc.gc | 430 ++++++++++++++---- .../jak2/pc/progress/progress-generic-h-pc.gc | 181 ++++++-- .../jak2/pc/progress/progress-generic-pc.gc | 419 ++++++++++++++--- goal_src/jak2/pc/progress/progress-pc.gc | 4 +- .../jak2/pc/progress/progress-static-pc.gc | 305 ++++++++++++- 20 files changed, 1358 insertions(+), 205 deletions(-) create mode 100644 game/assets/jak2/temp-text-id-mapping.json create mode 100644 game/assets/jak2/update-text-from-jak1.py diff --git a/common/util/FontUtils.cpp b/common/util/FontUtils.cpp index 1c2d7c7a0ba..e70865a0530 100644 --- a/common/util/FontUtils.cpp +++ b/common/util/FontUtils.cpp @@ -1876,6 +1876,18 @@ const GameTextFontBank* get_font_bank(GameTextVersion version) { return g_font_banks.at(version); } +const GameTextFontBank* get_font_bank_from_game_version(GameVersion version) { + // Jak 1 has been patched to use V2 + switch (version) { + case GameVersion::Jak1: + return get_font_bank(GameTextVersion::JAK1_V2); + case GameVersion::Jak2: + return get_font_bank(GameTextVersion::JAK2); + default: + ASSERT_MSG(false, "Unsupported game for get_font_bank_from_game_version"); + } +} + const GameTextFontBank* get_font_bank(const std::string& name) { if (auto it = sTextVerEnumMap.find(name); it == sTextVerEnumMap.end()) { throw std::runtime_error(fmt::format("unknown text version {}", name)); diff --git a/common/util/FontUtils.h b/common/util/FontUtils.h index baff0316d15..5aa1627a225 100644 --- a/common/util/FontUtils.h +++ b/common/util/FontUtils.h @@ -16,6 +16,7 @@ #include #include "common/common_types.h" +#include "common/versions/versions.h" // version of the game text file's text encoding. Not real, but we need to differentiate them // somehow, since the encoding changes. @@ -92,5 +93,6 @@ extern GameTextFontBank g_font_bank_jak2; extern std::map g_font_banks; const GameTextFontBank* get_font_bank(GameTextVersion version); +const GameTextFontBank* get_font_bank_from_game_version(GameVersion version); const GameTextFontBank* get_font_bank(const std::string& name); bool font_bank_exists(GameTextVersion version); diff --git a/common/util/string_util.cpp b/common/util/string_util.cpp index bb56af89aad..6ae4bf29a44 100644 --- a/common/util/string_util.cpp +++ b/common/util/string_util.cpp @@ -205,7 +205,28 @@ std::string to_lower(const std::string& str) { std::transform(str.begin(), str.end(), new_str.begin(), ::tolower); return new_str; } + bool hex_char(char c) { return !((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')); } + +std::string titlize(const std::string& str) { + // Iterate through the string, capitalizing any character that either comes first, or is preceeded + // by whitespace + const auto trimmed_string = trim(str); + std::string new_str = ""; + bool capitalize_next_char = true; + for (const auto& character : trimmed_string) { + if (capitalize_next_char) { + new_str.push_back(toupper(character)); + capitalize_next_char = false; + } else { + if (character == ' ') { + capitalize_next_char = true; + } + new_str.push_back(character); + } + } + return new_str; +} } // namespace str_util diff --git a/common/util/string_util.h b/common/util/string_util.h index 975b54ea09c..69706573a50 100644 --- a/common/util/string_util.h +++ b/common/util/string_util.h @@ -32,4 +32,5 @@ std::string to_upper(const std::string& str); std::string to_lower(const std::string& str); /// Is this a valid character for a hex number? bool hex_char(char c); +std::string titlize(const std::string& str); } // namespace str_util diff --git a/decompiler/config/jak2/all-types.gc b/decompiler/config/jak2/all-types.gc index fe7412339cc..e5d5e1c0879 100644 --- a/decompiler/config/jak2/all-types.gc +++ b/decompiler/config/jak2/all-types.gc @@ -7353,7 +7353,6 @@ (progress-camera-options-first-vert #x1282) (progress-camera-options-third-horz #x1283) (progress-camera-options-third-vert #x1284) - (progress-reset-to-default #x1285) (progress-normal #x1286) (progress-inverted #x1287) (progress-ps2-parts #x1288) @@ -7365,6 +7364,30 @@ (progress-frame-rate #x128e) (progress-misc-game-options #x128f) (progress-speedrunner-mode #x1290) + (progress-menu-input-options #x1291) + (progress-restore-defaults #x1292) + (progress-menu-controller-options #x1293) + (progress-controller-options-select-controller #x1294) + (progress-controller-options-analog-deadzone #x1295) + (progress-controller-options-ignore-if-unfocused #x1296) + (progress-controller-options-led-hp #x1297) + (progress-controller-options-led-darkjak #x1298) + (progress-input-options-enable-keyboard #x1299) + (progress-input-options-enable-mouse #x129a) + (progress-menu-mouse-options #x129b) + (progress-mouse-options-track-camera #x129c) + (progress-mouse-options-horz-sens #x129d) + (progress-mouse-options-vert-sens #x129e) + (progress-mouse-options-player-movement #x129f) + (progress-input-options-auto-hide-cursor #x1300) + (progress-menu-reassign-binds #x1301) + (progress-reassign-binds-controller #x1302) + (progress-reassign-binds-keyboard #x1303) + (progress-reassign-binds-mouse #x1304) + (progress-multiselect-no-items-found #x1305) + (progress-keybinds-waiting-for-bind #x1306) + (progress-keybinds-unset #x1307) + (progress-unknown-option #x1308) ) ;; ---text-id-h:text-id diff --git a/game/assets/jak2/temp-text-id-mapping.json b/game/assets/jak2/temp-text-id-mapping.json new file mode 100644 index 00000000000..2b77821def7 --- /dev/null +++ b/game/assets/jak2/temp-text-id-mapping.json @@ -0,0 +1,30 @@ +{ + "1280": "1000", + "1286": "1001", + "1287": "1002", + "1289": "1030", + "128e": "1060", + "128f": "100f", + "1290": "1500", + "1291": "1600", + "1292": "1007", + "1293": "160d", + "1294": "1601", + "1295": "1602", + "1296": "1603", + "1297": "1604", + "1299": "160e", + "129a": "160f", + "129b": "1610", + "129c": "1606", + "129d": "1607", + "129e": "1608", + "129f": "1609", + "1300": "1613", + "1301": "1611", + "1302": "160a", + "1303": "160b", + "1304": "160c", + "1307": "1614", + "1308": "1615" +} diff --git a/game/assets/jak2/text/game_custom_text_en-US.json b/game/assets/jak2/text/game_custom_text_en-US.json index bca2b793833..9044dcbb434 100644 --- a/game/assets/jak2/text/game_custom_text_en-US.json +++ b/game/assets/jak2/text/game_custom_text_en-US.json @@ -108,10 +108,10 @@ "1261": "Bad Weather", "1262": "Nice Weather", "1280": "Camera Options", - "1281": "Left/Right (First Person)", - "1282": "Up/Down (First Person)", - "1283": "Left/Right (Third Person)", - "1284": "Up/Down (Third Person)", + "1281": "Left/Right (1st Person)", + "1282": "Up/Down (1st Person)", + "1283": "Left/Right (3rd Person)", + "1284": "Up/Down (3rd Person)", "1285": "Reset to Default", "1286": "Normal", "1287": "Inverted", @@ -122,6 +122,30 @@ "128c": "High", "128d": "Credits", "128e": "Frame Rate (Experimental)", - "128f": "Misc. Options", - "1290": "Speedrunner Mode" + "128f": "Miscellaneous", + "1290": "Speedrunner Mode", + "1291": "Input Options", + "1292": "Restore Defaults", + "1293": "Controller Options", + "1294": "Select Controller", + "1295": "Analog Deadzone", + "1296": "Ignore If Window Unfocused", + "1297": "Controller Led For HP", + "1298": "Controller Led For Dark Jak", + "1299": "Enable Keyboard", + "129a": "Enable Mouse", + "129b": "Mouse Options", + "129c": "Track Camera", + "129d": "Horizontal Sensitivity", + "129e": "Vertical Sensitivity", + "129f": "Player Movement", + "1300": "Auto Hide Cursor", + "1301": "Reassign Binds", + "1302": "Controller Binds", + "1303": "Keyboard Binds", + "1304": "Mouse Binds", + "1305": "No Options", + "1306": "Waiting", + "1307": "Unset", + "1308": "Unknown" } diff --git a/game/assets/jak2/update-text-from-jak1.py b/game/assets/jak2/update-text-from-jak1.py new file mode 100644 index 00000000000..96851ae7737 --- /dev/null +++ b/game/assets/jak2/update-text-from-jak1.py @@ -0,0 +1,22 @@ +# Jak 2 shares many of the same custom menu strings as jak 1 obviously +# this is to copy them over so they are already translated. + +# TODO - make it enumerate all languages + +import json + + +with open("temp-text-id-mapping.json", "r", encoding="utf-8") as f: + mapping = json.load(f) + +with open("./text/game_custom_text_en-US.json", "r", encoding="utf-8") as f: + jak2_file = json.load(f) + +with open("../jak1/text/game_custom_text_en-US.json", "r", encoding="utf-8") as f: + jak1_file = json.load(f) + +for jak2_id, jak1_id in mapping.items(): + jak2_file[jak2_id] = jak1_file[jak1_id].title() + +with open("./text/game_custom_text_en-US.json", "w", encoding="utf-8") as f: + json.dump(jak2_file, f, indent=2) diff --git a/game/kernel/common/kmachine.cpp b/game/kernel/common/kmachine.cpp index 65f4d4532fc..8e5751f809a 100644 --- a/game/kernel/common/kmachine.cpp +++ b/game/kernel/common/kmachine.cpp @@ -6,6 +6,7 @@ #include "common/log/log.h" #include "common/symbols.h" #include "common/util/FileUtil.h" +#include "common/util/FontUtils.h" #include "common/util/Timer.h" #include "common/util/string_util.h" @@ -455,7 +456,15 @@ u64 pc_get_display_name(u32 id, u32 str_dest_ptr) { if (name.empty()) { return bool_to_symbol(false); } - strcpy(Ptr(str_dest_ptr).c()->data(), str_util::to_upper(name).c_str()); + if (g_game_version == GameVersion::Jak1) { + // The Jak 1 font has only caps + name = str_util::to_upper(name).c_str(); + } + // Encode the string to the game font + const auto encoded_name = get_font_bank_from_game_version(g_game_version) + ->convert_utf8_to_game(str_util::titlize(name).c_str()); + strcpy(Ptr(str_dest_ptr).c()->data(), encoded_name.c_str()); + strcpy(Ptr(str_dest_ptr).c()->data(), str_util::titlize(encoded_name).c_str()); return bool_to_symbol(true); } @@ -600,7 +609,16 @@ u64 pc_get_controller_name(u32 id, u32 str_dest_ptr) { if (name.empty()) { return bool_to_symbol(false); } - strcpy(Ptr(str_dest_ptr).c()->data(), str_util::to_upper(name).c_str()); + + if (g_game_version == GameVersion::Jak1) { + // The Jak 1 font has only caps + name = str_util::to_upper(name).c_str(); + } + // Encode the string to the game font + const auto encoded_name = get_font_bank_from_game_version(g_game_version) + ->convert_utf8_to_game(str_util::titlize(name).c_str()); + strcpy(Ptr(str_dest_ptr).c()->data(), encoded_name.c_str()); + strcpy(Ptr(str_dest_ptr).c()->data(), str_util::titlize(encoded_name).c_str()); return bool_to_symbol(true); } @@ -624,7 +642,14 @@ u64 pc_get_current_bind(s32 bind_assignment_info, u32 str_dest_ptr) { if (name.empty()) { return bool_to_symbol(false); } - strcpy(Ptr(str_dest_ptr).c()->data(), str_util::to_upper(name).c_str()); + if (g_game_version == GameVersion::Jak1) { + // The Jak 1 font has only caps + name = str_util::to_upper(name).c_str(); + } + // Encode the string to the game font + const auto encoded_name = get_font_bank_from_game_version(g_game_version) + ->convert_utf8_to_game(str_util::titlize(name).c_str()); + strcpy(Ptr(str_dest_ptr).c()->data(), encoded_name.c_str()); return bool_to_symbol(true); } // TODO - return something that lets the runtime use a translatable string if unknown diff --git a/goal_src/jak1/kernel/gstring.gc b/goal_src/jak1/kernel/gstring.gc index 78a0370e26a..1aedca26fc5 100644 --- a/goal_src/jak1/kernel/gstring.gc +++ b/goal_src/jak1/kernel/gstring.gc @@ -801,7 +801,7 @@ (define *temp-string* (new 'global 'string 256 (the string #f))) (define *temp-string2* (new 'global 'string 256 (the string #f))) (define *pc-cpp-temp-string* - "A conveniant place to retrieve a string from C++" + "A convenient place to retrieve a string from C++" (new 'global 'string 256 (the-as string #f))) (defmacro string-format (&rest args) diff --git a/goal_src/jak2/engine/ui/progress/progress-draw.gc b/goal_src/jak2/engine/ui/progress/progress-draw.gc index 96f4f78c1f4..88d4c5291af 100644 --- a/goal_src/jak2/engine/ui/progress/progress-draw.gc +++ b/goal_src/jak2/engine/ui/progress/progress-draw.gc @@ -6709,7 +6709,9 @@ (set-hud-piece-position! (-> obj sprites 3) (+ sv-64 242 s1-0) (+ s2-0 -4)) (set! sv-256 (-> *display* frames (-> *display* on-screen) global-buf)) (set! sv-272 (-> sv-256 base)) + ;; bar ((method-of-type hud-sprite draw) (the-as hud-sprite (-> obj sprites)) sv-256 (-> *level* default-level)) + ;; bar background (draw-sprite2d-xy sv-256 (+ s1-0 s0-0 (the int (* 230.0 (-> (the-as (pointer float) sv-208))))) @@ -6718,8 +6720,11 @@ 9 (the-as rgba sv-240) ) + ;; notch (draw (-> obj sprites 1) sv-256 (-> *level* default-level)) + ;; left icon (draw (-> obj sprites 2) sv-256 (-> *level* default-level)) + ;; right icon (draw (-> obj sprites 3) sv-256 (-> *level* default-level)) (let ((a3-13 (-> sv-256 base))) (let ((v1-183 (the-as object (-> sv-256 base)))) diff --git a/goal_src/jak2/engine/ui/text-id-h.gc b/goal_src/jak2/engine/ui/text-id-h.gc index 78b524556a9..35b13d843b4 100644 --- a/goal_src/jak2/engine/ui/text-id-h.gc +++ b/goal_src/jak2/engine/ui/text-id-h.gc @@ -681,7 +681,6 @@ (progress-camera-options-first-vert #x1282) (progress-camera-options-third-horz #x1283) (progress-camera-options-third-vert #x1284) - (progress-reset-to-default #x1285) (progress-normal #x1286) (progress-inverted #x1287) (progress-ps2-parts #x1288) @@ -693,6 +692,30 @@ (progress-frame-rate #x128e) (progress-misc-game-options #x128f) (progress-speedrunner-mode #x1290) + (progress-menu-input-options #x1291) + (progress-restore-defaults #x1292) + (progress-menu-controller-options #x1293) + (progress-controller-options-select-controller #x1294) + (progress-controller-options-analog-deadzone #x1295) + (progress-controller-options-ignore-if-unfocused #x1296) + (progress-controller-options-led-hp #x1297) + (progress-controller-options-led-darkjak #x1298) + (progress-input-options-enable-keyboard #x1299) + (progress-input-options-enable-mouse #x129a) + (progress-menu-mouse-options #x129b) + (progress-mouse-options-track-camera #x129c) + (progress-mouse-options-horz-sens #x129d) + (progress-mouse-options-vert-sens #x129e) + (progress-mouse-options-player-movement #x129f) + (progress-input-options-auto-hide-cursor #x1300) + (progress-menu-reassign-binds #x1301) + (progress-reassign-binds-controller #x1302) + (progress-reassign-binds-keyboard #x1303) + (progress-reassign-binds-mouse #x1304) + (progress-multiselect-no-items-found #x1305) + (progress-keybinds-waiting-for-bind #x1306) + (progress-keybinds-unset #x1307) + (progress-unknown-option #x1308) ) ;; ---text-id diff --git a/goal_src/jak2/kernel-defs.gc b/goal_src/jak2/kernel-defs.gc index 25344745401..ea40a1e5c0d 100644 --- a/goal_src/jak2/kernel-defs.gc +++ b/goal_src/jak2/kernel-defs.gc @@ -160,15 +160,16 @@ (define-extern __pc-get-tex-remap (function int int int)) ;; Input Related Functions +;; TODO - add get current controller index (define-extern pc-get-controller-count (function int)) -(define-extern pc-get-controller-name (function int string)) +(define-extern pc-get-controller-name (function int string string)) (deftype bind-assignment-info (structure) ((port int32) (device-type int32) (for-buttons? symbol) (input-idx int32) (analog-min-range? symbol))) -(define-extern pc-get-current-bind (function bind-assignment-info string)) +(define-extern pc-get-current-bind (function bind-assignment-info string symbol)) (define-extern pc-waiting-for-bind? (function symbol)) (define-extern pc-set-waiting-for-bind! (function int symbol symbol int none)) (define-extern pc-stop-waiting-for-bind! (function none)) @@ -177,6 +178,7 @@ (define-extern pc-set-mouse-options! (function symbol symbol symbol none)) (define-extern pc-set-mouse-camera-sens! (function float float none)) (define-extern pc-current-controller-has-led? (function symbol)) +(define-extern pc-current-controller-has-rumble? (function symbol)) (define-extern pc-set-controller-led! (function int int int int none)) (define-extern pc-ignore-background-controller-events! (function symbol none)) (define-extern pc-reset-bindings-to-defaults! (function int int none)) diff --git a/goal_src/jak2/kernel/gstring.gc b/goal_src/jak2/kernel/gstring.gc index 90a8aa9b703..71b58c0ce82 100644 --- a/goal_src/jak2/kernel/gstring.gc +++ b/goal_src/jak2/kernel/gstring.gc @@ -799,6 +799,10 @@ ;; up from 256 bytes in jak 1 (define *temp-string* (new 'global 'string 2048 (the-as string #f))) +(define *pc-cpp-temp-string* + "A convenient place to retrieve a string from C++" + (new 'global 'string 2048 (the-as string #f))) + (defmacro string-format (&rest args) "Formats into *temp-string* and returns it, for in-place string formating. DO NOT USE *temp-string* WITH THIS MACRO! It is read as input AFTER all of the args evaluate." diff --git a/goal_src/jak2/pc/pckernel.gc b/goal_src/jak2/pc/pckernel.gc index af88272ab26..feed7b50197 100644 --- a/goal_src/jak2/pc/pckernel.gc +++ b/goal_src/jak2/pc/pckernel.gc @@ -432,3 +432,5 @@ (defmacro adjust-game-x (x) `(adjust-game-x-centered CENTER_X ,x)) +(defmacro adjust-game-x-int (x-float) + `(the int (adjust-game-x-centered CENTER_X (the float ,x-float)))) diff --git a/goal_src/jak2/pc/progress/progress-generic-draw-pc.gc b/goal_src/jak2/pc/progress/progress-generic-draw-pc.gc index d0ee4633459..9834141e33e 100644 --- a/goal_src/jak2/pc/progress/progress-generic-draw-pc.gc +++ b/goal_src/jak2/pc/progress/progress-generic-draw-pc.gc @@ -58,14 +58,13 @@ (defun draw-page-header ((font-ctx font-context) (text text-id)) (let ((x-pos 70) - (y-pos 85) + (y-pos 80) (width 375)) (when (= (get-aspect-ratio) 'aspect16x9) (set! x-pos 79) (set! y-pos 55) (set! width 356)) - (set-scale! font-ctx 0.75) - (set! (-> font-ctx height) 20.0) + (set-scale! font-ctx 0.55) (set! (-> font-ctx origin y) (the float y-pos)) (set-color! font-ctx (font-color progress)) (print-game-text (lookup-text! *common-text* text #f) font-ctx #f 44 (bucket-id progress))) @@ -129,19 +128,23 @@ (restore-scissor hud-bounds buffer)) (none)) +(defun-debug draw-generic-page-row-line ((y-coord int)) + (with-dma-buffer-add-bucket ((buf (-> *display* frames (-> *display* on-screen) global-buf)) + (bucket-id debug-no-zbuf2)) + (draw-sprite2d-xy buf 0 y-coord 512 1 (static-rgba #xff #xff #xff #x40)))) + (defmethod draw-option menu-generic-scrolling-page ((obj menu-generic-scrolling-page) (progress progress) (font-ctx font-context) (arg3 int) (arg4 symbol)) - ;; (inspect obj) (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?))) (on-mount! obj)) ;; the list has a total of 200px of y-height ;; with 10px of margin at the top and bottom, that leaves 180 / 4 = 45px per item ;; it's the responsibility of each generic component to center itself within these 45px lines (when (not (-> *progress-pc-generic-store* clear-screen?)) - (let ((font-alpha (fmax 0.0 (* 2.0 (- 0.5 (-> progress menu-transition))))) - (hud-bounds (new 'stack-no-clear 'hud-box)) - (max-page-size (if (= (get-aspect-ratio) 'aspect16x9) 5 4)) - (margin-top-bottom 10.0) - (line-height 45.0)) + (let* ((font-alpha (fmax 0.0 (* 2.0 (- 0.5 (-> progress menu-transition))))) + (hud-bounds (new 'stack-no-clear 'hud-box)) + (max-page-size (if (= (get-aspect-ratio) 'aspect16x9) 7 5)) + (margin-top-bottom 0.0) + (line-height (/ (if (= (get-aspect-ratio) 'aspect16x9) 253.0 200.0) max-page-size))) (set! (-> font-ctx alpha) font-alpha) (set-color! font-ctx (font-color progress)) ;; header @@ -155,19 +158,21 @@ (set! (-> font-ctx origin y) (+ 86.0 margin-top-bottom)) (set! (-> font-ctx origin y) (+ 112.0 margin-top-bottom))) ;; render items - (let* ((menu-option-index (if (< (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size) - 0 - (-> *progress-pc-generic-store* current-menu-hover-index))) + (let* ((menu-option-index (max 0 (* (/ (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size) max-page-size))) (end-index (min (-> obj menu-options length) (+ menu-option-index max-page-size)))) (while (< menu-option-index end-index) (let ((menu-option (-> obj menu-options menu-option-index))) (when (nonzero? menu-option) - ;; save the y position as who knows where it will end up after the component finishes rendering - (let ((old-y-pos (-> font-ctx origin y))) + ;; save the y,x position as who knows where it will end up after the component finishes rendering + (let ((old-y-pos (-> font-ctx origin y)) + (old-x-pos (-> font-ctx origin x))) (draw-option menu-option progress font-ctx menu-option-index (= (-> obj selected-option-index) menu-option-index)) ;; move to the next line (set! (-> font-ctx origin y) (+ old-y-pos line-height)) + ;; - debugging, draw the dividing lines to make centering new items easier + (draw-generic-page-row-line (the int (-> font-ctx origin y))) + (set! (-> font-ctx origin x) old-x-pos) ;; reset the font color (set-color! font-ctx (font-color progress))))) (+! menu-option-index 1))) @@ -192,34 +197,31 @@ (width (if (= (get-aspect-ratio) 'aspect4x3) 374 500))) - ;; og:preserve-this - (#when PC_PORT - ;; added for better widescreen handling - (when (not (-> *pc-settings* use-vis?)) - (set! x-pos (the int (adjust-game-x (the float x-pos)))) - (set! width (the int (* (-> *pc-settings* aspect-ratio-reciprocal) width))))) + (when (not (-> *pc-settings* use-vis?)) + (set! x-pos (the int (adjust-game-x (the float x-pos)))) + (set! width (the int (* (-> *pc-settings* aspect-ratio-reciprocal) width)))) (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf)) (bucket-id progress) ) (draw-sprite2d-xy buffer x-pos y-pos width height (new 'static 'rgba :r #x40 :g #x80 :b #x80 :a (the int (* 64.0 alpha))))))) -(defmethod draw-option menu-generic-boolean-option ((obj menu-generic-boolean-option) (arg0 progress) (arg1 font-context) (option-index int) (selected? symbol)) +(defmethod draw-option menu-generic-boolean-option ((obj menu-generic-boolean-option) (arg0 progress) (font-ctx font-context) (option-index int) (selected? symbol)) (when (not (-> obj mounted?)) (on-mount! obj)) (let ((alpha (* 2.0 (- 0.5 (-> arg0 menu-transition)))) - (line-height 23.0)) + (line-height 18.0)) (max! alpha 0.0) - (set! (-> arg1 alpha) alpha) - (set-flags! arg1 (font-flags kerning middle large)) - (set-scale! arg1 0.65) - (+! (-> arg1 origin y) 5.0) + (set! (-> font-ctx alpha) alpha) + (set-flags! font-ctx (font-flags kerning middle large)) + (set-scale! font-ctx 0.45) + (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 7.0 5.0)) (cond (selected? - (set-color! arg1 (font-color progress-force-selected)) - (draw-generic-highlight (the int (+ -1.0 (-> arg1 origin y))) 41 alpha) - (print-game-text (lookup-text! *common-text* (-> obj name) #f) arg1 #f 44 (bucket-id progress)) - (+! (-> arg1 origin y) line-height) + (set-color! font-ctx (font-color progress-force-selected)) + (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) 32 alpha) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (+! (-> font-ctx origin y) line-height) (set! *temp-string* (clear *temp-string*)) (if (-> obj value) (format *temp-string* "~33L~S~35L ~S" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f)) @@ -227,22 +229,26 @@ ;; hover case (else (cond + ((and (nonzero? (-> obj should-disable?)) + (!= (-> obj should-disable?) #f) + ((-> obj should-disable?))) + (set-color! font-ctx (font-color progress-option-off)) + (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 0.5))) ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) - (set-color! arg1 (progress-selected 0)) - (draw-generic-highlight (the int (+ -1.0 (-> arg1 origin y))) 22 alpha)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 alpha)) (else - (set-color! arg1 (font-color progress)))) - (print-game-text (lookup-text! *common-text* (-> obj name) #f) arg1 #f 44 (bucket-id progress)) - (+! (-> arg1 origin y) line-height) + (set-color! font-ctx (font-color progress)))) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (+! (-> font-ctx origin y) line-height) (set! *temp-string* (clear *temp-string*)) - (let ((actual-value (if (and (nonzero? (-> obj get-value-fn)) (!= (-> obj get-value-fn) #f)) - ((-> obj get-value-fn)) - #f))) + (let ((actual-value (call-get-value-fn obj))) (if actual-value (format *temp-string* "~1L~S~35L ~S" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f)) (format *temp-string* "~35L~S ~1L~S~1L" (lookup-text! *common-text* (-> obj truthy-text) #f) (lookup-text! *common-text* (-> obj falsey-text) #f)))))) - (set-scale! arg1 0.5) - (print-game-text *temp-string* arg1 #f 44 (bucket-id progress))) + (set-scale! font-ctx 0.35) + (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress))) (none)) (defmethod draw-option menu-generic-carousel-option ((obj menu-generic-carousel-option) @@ -253,60 +259,330 @@ (when (not (-> obj mounted?)) (on-mount! obj)) (let ((alpha (fmax (* 2.0 (- 0.5 (-> progress menu-transition))) 0.0))) - (set! (-> font-ctx scale) 0.65) + (set! (-> font-ctx scale) 0.45) (set! (-> font-ctx alpha) alpha) - (+! (-> font-ctx origin y) 2.5) + (+! (-> font-ctx origin y) 5.0) (set-flags! font-ctx (font-flags kerning middle large)) ;; the item label (cond (selected? (set! (-> font-ctx color) (font-color progress-force-selected)) - (draw-generic-highlight (the int (-> font-ctx origin y)) 44 alpha)) + (draw-generic-highlight (the int (- (-> font-ctx origin y) 1.0)) 30 alpha)) + ((and (nonzero? (-> obj should-disable?)) + (!= (-> obj should-disable?) #f) + ((-> obj should-disable?))) + (set-color! font-ctx (font-color progress-option-off)) + (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 0.5))) ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) (set! (-> font-ctx color) (progress-selected 0)) - (draw-generic-highlight (the int (-> font-ctx origin y)) 24 alpha))) - (format (clear *temp-string*) "~S" (lookup-text! *common-text* (-> obj name) #f)) - (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress)) - (+! (-> font-ctx origin y) 24.0) - (set! (-> font-ctx scale) 0.5) + (draw-generic-highlight (the int (- (-> font-ctx origin y) 1.0)) 16 alpha))) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (+! (-> font-ctx origin y) 18.0) + (set! (-> font-ctx scale) 0.35) (set! (-> font-ctx color) (font-color progress)) - (when selected? - ;; left arrow - (+! (-> font-ctx origin x) -70.0) - (format (clear *temp-string*) "~33L~C" 163) - (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress)) - (+! (-> font-ctx origin x) 70.0) - (+! (-> font-ctx origin x) 70.0) - ;; right arrow - (format (clear *temp-string*) "~33L~C" 161) - (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress)) - (+! (-> font-ctx origin x) -70.0) - (set! (-> font-ctx color) (progress-selected 0))) ;; the value - ;; TODO - bounds checking would be smart - (if selected? - (print-game-text (lookup-text! *common-text* (-> obj items (-> obj item-index)) #f) font-ctx #f 44 (bucket-id progress)) - (let ((actual-index (if (and (nonzero? (-> obj get-item-index-fn)) (!= (-> obj get-item-index-fn) #f)) - ((-> obj get-item-index-fn)) - 0))) - (print-game-text (lookup-text! *common-text* (-> obj items actual-index) #f) font-ctx #f 44 (bucket-id progress))))) + (cond + ((or (< (-> obj item-index) 0) (> (-> obj item-index) (num-items obj))) + (print-game-text (lookup-text! *common-text* (text-id progress-multiselect-no-items-found) #f) font-ctx #f 44 (bucket-id progress))) + ((and selected? (>= (-> obj item-index) 0) (< (-> obj item-index) (num-items obj))) + (format (clear *temp-string*) "~33L~C ~S ~33L~C" 163 (get-item-label obj (-> obj item-index)) 161) + (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress))) + (else + (let ((actual-index (call-get-item-index-fn obj))) + (print-game-text (get-item-label obj actual-index) font-ctx #f 44 (bucket-id progress)))))) (none)) -(defmethod draw-option menu-generic-link-option ((obj menu-generic-link-option) (arg0 progress) (arg1 font-context) (option-index int) (selected? symbol)) +(defun draw-generic-simple-string-option ((option menu-generic-option) (progress progress) (font-ctx font-context) (option-index int) (str string)) + (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition)))) + (line-height 23.0)) + (max! alpha 0.0) + (set! (-> font-ctx alpha) alpha) + (set-flags! font-ctx (font-flags kerning middle large)) + (set-scale! font-ctx 0.45) + (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 14.0 11.0)) + (cond + ((and (nonzero? (-> option should-disable?)) + (!= (-> option should-disable?) #f) + ((-> option should-disable?))) + (set-color! font-ctx (font-color progress-option-off)) + (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 0.5))) + ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 17 alpha)) + (else + (set-color! font-ctx (font-color progress)))) + (print-game-text str font-ctx #f 44 (bucket-id progress))) + (none)) + +(defmethod draw-option menu-generic-link-option ((obj menu-generic-link-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol)) (when (not (-> obj mounted?)) (on-mount! obj)) - (let ((alpha (* 2.0 (- 0.5 (-> arg0 menu-transition)))) + (draw-generic-simple-string-option obj progress font-ctx option-index (lookup-text! *common-text* (-> obj name) #f)) + (none)) + +(defmethod draw-option menu-generic-confirm-option ((obj menu-generic-confirm-option) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol)) + (when (not (-> obj mounted?)) + (on-mount! obj)) + ;; drawn different depending on whether or not the confirmation prompt is open + (cond + (selected? + ;; TODO - this is duplicate code with the boolean option, but i ran out of arguments, make a struct or something later + (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition)))) + (line-height 18.0)) + (max! alpha 0.0) + (set! (-> font-ctx alpha) alpha) + (set-flags! font-ctx (font-flags kerning middle large)) + (set-scale! font-ctx 0.45) + (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) 7.0 5.0)) + (cond + (selected? + (set-color! font-ctx (font-color progress-force-selected)) + (draw-generic-highlight (the int (- (-> font-ctx origin y) 2.0)) 32 alpha) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (+! (-> font-ctx origin y) line-height) + (set! *temp-string* (clear *temp-string*)) + (if (-> obj confirmed?) + (format *temp-string* "~33L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)) + (format *temp-string* "~35L~S ~33L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)))) + ;; hover case + (else + (cond + ((and (nonzero? (-> obj should-disable?)) + (!= (-> obj should-disable?) #f) + ((-> obj should-disable?))) + (set-color! font-ctx (font-color progress-option-off)) + (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 0.5))) + ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 alpha)) + (else + (set-color! font-ctx (font-color progress)))) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (+! (-> font-ctx origin y) line-height) + (set! *temp-string* (clear *temp-string*)) + (if (-> obj confirmed?) + (format *temp-string* "~1L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)) + (format *temp-string* "~35L~S ~1L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))))) + (set-scale! font-ctx 0.35) + (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress)))) + (else + (draw-generic-simple-string-option obj progress font-ctx option-index (lookup-text! *common-text* (-> obj name) #f)))) + (none)) + +(defmethod draw-option menu-generic-slider-option ((obj menu-generic-slider-option) (arg0 progress) (font-ctx font-context) (option-index int) (selected? symbol)) + (when (not (-> obj mounted?)) + (on-mount! obj)) + (let ((alpha (max 0.0 (* 2.0 (- 0.5 (-> arg0 menu-transition))))) + (slider-value (if selected? (-> obj value) (call-get-value-fn obj)))) + (set! (-> font-ctx alpha) alpha) + (set-scale! font-ctx 0.45) + (+! (-> font-ctx origin y) 20.0) + (case (get-aspect-ratio) + (('aspect4x3)) + (('aspect16x9))) + (set-flags! font-ctx (font-flags kerning middle large)) + (cond + (selected? + (set-scale! font-ctx 0.35) + (+! (-> font-ctx origin y) (if (= (get-aspect-ratio) 'aspect4x3) -15.0 -15.0)) + (set-color! font-ctx (font-color progress-force-selected)) + (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) 35 alpha) + (if (= (-> obj show-decimal?) #t) + (print-game-text (string-format "~S: ~,,2f" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id progress)) + (print-game-text (string-format "~S: ~D" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id progress))) + (set! (-> obj bar-sprite tex) (lookup-texture-by-id (new 'static 'texture-id :index #xb :page #xc93))) + (set! (-> obj bar-sprite scale-x) 2.0) + (set! (-> obj bar-sprite scale-y) 0.5) + (let ((sprite-color-0 (-> obj bar-sprite color2))) + (set! (-> sprite-color-0 0) 128) + (set! (-> sprite-color-0 1) 128) + (set! (-> sprite-color-0 2) 128) + (set! (-> sprite-color-0 3) 128) + ) + (set! (-> obj bar-sprite pos z) #x3fffff) + (set! (-> obj bar-sprite pos w) 0) + (set! (-> obj bar-cursor-sprite tex) (lookup-texture-by-id (new 'static 'texture-id :index #xc :page #xc93))) + (set! (-> obj bar-cursor-sprite scale-x) 0.2) + (set! (-> obj bar-cursor-sprite scale-y) 1.0) + (let ((sprite-color-1 (-> obj bar-cursor-sprite color2))) + (set! (-> sprite-color-1 0) 128) + (set! (-> sprite-color-1 1) 128) + (set! (-> sprite-color-1 2) 128) + (set! (-> sprite-color-1 3) 128) + ) + (set! (-> obj bar-cursor-sprite pos z) #x3fffff) + (set! (-> obj bar-cursor-sprite pos w) 0) + ;; bar + (set-hud-piece-position! (-> obj bar-sprite) (the int (adjust-game-x 135.0)) (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 18 15))) + ;; calculate the percentage of the bar based on the range + ;; (actual + abs(range-min)) / (range-max + abs(range-min)) = percentage + (let* ((percentage (/ (+ slider-value (fabs (-> obj min-value))) + (+ (-> obj max-value) (fabs (-> obj min-value))))) + ;; cursor (135 -> 365) = 230 pixels + (cursor-x-pos (adjust-game-x-int (+ 135 (* (if (= (get-aspect-ratio) 'aspect4x3) 230.0 231.0) percentage)))) + (bar-remainder (- (adjust-game-x-int 365) cursor-x-pos))) + ;; cursor position + (set-hud-piece-position! (-> obj bar-cursor-sprite) cursor-x-pos (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 14 11))) + (with-dma-buffer-add-bucket ((buffer (-> *display* frames (-> *display* on-screen) global-buf)) + (bucket-id progress)) + (draw (-> obj bar-sprite) buffer (-> *level* default-level)) + ;; bar mask + ;; TODO - bar remainder isnt correct on custom aspect ratios since those internally still return `aspect4x3` for (get-aspect-ratio), this is a larger issue though + ;; perhaps just standardize menu size in general and ditch aspect ratio differences. + (draw-sprite2d-xy buffer (+ cursor-x-pos 10) (+ (the int (-> font-ctx origin y)) (if (= (get-aspect-ratio) 'aspect4x3) 23 20)) (+ bar-remainder (if (= (get-aspect-ratio) 'aspect4x3) 9 6)) 6 + (new 'static 'rgba :r (the int (* 0.0 alpha slider-value)) + :g (the int (* 0.0 alpha slider-value)) + :b (the int (* 0.0 alpha slider-value)) + :a (the int (* 128.0 alpha)))) + (draw (-> obj bar-cursor-sprite) buffer (-> *level* default-level))))) + (else + (+! (-> font-ctx origin y) -8.0) + (cond + ((and (nonzero? (-> obj should-disable?)) + (!= (-> obj should-disable?) #f) + ((-> obj should-disable?))) + (set-color! font-ctx (font-color progress-option-off)) + (when (= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (draw-generic-highlight (the int (+ -1.0 (-> font-ctx origin y))) 15 0.5))) + ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ -2.0 (-> font-ctx origin y))) 18 alpha)) + (else + (set-color! font-ctx (font-color progress)))) + (if (= (-> obj show-decimal?) #t) + (print-game-text (string-format "~S: ~,,2f" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id progress)) + (print-game-text (string-format "~S: ~D" (lookup-text! *common-text* (-> obj name) #f) slider-value) font-ctx #f 44 (bucket-id progress))))) + ) + (none)) + +(defmethod draw-option menu-generic-details-page ((obj menu-generic-details-page) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol)) + (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?))) + (on-mount! obj)) + ;; the list has a total of 200px of y-height + ;; with 10px of margin at the top and bottom, that leaves 180 / 4 = 45px per item + ;; it's the responsibility of each generic component to center itself within these 45px lines + (when (not (-> *progress-pc-generic-store* clear-screen?)) + (let* ((font-alpha (fmax 0.0 (* 2.0 (- 0.5 (-> progress menu-transition))))) + (hud-bounds (new 'stack-no-clear 'hud-box)) + (max-page-size (if (= (get-aspect-ratio) 'aspect16x9) 12 10)) + (margin-top-bottom 0.0) + (line-height (/ (if (= (get-aspect-ratio) 'aspect16x9) 253.0 200.0) max-page-size))) + (set! (-> font-ctx alpha) font-alpha) + (set-color! font-ctx (font-color progress)) + ;; header + (draw-page-header font-ctx (-> obj name)) + ;; background borders + (draw-page-border (-> obj box 0) font-alpha) + ;; background + (draw-page-background font-alpha) + (begin-scissor-scrolling-page hud-bounds) + (if (= (get-aspect-ratio) 'aspect16x9) + (set! (-> font-ctx origin y) (+ 86.0 margin-top-bottom)) + (set! (-> font-ctx origin y) (+ 112.0 margin-top-bottom))) + ;; render items + (let* ((entry-index (max 0 (* (/ (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size) max-page-size))) + (end-index (min (-> obj entries length) (+ entry-index max-page-size)))) + (while (< entry-index end-index) + (let ((entry (-> obj entries entry-index))) + (when (nonzero? entry) + ;; save the y,x position as who knows where it will end up after the component finishes rendering + (let ((old-y-pos (-> font-ctx origin y)) + (old-x-pos (-> font-ctx origin x))) + (draw-option entry progress font-ctx entry-index + (= (-> obj selected-entry-index) entry-index)) + ;; move to the next line + (set! (-> font-ctx origin y) (+ old-y-pos line-height)) + ;; - debugging, draw the dividing lines to make center new items easier + (draw-generic-page-row-line (the int (-> font-ctx origin y))) + (set! (-> font-ctx origin x) old-x-pos) + ;; reset the font color + (set-color! font-ctx (font-color progress))))) + (+! entry-index 1))) + ;; end + (end-scissor-scrolling-page hud-bounds 1.0) + (set-flags! font-ctx (font-flags kerning large)) + (let* ((draw-up-arrow? (and (not (zero? (-> *progress-pc-generic-store* current-menu-hover-index))) + (>= (-> *progress-pc-generic-store* current-menu-hover-index) max-page-size))) + (last-page-remainder (mod (-> obj entries length) max-page-size)) + (last-page-starting-index (if (zero? last-page-remainder) + (- (-> obj entries length) max-page-size) + (- (-> obj entries length) last-page-remainder))) + (draw-down-arrow? (and (> (-> obj entries length) max-page-size) + (< (-> *progress-pc-generic-store* current-menu-hover-index) last-page-starting-index)))) + (draw-scrolling-page-up-down-arrows font-ctx draw-up-arrow? draw-down-arrow?)))) + (none)) + +(defmethod draw-option menu-generic-details-keybind-entry ((obj menu-generic-details-keybind-entry) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol)) + (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?))) + (on-mount! obj)) + ;; TODO - implement `should-disable?` if it's ever relevant (its not right now) + (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition)))) + (line-height 23.0)) + (max! alpha 0.0) + (set! (-> font-ctx alpha) alpha) + (set-scale! font-ctx 0.40) + (cond + ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ 2.0 (-> font-ctx origin y))) 18 alpha)) + (else + (set-color! font-ctx (font-color progress)))) + ;; Print left aligned text + (set-flags! font-ctx (font-flags kerning left large)) + (-! (-> font-ctx origin y) 1.0) + (when (= (get-aspect-ratio) 'aspect16x9) + (+! (-> font-ctx origin x) 5.0)) + (print-game-text (get-keybind-string obj) font-ctx #f 44 (bucket-id progress)) + ;; Now print the right aligned text + (set! (-> font-ctx origin x) (the float (adjust-game-x (if (= (get-aspect-ratio) 'aspect16x9) 430.0 438.0)))) + (+! (-> font-ctx origin y) 6.0) + (set-flags! font-ctx (font-flags kerning right large)) + (let ((bind (pc-get-current-bind (-> obj bind-info) *pc-cpp-temp-string*))) + (cond + (selected? + (print-game-text (string-format "~S...(~Ds)" (lookup-text! *common-text* (text-id progress-keybinds-waiting-for-bind) #f) + (inc (/ (- (seconds 5) (- (current-time) (-> *progress-pc-generic-store* keybind-select-time))) TICKS_PER_SECOND))) + font-ctx #f 44 (bucket-id progress))) + ((= bind #f) + (print-game-text (lookup-text! *common-text* (text-id progress-keybinds-unset) #f) font-ctx #f 44 (bucket-id progress))) + ((string= *pc-cpp-temp-string* "unknown") + (print-game-text (lookup-text! *common-text* (text-id progress-unknown-option) #f) font-ctx #f 44 (bucket-id progress))) + (else + (print-game-text *pc-cpp-temp-string* font-ctx #f 44 (bucket-id progress)))))) + (none)) + +(defmethod draw-option menu-generic-details-confirm-entry ((obj menu-generic-details-confirm-entry) (progress progress) (font-ctx font-context) (option-index int) (selected? symbol)) + (when (or (zero? (-> obj mounted?)) (not (-> obj mounted?))) + (on-mount! obj)) + ;; TODO - implement `should-disable?` if it's ever relevant (its not right now) + (let ((alpha (* 2.0 (- 0.5 (-> progress menu-transition)))) (line-height 23.0)) (max! alpha 0.0) - (set! (-> arg1 alpha) alpha) - (set-flags! arg1 (font-flags kerning middle large)) - (set-scale! arg1 0.65) - (+! (-> arg1 origin y) 12.5) + (set! (-> font-ctx alpha) alpha) + (set-scale! font-ctx 0.40) (cond ((= option-index (-> *progress-pc-generic-store* current-menu-hover-index)) - (set-color! arg1 (progress-selected 0)) - (draw-generic-highlight (the int (+ -1.0 (-> arg1 origin y))) 22 alpha)) + (set-color! font-ctx (progress-selected 0)) + (draw-generic-highlight (the int (+ 2.0 (-> font-ctx origin y))) 18 alpha)) (else - (set-color! arg1 (font-color progress)))) - (print-game-text (lookup-text! *common-text* (-> obj name) #f) arg1 #f 44 (bucket-id progress))) + (set-color! font-ctx (font-color progress)))) + ;; Print left aligned text + (set-flags! font-ctx (font-flags kerning left large)) + (-! (-> font-ctx origin y) 1.0) + (when (= (get-aspect-ratio) 'aspect16x9) + (+! (-> font-ctx origin x) 5.0)) + (print-game-text (lookup-text! *common-text* (-> obj name) #f) font-ctx #f 44 (bucket-id progress)) + (when selected? + ;; Now print the right aligned text, if the option is selected + (set! (-> font-ctx origin x) (if (= (get-aspect-ratio) 'aspect16x9) 430.0 438.0)) + (+! (-> font-ctx origin y) 6.0) + (set-flags! font-ctx (font-flags kerning right large)) + (clear *temp-string*) + (if (-> obj confirmed?) + (format *temp-string* "~33L~S~35L ~S" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f)) + (format *temp-string* "~35L~S ~33L~S~1L" (lookup-text! *common-text* (text-id progress-yes) #f) (lookup-text! *common-text* (text-id progress-no) #f))) + (print-game-text *temp-string* font-ctx #f 44 (bucket-id progress)))) (none)) diff --git a/goal_src/jak2/pc/progress/progress-generic-h-pc.gc b/goal_src/jak2/pc/progress/progress-generic-h-pc.gc index 8d9c259e777..ae6c1f3c6de 100644 --- a/goal_src/jak2/pc/progress/progress-generic-h-pc.gc +++ b/goal_src/jak2/pc/progress/progress-generic-h-pc.gc @@ -1,10 +1,6 @@ ;;-*-Lisp-*- (in-package goal) -;; TODO: -;; - slider -;; - disabled options -;; - detail list (deftype generic-progress-state-entry (structure) "All info that is pushed onto a 'stack' when navigating to a sub-menu with @@ -16,13 +12,16 @@ ;; so we can restore back to the same menu position (hover-index int32) ;; symbol used normally for progress stuff - (progress-id symbol))) + (progress-id symbol)) + (:methods + (call-on-load (_type_) none))) (deftype progress-pc-generic-store (structure) "Isolated type for keeping track of some global state, as re-using the normal [[*progress*]] object can lead to unexpected behaviour -- they change some values all over the place" ((current-menu-hover-index int32) (clear-screen? symbol) + (keybind-select-time time-frame) (history-stack generic-progress-state-entry 10 :inline) (history-stack-index int32)) (:methods @@ -30,16 +29,34 @@ (navigate! (_type_ progress menu-option-list (function none)) none) (back! (_type_ progress) none) (has-history? (_type_) symbol) - (clear-history-if-empty! (_type_) none))) + (clear-history-if-empty! (_type_) none) + (clear-history! (_type_) none))) (define *progress-pc-generic-store* (new 'static 'progress-pc-generic-store)) (deftype menu-generic-option (menu-option) - ((mounted? symbol)) + ((mounted? symbol) + (should-disable? (function symbol))) (:methods - (on-mount! "Called when the menu item is first drawn as a means to initialize defaults, etc" (_type_) none))) + (on-mount! "Called when the menu item is first drawn as a means to initialize defaults, etc" (_type_) none) + (should-disable? (_type_) symbol))) + +(deftype menu-generic-scrolling-page (menu-generic-option) + "A menu option that holds menu options" + (;; props + (menu-options (array menu-option)) + ;; state + (selected-option-index int32) + (last-move time-frame))) + +(deftype menu-generic-link-option (menu-generic-option) + "A very simple link option that allows you to link to any other [[menu-option-list]]" + (;; props + (target menu-option-list) + ;; generic function to potentially run some setup code when the entry is loaded + ;; this is not called from the link option, but rather stored in the history entry + (on-load (function none)))) -;; TODO - make methods for calling the lambdas just to reduce duplication (checking if the value is set, etc) (deftype menu-generic-boolean-option (menu-generic-option) "Generic two option menu entry (ie. yes/no)" (;; props @@ -49,46 +66,156 @@ (value symbol) ;; lambdas (get-value-fn (function symbol)) - (on-confirm (function symbol none)))) + (on-confirm (function symbol none))) + (:methods + (call-get-value-fn (_type_) symbol) + (call-on-confirm (_type_ symbol) none))) -;; TODO - make methods for calling the lambdas just to reduce duplication (checking if the value is set, etc) (deftype menu-generic-carousel-option (menu-generic-option) "Generic left-right menu entry (ie. language selection)" (;; props + ;; - either you can provide a list of hard-coded items (takes precedence) (items (array text-id)) + ;; - or you can provide functions that return the max-size and the string labels at those indicies + (get-max-size-fn (function int)) + (get-item-label-fn (function int string)) + (no-items-label text-id) ;; TODO - implement if `progress-multiselect-no-items-found` isn't ever sufficient ;; state (item-index int32) ;; lambdas (get-item-index-fn (function int)) - (on-confirm (function int none)))) + (on-confirm (function int none))) + (:methods + (num-items (_type_) int) + (get-item-label (_type_ int) string) + (call-get-item-index-fn (_type_) int) + (call-on-confirm (_type_ int) none))) -(deftype menu-generic-scrolling-page (menu-generic-option) - "A menu option that holds menu options" +(deftype menu-generic-confirm-option (menu-generic-option) + "A button option that confirms before triggering it's action" (;; props - (menu-options (array menu-option)) - (header text-id) + (on-confirm (function none)) ;; state - (selected-option-item menu-option) - (selected-option-index int32) - (last-move time-frame))) + (confirmed? symbol)) + (:methods + (call-on-confirm (_type_) none))) -;; TODO - make methods for calling the lambdas just to reduce duplication (checking if the value is set, etc) -(deftype menu-generic-link-option (menu-generic-option) - "A very simple link option that allows you to link to any other menu-option" +(deftype menu-generic-slider-option (menu-generic-option) + "A generic slider, can go into the negative as well." (;; props - (target menu-option-list) - ;; generic function to potentially run some setup code when the entry is loaded - (on-load (function none)))) + (min-value float) + (max-value float) + (step float) + (show-decimal? symbol) + ;; state + (value float) + (bar-sprite hud-sprite :inline) + (bar-cursor-sprite hud-sprite :inline) + (last-sound-played time-frame) + ;; lambdas + (get-value-fn (function float)) + (on-confirm (function float none))) + (:methods + (call-get-value-fn (_type_) float) + (call-on-confirm (_type_ float) none))) + +(deftype menu-generic-details-entry (menu-generic-option) + "A generic details list entry" + ()) + +(defenum controller-keybind + :type int8 + (select 0) + (l3 1) + (r3 2) + (start 3) + (dpad-up 4) + (dpad-right 5) + (dpad-down 6) + (dpad-left 7) + (l2 8) + (r2 9) + (l1 10) + (r1 11) + (triangle 12) + (circle 13) + (cross 14) + (square 15) + (l-analog-up 16) + (l-analog-down 17) + (l-analog-left 18) + (l-analog-right 19) + (r-analog-up 20) + (r-analog-down 21) + (r-analog-left 22) + (r-analog-right 23)) + +(defenum input-device-type + :type int8 + (controller 0) + (keyboard 1) + (mouse 2)) + +(deftype menu-generic-details-keybind-entry (menu-generic-details-entry) + ((keybind controller-keybind) + (device-type input-device-type) + ;; state + (bind-info bind-assignment-info :inline)) + (:methods + (get-keybind-string (_type_) string))) + +(deftype menu-generic-details-confirm-entry (menu-generic-details-entry) + (;; props + (on-confirm (function none)) + ;; state + (confirmed? symbol)) + (:methods + (call-on-confirm (_type_) none))) + +(deftype menu-generic-details-page (menu-generic-option) + "A generic details list page, compact rows that can be selected. + This is very similar to the [[menu-generic-scrolling-page]] component but instead of holding + [[menu-option]]s, it holds [[menu-generic-details-entry]]'s" + ((entries (array menu-generic-details-entry)) + ;; state + (selected-entry-index int32) + (last-move time-frame))) + +(defmacro progress-new-generic-option (option) + `(new 'static 'menu-option-list :options (new 'static 'boxed-array :type menu-option ,option))) (defmacro progress-new-generic-scrolling-page (title &rest options) `(new 'static 'menu-option-list :options (new 'static 'boxed-array :type menu-option (new 'static 'menu-generic-scrolling-page - :name ,title ; (text-id progress-misc-game-options) + :name ,title :menu-options (new 'static 'boxed-array :type menu-option ,@options))))) -(defmacro progress-new-generic-link (text target) +(defmacro progress-new-generic-link (text target &key (should-disable? #f)) `(new 'static 'menu-generic-link-option :name ,text + :should-disable? ,should-disable? :target ,target)) + +(defmacro progress-new-generic-link-to-scrolling-page (title &key (should-disable? #f) &rest options) + `(new 'static 'menu-generic-link-option + :name ,title + :should-disable? ,should-disable? + :target (new 'static 'menu-option-list + :options (new 'static 'boxed-array :type menu-option + (new 'static 'menu-generic-scrolling-page + :name ,title + :menu-options (new 'static 'boxed-array :type menu-option + ,@options)))))) + +(defmacro progress-new-generic-link-to-details-page (title &key (should-disable? #f) &rest entries) + `(new 'static 'menu-generic-link-option + :name ,title + :should-disable? ,should-disable? + :target (new 'static 'menu-option-list + :options (new 'static 'boxed-array :type menu-option + (new 'static 'menu-generic-details-page + :name ,title + :entries (new 'static 'boxed-array :type menu-generic-details-entry + ,@entries)))))) diff --git a/goal_src/jak2/pc/progress/progress-generic-pc.gc b/goal_src/jak2/pc/progress/progress-generic-pc.gc index 96441cabeab..815728e3d1a 100644 --- a/goal_src/jak2/pc/progress/progress-generic-pc.gc +++ b/goal_src/jak2/pc/progress/progress-generic-pc.gc @@ -1,8 +1,54 @@ ;;-*-Lisp-*- (in-package goal) +(defmethod call-on-load generic-progress-state-entry ((this generic-progress-state-entry)) + (when (and (nonzero? (-> this on-load)) (!= (-> this on-load) #f)) + ((-> this on-load))) + (none)) + +(defmethod call-get-value-fn menu-generic-boolean-option ((this menu-generic-boolean-option)) + (if (and (nonzero? (-> this get-value-fn)) (!= (-> this get-value-fn) #f)) + ((-> this get-value-fn)) + #f)) + +(defmethod call-on-confirm menu-generic-boolean-option ((this menu-generic-boolean-option) (val symbol)) + (when (and (nonzero? (-> this on-confirm)) (!= (-> this on-confirm) #f)) + ((-> this on-confirm) val)) + (none)) + +(defmethod call-get-item-index-fn menu-generic-carousel-option ((this menu-generic-carousel-option)) + (if (and (nonzero? (-> this get-item-index-fn)) (!= (-> this get-item-index-fn) #f)) + ((-> this get-item-index-fn)) + 0)) + +(defmethod call-on-confirm menu-generic-carousel-option ((this menu-generic-carousel-option) (val int)) + (when (and (nonzero? (-> this on-confirm)) (!= (-> this on-confirm) #f)) + ((-> this on-confirm) val)) + (none)) + +(defmethod call-on-confirm menu-generic-confirm-option ((this menu-generic-confirm-option)) + (when (and (nonzero? (-> this on-confirm)) (!= (-> this on-confirm) #f)) + ((-> this on-confirm))) + (none)) + +(defmethod call-get-value-fn menu-generic-slider-option ((this menu-generic-slider-option)) + (if (and (nonzero? (-> this get-value-fn)) (!= (-> this get-value-fn) #f)) + ((-> this get-value-fn)) + 0.0)) + +(defmethod call-on-confirm menu-generic-slider-option ((this menu-generic-slider-option) (val float)) + (when (and (nonzero? (-> this on-confirm)) (!= (-> this on-confirm) #f)) + ((-> this on-confirm) val)) + (none)) + (defmethod init! progress-pc-generic-store ((this progress-pc-generic-store)) (set! (-> this clear-screen?) #f) + (set! (-> this keybind-select-time) 0) + (none)) + +(defmethod call-on-confirm menu-generic-details-confirm-entry ((this menu-generic-details-confirm-entry)) + (when (and (nonzero? (-> this on-confirm)) (!= (-> this on-confirm) #f)) + ((-> this on-confirm))) (none)) (defmethod navigate! progress-pc-generic-store ((this progress-pc-generic-store) (progress progress) (target menu-option-list) (on-load (function none))) @@ -43,8 +89,7 @@ (> (-> this history-stack-index) 0)) (defmethod clear-history-if-empty! progress-pc-generic-store ((this progress-pc-generic-store)) - ;; if we are have no history, just reset the entry. This is so we don't preserve state - ;; after completely exiting the menu + "if we have no history, just reset the entry. This is so we don't preserve state after completely exiting the menu" (when (not (has-history? this)) (set! (-> this history-stack-index) 0) (set! (-> this clear-screen?) #f) @@ -56,10 +101,18 @@ (set! (-> stack-entry progress-id) #f))) (none)) +(defmethod clear-history! progress-pc-generic-store ((this progress-pc-generic-store)) + (set! (-> this history-stack-index) 0) + (set! (-> this clear-screen?) #t) + (set! (-> this current-menu-hover-index) 0) + (none)) + (defmethod on-mount! menu-generic-option ((this menu-generic-option)) (set! (-> this mounted?) #t) (none)) +;; TODO - call the parent methods, when there is an elegant way to do so (not having to know the ID) + (defmethod on-mount! menu-generic-carousel-option ((this menu-generic-carousel-option)) (set! (-> this mounted?) #t) (set! (-> this item-index) 0) @@ -67,10 +120,47 @@ (defmethod on-mount! menu-generic-scrolling-page ((this menu-generic-scrolling-page)) (set! (-> this mounted?) #t) - (set! (-> this selected-option-item) #f) (set! (-> this selected-option-index) -1) (none)) +(defmethod on-mount! menu-generic-details-page ((this menu-generic-details-page)) + (set! (-> this mounted?) #t) + (set! (-> this selected-entry-index) -1) + (none)) + +(defmethod on-mount! menu-generic-confirm-option ((this menu-generic-confirm-option)) + (set! (-> this mounted?) #t) + (set! (-> this confirmed?) #f) + (none)) + +(defun controller-keybind->input-index ((bind controller-keybind)) + (case bind + (((controller-keybind l-analog-up)) 1) + (((controller-keybind l-analog-down)) 1) + (((controller-keybind l-analog-left)) 0) + (((controller-keybind l-analog-right)) 0) + (((controller-keybind r-analog-up)) 3) + (((controller-keybind r-analog-down)) 3) + (((controller-keybind r-analog-left)) 2) + (((controller-keybind r-analog-right)) 2) + (else (the int bind)))) + +(defmethod on-mount! menu-generic-details-keybind-entry ((this menu-generic-details-keybind-entry)) + (set! (-> this mounted?) #t) + (set! (-> this bind-info port) 0) ;; always port 0 for now + (set! (-> this bind-info device-type) (the int (-> this device-type))) + (set! (-> this bind-info for-buttons?) #t) + (set! (-> this bind-info analog-min-range?) #f) + (set! (-> this bind-info input-idx) (controller-keybind->input-index (-> this keybind))) + (case (-> this keybind) + (((controller-keybind l-analog-up) (controller-keybind l-analog-down) (controller-keybind l-analog-left) (controller-keybind l-analog-right) + (controller-keybind r-analog-up) (controller-keybind r-analog-down) (controller-keybind r-analog-left) (controller-keybind r-analog-right)) + (set! (-> this bind-info for-buttons?) #f) + (case (-> this keybind) + (((controller-keybind l-analog-up) (controller-keybind l-analog-left) (controller-keybind r-analog-up) (controller-keybind r-analog-left)) + (set! (-> this bind-info analog-min-range?) #t))))) + (none)) + ;; Progress Code Overrides (defmethod respond-to-cpad progress ((obj progress)) @@ -83,7 +173,8 @@ (has-generic-history? (has-history? *progress-pc-generic-store*))) (when (and option-array (= (-> obj menu-transition) 0.0)) (let ((in-generic-page? (and (= (-> option-array length) 1) - (type? (-> option-array 0) menu-generic-scrolling-page)))) + (or (type? (-> option-array 0) menu-generic-scrolling-page) + (type? (-> option-array 0) menu-generic-details-page))))) (cond ;; If it's a scrolling menu, we have to pull from it's list of items (in-generic-page? @@ -163,53 +254,65 @@ ;; Component implementation +;; - input handling + (defmethod respond-progress menu-generic-scrolling-page ((obj menu-generic-scrolling-page) (progress progress) (selected? symbol)) "Handle progress menu navigation logic." - (if (or (= (-> obj selected-option-item) #f) - (zero? (-> obj selected-option-item))) - (cond - ((or (cpad-pressed? 0 down l-analog-down) - (and (cpad-hold? 0 down l-analog-down) - (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) - (set! (-> obj last-move) (current-time)) - (cond - ((< (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj menu-options length))) - (+! (-> *progress-pc-generic-store* current-menu-hover-index) 1) - (sound-play "roll-over")) - (else - (set! (-> *progress-pc-generic-store* current-menu-hover-index) 0) - (sound-play "roll-over")))) - ((or (cpad-pressed? 0 up l-analog-up) - (and (cpad-hold? 0 up l-analog-up) - (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) + (let ((selected-item? #f)) + (if (= (-> obj selected-option-index) -1) + (cond + ((or (cpad-pressed? 0 down l-analog-down) + (and (cpad-hold? 0 down l-analog-down) + (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) (set! (-> obj last-move) (current-time)) - (+! (-> *progress-pc-generic-store* current-menu-hover-index) -1) - (sound-play "roll-over") - (when (< (-> *progress-pc-generic-store* current-menu-hover-index) 0) - (set! (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj menu-options length))))) - ((cpad-pressed? 0 confirm) - ;; ignore confirm if it's a link - (when (and (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj menu-options length)) - (not (type? (-> obj menu-options (-> *progress-pc-generic-store* current-menu-hover-index)) menu-generic-link-option))) - (set! (-> obj selected-option-index) (-> *progress-pc-generic-store* current-menu-hover-index)) - (set! (-> obj selected-option-item) (-> obj menu-options (-> *progress-pc-generic-store* current-menu-hover-index)))) - (sound-play "generic-beep")) - ((cpad-pressed? 0 triangle) - ;; we are in a sub-page, time to go back - (when (has-history? *progress-pc-generic-store*) - (back! *progress-pc-generic-store* progress) - (sound-play "score-slide"))) - ) - (cond - ((cpad-pressed? 0 confirm) - (set! (-> obj selected-option-index) -1) - (set! (-> obj selected-option-item) #f)) - ((cpad-pressed? 0 triangle) - (set! (-> obj selected-option-index) -1) - (set! (-> obj selected-option-item) #f)))) - ;; propagate event to menu-option - (when (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj menu-options length)) - (respond-progress (-> obj menu-options (-> *progress-pc-generic-store* current-menu-hover-index)) progress selected?)) + (cond + ((< (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj menu-options length))) + (+! (-> *progress-pc-generic-store* current-menu-hover-index) 1) + (sound-play "roll-over")) + (else + (set! (-> *progress-pc-generic-store* current-menu-hover-index) 0) + (sound-play "roll-over")))) + ((or (cpad-pressed? 0 up l-analog-up) + (and (cpad-hold? 0 up l-analog-up) + (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) + (set! (-> obj last-move) (current-time)) + (+! (-> *progress-pc-generic-store* current-menu-hover-index) -1) + (sound-play "roll-over") + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) 0) + (set! (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj menu-options length))))) + ((cpad-pressed? 0 confirm) + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj menu-options length)) + (let ((menu-option (-> obj menu-options (-> *progress-pc-generic-store* current-menu-hover-index)))) + ;; if the option is disabled, return early + (when (and (type? menu-option menu-generic-option) + (nonzero? (-> (the-as menu-generic-option menu-option) should-disable?)) + (!= (-> (the-as menu-generic-option menu-option) should-disable?) #f) + ((-> (the-as menu-generic-option menu-option) should-disable?))) + (sound-play "roll-over") + (logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons confirm)) + (logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons confirm)) + (return 0)) + ;; ignore confirm if it's a link + (cond + ((type? menu-option menu-generic-link-option) + (set! selected-item? #t)) + (else + (set! (-> obj selected-option-index) (-> *progress-pc-generic-store* current-menu-hover-index)) + (sound-play "generic-beep")))))) + ((cpad-pressed? 0 triangle) + ;; we are in a sub-page, time to go back + (when (has-history? *progress-pc-generic-store*) + (back! *progress-pc-generic-store* progress) + (sound-play "score-slide")))) + ;; menu option already selected + (cond + ((cpad-pressed? 0 confirm) + (set! (-> obj selected-option-index) -1)) + ((cpad-pressed? 0 triangle) + (set! (-> obj selected-option-index) -1)))) + ;; propagate event to menu-option + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj menu-options length)) + (respond-progress (-> obj menu-options (-> *progress-pc-generic-store* current-menu-hover-index)) progress (or selected? selected-item?)))) 0) (defmethod respond-progress menu-generic-boolean-option ((obj menu-generic-boolean-option) (progress progress) (selected? symbol)) @@ -221,16 +324,13 @@ (set! (-> obj value) #t)) (sound-play "generic-beep")) ((cpad-pressed? 0 confirm) - (when (and (nonzero? (-> obj on-confirm)) (!= (-> obj on-confirm) #f)) - ((-> obj on-confirm) (-> obj value))) + (call-on-confirm obj (-> obj value)) (sound-play "generic-beep"))) (cond ((cpad-pressed? 0 confirm) ;; set the value, this is so we edit the component's state and not the actual underlying value ;; in other words, don't change the setting until the user has actually confirmed the change! - (when (and (nonzero? (-> obj get-value-fn)) - (!= (-> obj get-value-fn) #f)) - (set! (-> obj value) ((-> obj get-value-fn))))))) + (set! (-> obj value) (call-get-value-fn obj))))) 0) (defmethod respond-progress menu-generic-carousel-option ((obj menu-generic-carousel-option) (progress progress) (selected? symbol)) @@ -239,30 +339,223 @@ ((cpad-pressed? 0 left l-analog-left) (dec! (-> obj item-index)) (when (< (-> obj item-index) 0) - (set! (-> obj item-index) (dec (-> obj items length)))) + (set! (-> obj item-index) (dec (num-items obj)))) (sound-play "generic-beep")) ((cpad-pressed? 0 right l-analog-right) (inc! (-> obj item-index)) - (when (>= (-> obj item-index) (-> obj items length)) + (when (>= (-> obj item-index) (num-items obj)) (set! (-> obj item-index) 0)) (sound-play "generic-beep")) ((cpad-pressed? 0 confirm) - (when (and (nonzero? (-> obj on-confirm)) (!= (-> obj on-confirm) #f)) - ((-> obj on-confirm) (-> obj item-index))) + (call-on-confirm obj (-> obj item-index)) (sound-play "generic-beep"))) (cond ((cpad-pressed? 0 confirm) ;; set the value, this is so we edit the component's state and not the actual underlying value ;; in other words, don't change the setting until the user has actually confirmed the change! - (when (and (nonzero? (-> obj get-item-index-fn)) (!= (-> obj get-item-index-fn) #f)) - (set! (-> obj item-index) ((-> obj get-item-index-fn))))))) + (set! (-> obj item-index) (call-get-item-index-fn obj))))) 0) (defmethod respond-progress menu-generic-link-option ((obj menu-generic-link-option) (progress progress) (selected? symbol)) - (when (>= (-> *progress-pc-generic-store* current-menu-hover-index) 0) + (when (and selected? (cpad-pressed? 0 confirm)) + (navigate! *progress-pc-generic-store* progress (-> obj target) (-> obj on-load)) + (set! (-> progress selected-option) #f) + (sound-play "score-slide")) + 0) + +(defmethod respond-progress menu-generic-confirm-option ((obj menu-generic-confirm-option) (progress progress) (selected? symbol)) + (if selected? + (cond + ((cpad-pressed? 0 left l-analog-left right l-analog-right) + (if (-> obj confirmed?) + (set! (-> obj confirmed?) #f) + (set! (-> obj confirmed?) #t)) + (sound-play "generic-beep")) + ((cpad-pressed? 0 confirm) + (call-on-confirm obj) + (sound-play "generic-beep"))) (cond ((cpad-pressed? 0 confirm) - (navigate! *progress-pc-generic-store* progress (-> obj target) (-> obj on-load)) - (set! (-> progress selected-option) #f) - (sound-play "score-slide")))) + (set! (-> obj confirmed?) #f)))) + 0) + +(defmethod respond-progress menu-generic-slider-option ((obj menu-generic-slider-option) (progress progress) (selected? symbol)) + (if selected? + (cond + ((and (> (-> obj value) (-> obj min-value)) + (cpad-hold? 0 left l-analog-left)) + ;; TODO - might not work well on higher frame-rates + (set! (-> obj value) (fmax (- (-> obj value) (-> obj step)) (-> obj min-value))) + (when (< (seconds 0.03) (- (current-time) (-> obj last-sound-played))) + (set! (-> obj last-sound-played) (current-time)) + (sound-play-by-name (static-sound-name "menu-slide") (new-sound-id) 512 0 0 (sound-group sfx) #t))) + ((and (< (-> obj value) (-> obj max-value)) + (cpad-hold? 0 right l-analog-right)) + ;; TODO - might not work well on higher frame-rates + (set! (-> obj value) (fmin (+ (-> obj value) (-> obj step)) (-> obj max-value))) + (when (< (seconds 0.03) (- (current-time) (-> obj last-sound-played))) + (set! (-> obj last-sound-played) (current-time)) + (sound-play-by-name (static-sound-name "menu-slide") (new-sound-id) 512 0 0 (sound-group sfx) #t))) + ((cpad-pressed? 0 confirm) + (call-on-confirm obj (-> obj value)) + (sound-play "generic-beep"))) + (cond + ((cpad-pressed? 0 confirm) + ;; set the value, this is so we edit the component's state and not the actual underlying value + ;; in other words, don't change the setting until the user has actually confirmed the change! + (set! (-> obj value) (call-get-value-fn obj))))) 0) + +(defmethod respond-progress menu-generic-details-page ((obj menu-generic-details-page) (progress progress) (selected? symbol)) + (if (= (-> obj selected-entry-index) -1) + (cond + ((or (cpad-pressed? 0 down l-analog-down) + (and (cpad-hold? 0 down l-analog-down) + (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) + (set! (-> obj last-move) (current-time)) + (cond + ((< (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj entries length))) + (+! (-> *progress-pc-generic-store* current-menu-hover-index) 1) + (sound-play "roll-over")) + (else + (set! (-> *progress-pc-generic-store* current-menu-hover-index) 0) + (sound-play "roll-over")))) + ((or (cpad-pressed? 0 up l-analog-up) + (and (cpad-hold? 0 up l-analog-up) + (>= (- (current-time) (the-as int (-> obj last-move))) (seconds 0.5)))) + (set! (-> obj last-move) (current-time)) + (+! (-> *progress-pc-generic-store* current-menu-hover-index) -1) + (sound-play "roll-over") + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) 0) + (set! (-> *progress-pc-generic-store* current-menu-hover-index) (dec (-> obj entries length))))) + ((cpad-pressed? 0 confirm) + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj entries length)) + (set! (-> obj selected-entry-index) (-> *progress-pc-generic-store* current-menu-hover-index)) + (sound-play "generic-beep"))) + ((cpad-pressed? 0 triangle) + ;; we are in a sub-page, time to go back + (when (has-history? *progress-pc-generic-store*) + (back! *progress-pc-generic-store* progress) + (sound-play "score-slide")))) + ;; menu option already selected + (cond + ((cpad-pressed? 0 confirm) + (set! (-> obj selected-entry-index) -1)) + ((cpad-pressed? 0 triangle) + (set! (-> obj selected-entry-index) -1)) + ;; keybinds + ((nonzero? (-> *progress-pc-generic-store* keybind-select-time)) + ;; when the bind has been set, or it's expired + (when (or (not (pc-waiting-for-bind?)) + (>= (- (current-time) (the-as int (-> *progress-pc-generic-store* keybind-select-time))) (seconds 5.0))) + (set! (-> *progress-pc-generic-store* keybind-select-time) 0) + (set! (-> obj selected-entry-index) -1) + (set! (-> progress selected-option) #f) + (cond + ((not (pc-waiting-for-bind?)) + (sound-play "generic-beep")) + (else + (pc-stop-waiting-for-bind!) + (sound-play "roll-over"))))))) + ;; propagate event to menu-option + (when (< (-> *progress-pc-generic-store* current-menu-hover-index) (-> obj entries length)) + (respond-progress (-> obj entries (-> *progress-pc-generic-store* current-menu-hover-index)) progress selected?)) + 0) + +(defmethod respond-progress menu-generic-details-keybind-entry ((obj menu-generic-details-keybind-entry) (progress progress) (selected? symbol)) + (when (not selected?) + (cond + ((cpad-pressed? 0 confirm) + (let ((bind-info (-> obj bind-info))) + (pc-set-waiting-for-bind! (-> bind-info device-type) (not (-> bind-info for-buttons?)) (-> bind-info analog-min-range?) (-> bind-info input-idx))) + (set! (-> *progress-pc-generic-store* keybind-select-time) (current-time))))) + 0) + +(defmethod respond-progress menu-generic-details-confirm-entry ((obj menu-generic-details-confirm-entry) (progress progress) (selected? symbol)) + (if selected? + (cond + ((cpad-pressed? 0 left l-analog-left right l-analog-right) + (if (-> obj confirmed?) + (set! (-> obj confirmed?) #f) + (set! (-> obj confirmed?) #t)) + (sound-play "generic-beep")) + ((cpad-pressed? 0 confirm) + (call-on-confirm obj) + (sound-play "generic-beep"))) + (cond + ((cpad-pressed? 0 confirm) + (set! (-> obj confirmed?) #f)))) + 0) + +;; - rest of component logic + +(defmethod num-items menu-generic-carousel-option ((this menu-generic-carousel-option)) + "Get the number of items in the carousel" + (if (and (nonzero? (-> this items)) (!= (-> this items) #f)) + (-> this items length) + (if (and (and (nonzero? (-> this get-max-size-fn)) (!= (-> this get-max-size-fn) #f)) + (and (nonzero? (-> this get-item-label-fn)) (!= (-> this get-max-size-fn) #f))) + ((-> this get-max-size-fn)) + 0))) + +(defmethod get-item-label menu-generic-carousel-option ((this menu-generic-carousel-option) (item-index int)) + "Gets the string label of the currently choosen item, preferring the `items` array if it exists" + (if (and (nonzero? (-> this items)) (!= (-> this items) #f)) + (lookup-text! *common-text* (-> this items item-index) #f) + (if (and (nonzero? (-> this get-item-label-fn)) (!= (-> this get-max-size-fn) #f)) + ((-> this get-item-label-fn) item-index) + "#ERROR"))) + +;; TODO - it could be possible to map certain controllers to buttons (ie. dualshock controllers could have nice mappings instead of SDL named ones) +(defmethod get-keybind-string menu-generic-details-keybind-entry ((this menu-generic-details-keybind-entry)) + (case (-> this keybind) + (((controller-keybind cross)) + "~Y~22L<~Z~Y~27L*~Z~Y~1L>~Z~Y~23L[~Z~+26H Cross") + (((controller-keybind square)) + "~Y~22L<~Z~Y~24L#~Z~Y~1L>~Z~Y~23L[~Z~+26H S~+7Vq~-7Vuare") + (((controller-keybind circle)) + "~Y~22L<~Z~Y~25L@~Z~Y~1L>~Z~Y~23L[~Z~+26H Circle") + (((controller-keybind triangle)) + "~Y~22L<~Z~Y~26L;~Z~Y~1L>~Z~Y~23L[~Z~+26H Trian~+7Vg~-7Vle") + (((controller-keybind dpad-up)) + "~Y~0L\ca1~Z~3L~+17H~-13V\ca2~Z~0L~+17H~+14V\ca0~Z~0L~+32H\ca3~Z~+56H D-Pad U~+7Vp~-7V") + (((controller-keybind dpad-down)) + "~Y~0L\ca1~Z~0L~+17H~-13V\ca2~Z~3L~+17H~+14V\ca0~Z~0L~+32H\ca3~Z~+56H D-Pad Down") + (((controller-keybind dpad-right)) + "~Y~0L\ca1~Z~0L~+17H~-13V\ca2~Z~0L~+17H~+14V\ca0~Z~3L~+32H\ca3~Z~+56H D-Pad Ri~+7Vg~-7Vht") + (((controller-keybind dpad-left)) + "~Y~3L\ca1~Z~0L~+17H~-13V\ca2~Z~0L~+17H~+14V\ca0~Z~0L~+32H\ca3~Z~+56H D-Pad Left") + (((controller-keybind l1)) + "~Y~22L~-2H~-12V\ca6\ca7~Z~22L~-2H~+17V\cb0\cb1~Z~1L~+4H~+3V\c95~Z~+38H L1") + (((controller-keybind l2)) + "~Y~22L~-2H~-6V\ca8\ca9~Z~22L~-2H~+16V\cb2\cb3~Z~1L~+5H~-2V\c97~Z~+38H L2") + (((controller-keybind l3)) + "\c91 L3") + (((controller-keybind r1)) + "~Y~22L~-2H~-12V\ca6\ca7~Z~22L~-2H~+17V\cb0\cb1~Z~1L~+6H~+3V\c94~Z~+38H R1") + (((controller-keybind r2)) + "~Y~22L~-2H~-6V\ca8\ca9~Z~22L~-2H~+16V\cb2\cb3~Z~1L~+5H~-2V\c96~Z~+38H R2") + (((controller-keybind r3)) + "\c91 R3") + (((controller-keybind select)) + "\c92 Select") + (((controller-keybind start)) + "\c92 Start") + (((controller-keybind l-analog-up)) + "~Y~1L\c91~Z~-17V~6L\c98~Z~+26H Left Analo~+7Vg~-7V U~+7Vp~-7V") + (((controller-keybind l-analog-down)) + "~Y~1L\c91~Z~+15V~6L\c9c~Z~+26H Left Analo~+7Vg~-7V Down") + (((controller-keybind l-analog-left)) + "~Y~1L\c91~Z~-17H~6L\c9e~Z~+26H Left Analo~+7Vg~-7V Left") + (((controller-keybind l-analog-right)) + "~Y~1L\c91~Z~+17H~6L\ca4~Z~+26H Left Analo~+7Vg~-7V Ri~+7Vg~-7Vht") + (((controller-keybind r-analog-up)) + "~Y~1L\c91~Z~-17V~6L\c98~Z~+26H Ri~+7Vg~-7Vht Analo~+7Vg~-7V U~+7Vp~-7V") + (((controller-keybind r-analog-down)) + "~Y~1L\c91~Z~+15V~6L\c9c~Z~+26H Ri~+7Vg~-7Vht Analo~+7Vg~-7V Down") + (((controller-keybind r-analog-left)) + "~Y~1L\c91~Z~-17H~6L\c9e~Z~+26H Ri~+7Vg~-7Vht Analo~+7Vg~-7V Left") + (((controller-keybind r-analog-right)) + "~Y~1L\c91~Z~+17H~6L\ca4~Z~+26H Ri~+7Vg~-7Vht Analo~+7Vg~-7V Ri~+7Vg~-7Vht") + (else + "Unknown Bind"))) diff --git a/goal_src/jak2/pc/progress/progress-pc.gc b/goal_src/jak2/pc/progress/progress-pc.gc index 99698e9062b..5d340547bb2 100644 --- a/goal_src/jak2/pc/progress/progress-pc.gc +++ b/goal_src/jak2/pc/progress/progress-pc.gc @@ -355,8 +355,7 @@ (-> *progress-pc-generic-store* history-stack-index)))) ;; call the on-load function is appropriate, this can be used to perform some kind of generic setup ;; for the particular route - (when (and (nonzero? (-> curr-history-entry on-load)) (!= (-> curr-history-entry on-load) #f)) - ((-> curr-history-entry on-load))) + (call-on-load curr-history-entry) ;; restore state from the history entry (set! (-> *progress-pc-generic-store* clear-screen?) #f) (set! (-> *progress-pc-generic-store* current-menu-hover-index) (-> curr-history-entry hover-index)) @@ -751,6 +750,7 @@ (when (and *progress-process* *progress-state* (!= (-> *progress-state* starting-state) 'title)) (stop-music-player) (set-next-state (-> *progress-process* 0) 'go-away 0) + (clear-history! *progress-pc-generic-store*) ) 0 (none) diff --git a/goal_src/jak2/pc/progress/progress-static-pc.gc b/goal_src/jak2/pc/progress/progress-static-pc.gc index 824704b981a..76179a9b9ca 100644 --- a/goal_src/jak2/pc/progress/progress-static-pc.gc +++ b/goal_src/jak2/pc/progress/progress-static-pc.gc @@ -1,24 +1,263 @@ ;;-*-Lisp-*- (in-package goal) -#| - - Additional PC port specific file for overriding/expanding the progress menu - This gives us more freedom to write code how we want. - +#|@file +Additional PC port specific file for overriding/expanding the progress menu +This gives us more freedom to write code how we want. |# - (set! (-> *main-options-debug* options 9) (new 'static 'menu-main-menu-option :name (text-id progress-music-player) :scale #t :next-state 'music-player)) +;; in jak 2, the options dont have to be all-caps anymore! +;; encode controller/display names - current bug waiting to happen + (define *game-options-pc* (progress-new-generic-scrolling-page (text-id progress-root-game-options) - (new 'static 'menu-generic-boolean-option - :name (text-id progress-vibration) - :truthy-text (text-id progress-on) - :falsey-text (text-id progress-off) - :get-value-fn (lambda () (-> *setting-control* user-default vibration)) - :on-confirm (lambda ((val symbol)) (set! (-> *setting-control* user-default vibration) val))) + (progress-new-generic-link-to-scrolling-page (text-id progress-menu-input-options) + (progress-new-generic-link-to-scrolling-page (text-id progress-camera-options) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-camera-options-first-horz) + :truthy-text (text-id progress-normal) + :falsey-text (text-id progress-inverted) + :get-value-fn (lambda () (-> *pc-settings* first-camera-h-inverted?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* first-camera-h-inverted?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-camera-options-first-vert) + :truthy-text (text-id progress-normal) + :falsey-text (text-id progress-inverted) + :get-value-fn (lambda () (-> *pc-settings* first-camera-v-inverted?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* first-camera-v-inverted?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-camera-options-third-horz) + :truthy-text (text-id progress-normal) + :falsey-text (text-id progress-inverted) + :get-value-fn (lambda () (-> *pc-settings* third-camera-h-inverted?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* third-camera-h-inverted?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-camera-options-third-vert) + :truthy-text (text-id progress-normal) + :falsey-text (text-id progress-inverted) + :get-value-fn (lambda () (-> *pc-settings* third-camera-v-inverted?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* third-camera-v-inverted?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-confirm-option + :name (text-id progress-restore-defaults) + :on-confirm (lambda ((val symbol)) + (reset-camera *pc-settings* #t) + (commit-to-file *pc-settings*)))) + (progress-new-generic-link-to-scrolling-page (text-id progress-menu-controller-options) :should-disable? (lambda () (<= (pc-get-controller-count) 0)) + (new 'static 'menu-generic-carousel-option + :name (text-id progress-controller-options-select-controller) + :get-max-size-fn (lambda () (pc-get-controller-count)) + :get-item-label-fn (lambda ((index int)) + (pc-get-controller-name index *pc-cpp-temp-string*) + *pc-cpp-temp-string*) + :get-item-index-fn (lambda () 0) + :on-confirm (lambda ((index int)) (pc-set-controller! 0 index))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-vibration) + :should-disable? (lambda () (not (pc-current-controller-has-rumble?))) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *setting-control* user-default vibration)) + :on-confirm (lambda ((val symbol)) (set! (-> *setting-control* user-default vibration) val))) + (new 'static 'menu-generic-slider-option + :name (text-id progress-controller-options-analog-deadzone) + :min-value 0.0 + :max-value 1.0 + :step 0.01 + :show-decimal? #t + :get-value-fn (lambda () (-> *pc-settings* stick-deadzone)) + :on-confirm (lambda ((val float)) + (set! (-> *pc-settings* stick-deadzone) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-controller-options-ignore-if-unfocused) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* ignore-controller-win-unfocused?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* ignore-controller-win-unfocused?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-controller-options-led-hp) + :should-disable? (lambda () (not (pc-current-controller-has-led?))) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* controller-hp-led?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* controller-hp-led?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-controller-options-led-darkjak) + :should-disable? (lambda () (not (pc-current-controller-has-led?))) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* controller-eco-led?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* controller-eco-led?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-confirm-option + :name (text-id progress-restore-defaults) + :on-confirm (lambda ((val symbol)) + (reset-input *pc-settings* 'controller #t) + (set-ignore-controller-in-bg! *pc-settings* (-> *pc-settings* ignore-controller-win-unfocused?)) + (commit-to-file *pc-settings*)))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-input-options-enable-keyboard) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* keyboard-enabled?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* keyboard-enabled?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-input-options-enable-mouse) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* mouse-enabled?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* mouse-enabled?) val) + (commit-to-file *pc-settings*))) + (progress-new-generic-link-to-scrolling-page (text-id progress-menu-mouse-options) :should-disable? (lambda () (not (-> *pc-settings* mouse-enabled?))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-mouse-options-track-camera) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* mouse-camera?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* mouse-camera?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-slider-option + :name (text-id progress-mouse-options-horz-sens) + :should-disable? (lambda () (not (-> *pc-settings* mouse-camera?))) + :min-value -30.0 + :max-value 30.0 + :step 0.10 + :show-decimal? #t + :get-value-fn (lambda () (-> *pc-settings* mouse-xsens)) + :on-confirm (lambda ((val float)) + (set! (-> *pc-settings* mouse-xsens) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-slider-option + :name (text-id progress-mouse-options-vert-sens) + :should-disable? (lambda () (not (-> *pc-settings* mouse-camera?))) + :min-value -30.0 + :max-value 30.0 + :step 0.10 + :show-decimal? #t + :get-value-fn (lambda () (-> *pc-settings* mouse-ysens)) + :on-confirm (lambda ((val float)) + (set! (-> *pc-settings* mouse-ysens) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-mouse-options-player-movement) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* mouse-movement?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* mouse-movement?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-confirm-option + :name (text-id progress-restore-defaults) + :on-confirm (lambda ((val symbol)) + (reset-input *pc-settings* 'mouse #t) + (update-mouse-controls! *pc-settings*) + (commit-to-file *pc-settings*)))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-input-options-auto-hide-cursor) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* auto-hide-cursor?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* auto-hide-cursor?) val) + (update-mouse-controls! *pc-settings*) + (commit-to-file *pc-settings*))) + ;; TODO - there is a bug where if you restore default binds and that changes your `X` bind, + ;; the next X input is ignored, figure this out eventually / make an issue for it. + (progress-new-generic-link-to-scrolling-page (text-id progress-menu-reassign-binds) + (progress-new-generic-link-to-details-page (text-id progress-reassign-binds-controller) :should-disable? (lambda () (<= (pc-get-controller-count) 0)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind select) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l3) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r3) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind start) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-up) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-right) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-down) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-left) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l2) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r2) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l1) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r1) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind triangle) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind circle) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind cross) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind square) :device-type (input-device-type controller)) + (new 'static 'menu-generic-details-confirm-entry + :name (text-id progress-restore-defaults) + :on-confirm (lambda () (pc-reset-bindings-to-defaults! 0 0)))) + (progress-new-generic-link-to-details-page (text-id progress-reassign-binds-keyboard) :should-disable? (lambda () (not (-> *pc-settings* keyboard-enabled?))) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l-analog-up) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l-analog-down) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l-analog-left) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l-analog-right) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r-analog-up) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r-analog-down) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r-analog-left) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r-analog-right) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind select) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l3) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r3) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind start) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-up) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-right) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-down) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-left) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l2) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r2) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l1) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r1) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind triangle) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind circle) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind cross) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind square) :device-type (input-device-type keyboard)) + (new 'static 'menu-generic-details-confirm-entry + :name (text-id progress-restore-defaults) + :on-confirm (lambda () (pc-reset-bindings-to-defaults! 0 1)))) + (progress-new-generic-link-to-details-page (text-id progress-reassign-binds-mouse) :should-disable? (lambda () (not (-> *pc-settings* mouse-enabled?))) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind select) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l3) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r3) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind start) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-up) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-right) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-down) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind dpad-left) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l2) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r2) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind l1) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind r1) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind triangle) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind circle) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind cross) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-keybind-entry :keybind (controller-keybind square) :device-type (input-device-type mouse)) + (new 'static 'menu-generic-details-confirm-entry + :name (text-id progress-restore-defaults) + :on-confirm (lambda () (pc-reset-bindings-to-defaults! 0 2))))) + (new 'static 'menu-generic-confirm-option + :name (text-id progress-restore-defaults) + :on-confirm (lambda ((val symbol)) + (reset-input *pc-settings* 'input #t) + (set-enable-keyboard! *pc-settings* (-> *pc-settings* keyboard-enabled?)) + (update-mouse-controls! *pc-settings*) + (commit-to-file *pc-settings*)))) (new 'static 'menu-generic-boolean-option :name (text-id progress-subtitles) :truthy-text (text-id progress-on) @@ -55,18 +294,40 @@ ;; NOTE - this doesn't actually work (naughty dog tried it too in their progress code) ;; fix it eventually (load-level-text-files (the-as int (-> *setting-control* user-default language))))) - (progress-new-generic-link (text-id progress-misc-game-options) - (progress-new-generic-scrolling-page (text-id progress-misc-game-options) - (new 'static 'menu-generic-boolean-option - :name (text-id progress-speedrunner-mode) - :truthy-text (text-id progress-on) - :falsey-text (text-id progress-off) - :get-value-fn (lambda () (-> *pc-settings* speedrunner-mode?)) - :on-confirm (lambda ((val symbol)) - (set! (-> *pc-settings* speedrunner-mode?) val) - (commit-to-file *pc-settings*))))))) + (progress-new-generic-link-to-scrolling-page (text-id progress-misc-game-options) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-discord-rpc) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* discord-rpc?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* discord-rpc?) val) + (commit-to-file *pc-settings*))) + (new 'static 'menu-generic-boolean-option + :name (text-id progress-speedrunner-mode) + :truthy-text (text-id progress-on) + :falsey-text (text-id progress-off) + :get-value-fn (lambda () (-> *pc-settings* speedrunner-mode?)) + :on-confirm (lambda ((val symbol)) + (set! (-> *pc-settings* speedrunner-mode?) val) + (commit-to-file *pc-settings*)))))) +;; TODO - migrate this menu as well +;; graphic options +;; resolution +;; display mode +;; display select (disable if windowed) +;; vsync +;; aspect ratio +;; msaa +;; frame rate (dont go beyond refresh rate) (disable if SRMode) +;; ps2 options +;; lod bg +;; lod fg +;; particle culling +;; force env mapping +;; actor culling (define *graphic-options-pc* (new 'static 'menu-option-list :y-center 198