diff --git a/.gitmodules b/.gitmodules
index 3af4d02..d0454b4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,15 +1,6 @@
[submodule "lib/N64ModernRuntime"]
path = lib/N64ModernRuntime
url = https://github.com/N64Recomp/N64ModernRuntime
-[submodule "lib/RmlUi"]
- path = lib/RmlUi
- url = https://github.com/mikke89/RmlUi
-[submodule "lib/freetype-windows-binaries"]
- path = lib/freetype-windows-binaries
- url = https://github.com/ubawurinna/freetype-windows-binaries/
-[submodule "lib/lunasvg"]
- path = lib/lunasvg
- url = https://github.com/sammycage/lunasvg
[submodule "lib/rt64"]
path = lib/rt64
url = https://github.com/rt64/rt64
@@ -19,3 +10,6 @@
[submodule "BanjoRecompSyms"]
path = BanjoRecompSyms
url = https://github.com/BanjoRecomp/BanjoRecompSyms
+[submodule "lib/RecompFrontend"]
+ path = lib/RecompFrontend
+ url = https://github.com/N64Recomp/RecompFrontend
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9fde522..21a1efa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,15 +51,7 @@ endif()
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/rt64 ${CMAKE_BINARY_DIR}/rt64)
-# set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
set(BUILD_SHARED_LIBS OFF)
-SET(LUNASVG_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
-add_subdirectory(${CMAKE_SOURCE_DIR}/lib/lunasvg)
-# set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
-SET(RMLUI_SVG_PLUGIN ON CACHE BOOL "" FORCE)
-SET(RMLUI_TESTS_ENABLED OFF CACHE BOOL "" FORCE)
-add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RmlUi)
-target_compile_definitions(rmlui_core PRIVATE LUNASVG_BUILD_STATIC)
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime)
@@ -149,14 +141,10 @@ add_executable(BanjoRecompiled)
set (SOURCES
${CMAKE_SOURCE_DIR}/src/main/main.cpp
- ${CMAKE_SOURCE_DIR}/src/main/support.cpp
${CMAKE_SOURCE_DIR}/src/main/register_overlays.cpp
${CMAKE_SOURCE_DIR}/src/main/register_patches.cpp
- ${CMAKE_SOURCE_DIR}/src/main/rt64_render_context.cpp
${CMAKE_SOURCE_DIR}/src/main/theme.cpp
- ${CMAKE_SOURCE_DIR}/src/game/input.cpp
- ${CMAKE_SOURCE_DIR}/src/game/controls.cpp
${CMAKE_SOURCE_DIR}/src/game/config.cpp
${CMAKE_SOURCE_DIR}/src/game/debug.cpp
${CMAKE_SOURCE_DIR}/src/game/recomp_api.cpp
@@ -164,61 +152,22 @@ set (SOURCES
${CMAKE_SOURCE_DIR}/src/game/recomp_data_api.cpp
${CMAKE_SOURCE_DIR}/src/game/rom_decompression.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_renderer.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_state.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_launcher.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_config.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_prompt.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_config_sub_menu.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_color_hack.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_rml_hacks.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_elements.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_mod_details_panel.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_mod_installer.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_mod_menu.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_api.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_api_events.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_api_images.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/ui_utils.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/util/hsv.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/core/ui_context.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_button.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_clickable.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_container.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_element.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_image.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_label.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_radio.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_scroll_container.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_slider.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_span.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_style.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_text_input.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_theme.cpp
- ${CMAKE_SOURCE_DIR}/src/ui/elements/ui_toggle.cpp
-
${CMAKE_SOURCE_DIR}/rsp/n_aspMain.cpp
-
- ${CMAKE_SOURCE_DIR}/lib/RmlUi/Backends/RmlUi_Platform_SDL.cpp
)
-if (APPLE)
- list(APPEND SOURCES ${CMAKE_SOURCE_DIR}/src/main/support_apple.mm)
-endif()
-
target_include_directories(BanjoRecompiled PRIVATE
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime/N64Recomp/include
${CMAKE_SOURCE_DIR}/lib/concurrentqueue
- ${CMAKE_SOURCE_DIR}/lib/GamepadMotionHelpers
- ${CMAKE_SOURCE_DIR}/lib/RmlUi/Include
- ${CMAKE_SOURCE_DIR}/lib/RmlUi/Backends
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/hlslpp/include
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/dxc/inc
${CMAKE_SOURCE_DIR}/lib/rt64/src
${CMAKE_SOURCE_DIR}/lib/rt64/src/rhi
${CMAKE_SOURCE_DIR}/lib/rt64/src/render
+ ${CMAKE_SOURCE_DIR}/lib/RecompFrontend/recompinput/include
+ ${CMAKE_SOURCE_DIR}/lib/RecompFrontend/recompui/include
+ ${CMAKE_SOURCE_DIR}/lib/RecompFrontend/recompui/src
${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include
${CMAKE_SOURCE_DIR}/lib/SlotMap
@@ -285,7 +234,7 @@ if (WIN32)
PROPERTIES
LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE"
LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
- LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
+ LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE" # "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
)
@@ -349,16 +298,20 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
target_link_libraries(BanjoRecompiled PRIVATE "-latomic -static-libstdc++" ${CMAKE_DL_LIBS} Threads::Threads)
endif()
+set(RECOMP_FRONTEND_N64MODERNRUNTIME_PATH ${CMAKE_SOURCE_DIR}/lib/N64ModernRuntime)
+set(RECOMP_FRONTEND_RT64_PATH ${CMAKE_SOURCE_DIR}/lib/rt64)
+
+add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RecompFrontend)
+
target_link_libraries(BanjoRecompiled PRIVATE
PatchesLib
RecompiledFuncs
+ recompui
+ recompinput
librecomp
ultramodern
rt64
- RmlUi::Core
- RmlUi::Debugger
nfd
- lunasvg
)
# TODO fix the rt64 CMake script so that this doesn't need to be duplicated here
diff --git a/assets/LatoLatin-Bold.ttf b/assets/LatoLatin-Bold.ttf
new file mode 100644
index 0000000..c598c24
Binary files /dev/null and b/assets/LatoLatin-Bold.ttf differ
diff --git a/assets/LatoLatin-BoldItalic.ttf b/assets/LatoLatin-BoldItalic.ttf
new file mode 100644
index 0000000..c1f225a
Binary files /dev/null and b/assets/LatoLatin-BoldItalic.ttf differ
diff --git a/assets/LatoLatin-Italic.ttf b/assets/LatoLatin-Italic.ttf
new file mode 100644
index 0000000..c61fc07
Binary files /dev/null and b/assets/LatoLatin-Italic.ttf differ
diff --git a/assets/LatoLatin-Regular.ttf b/assets/LatoLatin-Regular.ttf
new file mode 100644
index 0000000..bcc5778
Binary files /dev/null and b/assets/LatoLatin-Regular.ttf differ
diff --git a/assets/banjkazoobg.svg b/assets/banjkazoobg.svg
new file mode 100644
index 0000000..1fffad2
--- /dev/null
+++ b/assets/banjkazoobg.svg
@@ -0,0 +1,37 @@
+
diff --git a/assets/config_menu.rml b/assets/config_menu.rml
deleted file mode 100644
index 8d582dc..0000000
--- a/assets/config_menu.rml
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
- Inventory
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- General
-
-
-
-
-
-
- Controls
-
-
-
-
-
-
- Graphics
-
-
-
-
-
-
- Sound
-
-
-
-
-
-
- Mods
-
-
-
-
-
-
- Debug
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/config_menu/controls.rml b/assets/config_menu/controls.rml
deleted file mode 100644
index 3a8371e..0000000
--- a/assets/config_menu/controls.rml
+++ /dev/null
@@ -1,360 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/config_menu/debug.rml b/assets/config_menu/debug.rml
deleted file mode 100644
index 22a04e2..0000000
--- a/assets/config_menu/debug.rml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/config_menu/general.rml b/assets/config_menu/general.rml
deleted file mode 100644
index 86a539d..0000000
--- a/assets/config_menu/general.rml
+++ /dev/null
@@ -1,330 +0,0 @@
-
-
-
-
-
-
-
diff --git a/assets/config_menu/graphics.rml b/assets/config_menu/graphics.rml
deleted file mode 100644
index a11de72..0000000
--- a/assets/config_menu/graphics.rml
+++ /dev/null
@@ -1,325 +0,0 @@
-
-
-
-
-
-
-
diff --git a/assets/config_menu/mods.rml b/assets/config_menu/mods.rml
deleted file mode 100644
index debab39..0000000
--- a/assets/config_menu/mods.rml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
diff --git a/assets/config_menu/sound.rml b/assets/config_menu/sound.rml
deleted file mode 100644
index c176f9f..0000000
--- a/assets/config_menu/sound.rml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/config_sub_menu.rml b/assets/config_sub_menu.rml
deleted file mode 100644
index 0022f1e..0000000
--- a/assets/config_sub_menu.rml
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
- Inventory
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/icons/Caret.svg b/assets/icons/Caret.svg
new file mode 100644
index 0000000..9266f13
--- /dev/null
+++ b/assets/icons/Caret.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/Cont.svg b/assets/icons/Cont.svg
new file mode 100644
index 0000000..5959613
--- /dev/null
+++ b/assets/icons/Cont.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/Keyboard.svg b/assets/icons/Keyboard.svg
new file mode 100644
index 0000000..880ceb0
--- /dev/null
+++ b/assets/icons/Keyboard.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/PlusKeyboard.svg b/assets/icons/PlusKeyboard.svg
new file mode 100644
index 0000000..158c6a0
--- /dev/null
+++ b/assets/icons/PlusKeyboard.svg
@@ -0,0 +1,17 @@
+
diff --git a/assets/icons/Port.svg b/assets/icons/Port.svg
new file mode 100644
index 0000000..224a4d8
--- /dev/null
+++ b/assets/icons/Port.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/Question.svg b/assets/icons/Question.svg
new file mode 100644
index 0000000..9fdcaf3
--- /dev/null
+++ b/assets/icons/Question.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/RecordSpinner.svg b/assets/icons/RecordSpinner.svg
new file mode 100644
index 0000000..fb9accd
--- /dev/null
+++ b/assets/icons/RecordSpinner.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/launcher.rml b/assets/launcher.rml
deleted file mode 100644
index 08c87ee..0000000
--- a/assets/launcher.rml
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
- Launcher
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/promptfont/promptfont.css b/assets/promptfont/promptfont.css
deleted file mode 100644
index 1567cd6..0000000
--- a/assets/promptfont/promptfont.css
+++ /dev/null
@@ -1,335 +0,0 @@
-@font-face{font-family:'promptfont'; src:url('promptfont.ttf');}
-.pf{font-family:promptfont;}
-.pf-exchange::after{content:'\u2194';}
-.pf-reverse::after{content:'\u2195';}
-.pf-left-trigger-lt::after{content:'\u2196';}
-.pf-right-trigger-rt::after{content:'\u2197';}
-.pf-left-shoulder-lb::after{content:'\u2198';}
-.pf-right-shoulder-rb::after{content:'\u2199';}
-.pf-left-trigger-zl::after{content:'\u219A';}
-.pf-right-trigger-zr::after{content:'\u219B';}
-.pf-left-shoulder-l::after{content:'\u219C';}
-.pf-right-shoulder-r::after{content:'\u219D';}
-.pf-dpad-left::after{content:'\u219E';}
-.pf-dpad-up::after{content:'\u219F';}
-.pf-dpad-right::after{content:'\u21A0';}
-.pf-dpad-down::after{content:'\u21A1';}
-.pf-dpad-left-right::after{content:'\u21A2';}
-.pf-dpad-up-down::after{content:'\u21A3';}
-.pf-button-left-x::after{content:'\u21A4';}
-.pf-button-up-y::after{content:'\u21A5';}
-.pf-button-right-b::after{content:'\u21A6';}
-.pf-button-down-a::after{content:'\u21A7';}
-.pf-left-analog-clockwise::after{content:'\u21A9';}
-.pf-left-analog-counter::after{content:'\u21AA';}
-.pf-right-analog-clockwise::after{content:'\u21AB';}
-.pf-right-analog-counter::after{content:'\u21AC';}
-.pf-both-analog-clockwise::after{content:'\u21AD';}
-.pf-both-analog-counter::after{content:'\u21AE';}
-.pf-left-shoulder-l1::after{content:'\u21B0';}
-.pf-right-shoulder-r1::after{content:'\u21B1';}
-.pf-left-trigger-l2::after{content:'\u21B2';}
-.pf-right-trigger-r2::after{content:'\u21B3';}
-.pf-dpad-left-down::after{content:'\u21B4';}
-.pf-dpad-up-right::after{content:'\u21B5';}
-.pf-analog-clockwise::after{content:'\u21B6';}
-.pf-analog-counter::after{content:'\u21B7';}
-.pf-both-analog-click::after{content:'\u21B9';}
-.pf-left-analog-click::after{content:'\u21BA';}
-.pf-right-analog-click::after{content:'\u21BB';}
-.pf-left-analog-left::after{content:'\u21BC';}
-.pf-right-analog-left::after{content:'\u21BD';}
-.pf-left-analog-up::after{content:'\u21BE';}
-.pf-right-analog-up::after{content:'\u21BF';}
-.pf-left-analog-right::after{content:'\u21C0';}
-.pf-right-analog-right::after{content:'\u21C1';}
-.pf-left-analog-down::after{content:'\u21C2';}
-.pf-right-analog-down::after{content:'\u21C3';}
-.pf-left-analog-left-right::after{content:'\u21C4';}
-.pf-left-analog-up-down::after{content:'\u21C5';}
-.pf-right-analog-left-right::after{content:'\u21C6';}
-.pf-analog-left::after{content:'\u21C7';}
-.pf-analog-up::after{content:'\u21C8';}
-.pf-analog-right::after{content:'\u21C9';}
-.pf-analog-down::after{content:'\u21CA';}
-.pf-left-analog::after{content:'\u21CB';}
-.pf-right-analog::after{content:'\u21CC';}
-.pf-dpad::after{content:'\u21CE';}
-.pf-button-x::after{content:'\u21D0';}
-.pf-button-y::after{content:'\u21D1';}
-.pf-button-b::after{content:'\u21D2';}
-.pf-button-a::after{content:'\u21D3';}
-.pf-analog-left-right::after{content:'\u21D4';}
-.pf-analog-up-down::after{content:'\u21D5';}
-.pf-analog-up-left::after{content:'\u21D6';}
-.pf-analog-up-right::after{content:'\u21D7';}
-.pf-analog-down-right::after{content:'\u21D8';}
-.pf-analog-down-left::after{content:'\u21D9';}
-.pf-left-analog-touch::after{content:'\u21DA';}
-.pf-right-analog-touch::after{content:'\u21DB';}
-.pf-left-trigger-pull::after{content:'\u21DC';}
-.pf-right-trigger-pull::after{content:'\u21DD';}
-.pf-dpad-right-down::after{content:'\u21DE';}
-.pf-dpad-left-up::after{content:'\u21DF';}
-.pf-button-square::after{content:'\u21E0';}
-.pf-button-triangle::after{content:'\u21E1';}
-.pf-button-circle::after{content:'\u21E2';}
-.pf-button-cross::after{content:'\u21E3';}
-.pf-steam-menu::after{content:'\u21E4';}
-.pf-options-menu::after{content:'\u21E5';}
-.pf-dualshock-share::after{content:'\u21E6';}
-.pf-dualshock-touchpad::after{content:'\u21E7';}
-.pf-dualshock-options::after{content:'\u21E8';}
-.pf-gamecube-z::after{content:'\u21E9';}
-.pf-back-trigger-z::after{content:'\u21EA';}
-.pf-button-c::after{content:'\u21EB';}
-.pf-button-z::after{content:'\u21EC';}
-.pf-button-alt-1::after{content:'\u21ED';}
-.pf-button-alt-2::after{content:'\u21EE';}
-.pf-left-analog-any::after{content:'\u21F1';}
-.pf-right-analog-any::after{content:'\u21F2';}
-.pf-analog-any::after{content:'\u21F3';}
-.pf-right-analog-up-down::after{content:'\u21F5';}
-.pf-select-share::after{content:'\u21F7';}
-.pf-start::after{content:'\u21F8';}
-.pf-home-menu::after{content:'\u21F9';}
-.pf-share-capture::after{content:'\u21FA';}
-.pf-burger-menu::after{content:'\u21FB';}
-.pf-minus::after{content:'\u21FD';}
-.pf-plus::after{content:'\u21FE';}
-.pf-joycon-dpad-left::after{content:'\u21FF';}
-.pf-joycon-dpad-up::after{content:'\u2200';}
-.pf-joycon-dpad-right::after{content:'\u2201';}
-.pf-joycon-dpad-down::after{content:'\u2202';}
-.pf-joycon-sl::after{content:'\u2203';}
-.pf-joycon-sr::after{content:'\u2204';}
-.pf-lenovo-legion-quick-settings::after{content:'\u2205';}
-.pf-dualsense-share::after{content:'\u2206';}
-.pf-dualsense-touchpad::after{content:'\u2207';}
-.pf-dualsense-options::after{content:'\u2208';}
-.pf-ayaneo-lc::after{content:'\u2209';}
-.pf-ayaneo-rc::after{content:'\u220A';}
-.pf-ayaneo-wave::after{content:'\u220B';}
-.pf-ayn-home::after{content:'\u220C';}
-.pf-ayn-lcc::after{content:'\u220D';}
-.pf-gpd-c1::after{content:'\u220E';}
-.pf-gpd-c2::after{content:'\u220F';}
-.pf-onexplayer-keyboard::after{content:'\u2210';}
-.pf-onexplayer-turbo::after{content:'\u2211';}
-.pf-m1::after{content:'\u2212';}
-.pf-m2::after{content:'\u2213';}
-.pf-m3::after{content:'\u2214';}
-.pf-y1::after{content:'\u2215';}
-.pf-y2::after{content:'\u2216';}
-.pf-y3::after{content:'\u2217';}
-.pf-onexplayer-function::after{content:'\u2218';}
-.pf-onexplayer-home::after{content:'\u2219';}
-.pf-left-trackpad-any::after{content:'\u2264';}
-.pf-right-trackpad-any::after{content:'\u2265';}
-.pf-left-trackpad-click::after{content:'\u2266';}
-.pf-right-trackpad-click::after{content:'\u2267';}
-.pf-left-trackpad-touch::after{content:'\u2268';}
-.pf-right-trackpad-touch::after{content:'\u2269';}
-.pf-left-trackpad-left::after{content:'\u226E';}
-.pf-right-trackpad-left::after{content:'\u226F';}
-.pf-left-trackpad-up::after{content:'\u2270';}
-.pf-right-trackpad-up::after{content:'\u2271';}
-.pf-left-trackpad-right::after{content:'\u2272';}
-.pf-right-trackpad-right::after{content:'\u2273';}
-.pf-left-trackpad-down::after{content:'\u2274';}
-.pf-right-trackpad-down::after{content:'\u2275';}
-.pf-steamdeck-l4::after{content:'\u2276';}
-.pf-steamdeck-r4::after{content:'\u2277';}
-.pf-steamdeck-l5::after{content:'\u2278';}
-.pf-steamdeck-r5::after{content:'\u2279';}
-.pf-xbox-dpad-left::after{content:'\u227A';}
-.pf-xbox-dpad-up::after{content:'\u227B';}
-.pf-xbox-dpad-right::after{content:'\u227C';}
-.pf-xbox-dpad-down::after{content:'\u227D';}
-.pf-xbox-dpad-left-right::after{content:'\u227E';}
-.pf-xbox-dpad-up-down::after{content:'\u227F';}
-.pf-xbox-dpad-left-up::after{content:'\u2280';}
-.pf-xbox-dpad-right-up::after{content:'\u2281';}
-.pf-xbox-dpad-left-down::after{content:'\u2282';}
-.pf-xbox-dpad-right-down::after{content:'\u2283';}
-.pf-xbox-dpad::after{content:'\u2284';}
-.pf-pin::after{content:'\u2316';}
-.pf-tabs::after{content:'\u23CD';}
-.pf-back::after{content:'\u23CE';}
-.pf-home-screen::after{content:'\u23CF';}
-.pf-horizontal-dots::after{content:'\u23D0';}
-.pf-vertical-dots::after{content:'\u23D1';}
-.pf-hamburger-menu::after{content:'\u23D2';}
-.pf-arrow-left::after{content:'\u23F4';}
-.pf-arrow-up::after{content:'\u23F5';}
-.pf-arrow-right::after{content:'\u23F6';}
-.pf-arrow-down::after{content:'\u23F7';}
-.pf-wasd::after{content:'\u2423';}
-.pf-arrow-keys::after{content:'\u2424';}
-.pf-ijkl::after{content:'\u2425';}
-.pf-fn::after{content:'\u2426';}
-.pf-ctrl::after{content:'\u2427';}
-.pf-alt::after{content:'\u2428';}
-.pf-shift::after{content:'\u2429';}
-.pf-super::after{content:'\u242A';}
-.pf-tab::after{content:'\u242B';}
-.pf-caps::after{content:'\u242C';}
-.pf-backspace::after{content:'\u242D';}
-.pf-enter::after{content:'\u242E';}
-.pf-esc::after{content:'\u242F';}
-.pf-prtsc::after{content:'\u2430';}
-.pf-scrlk::after{content:'\u2431';}
-.pf-pause::after{content:'\u2432';}
-.pf-numlock::after{content:'\u2433';}
-.pf-insert::after{content:'\u2434';}
-.pf-home::after{content:'\u2435';}
-.pf-page-up::after{content:'\u2436';}
-.pf-delete::after{content:'\u2437';}
-.pf-end::after{content:'\u2438';}
-.pf-page-down::after{content:'\u2439';}
-.pf-space::after{content:'\u243A';}
-.pf-gamepad::after{content:'\u243C';}
-.pf-keyboard::after{content:'\u243D';}
-.pf-mouse::after{content:'\u243E';}
-.pf-mouse-and-keyboard::after{content:'\u243F';}
-.pf-f1::after{content:'\u2460';}
-.pf-f2::after{content:'\u2461';}
-.pf-f3::after{content:'\u2462';}
-.pf-f4::after{content:'\u2463';}
-.pf-f5::after{content:'\u2464';}
-.pf-f6::after{content:'\u2465';}
-.pf-f7::after{content:'\u2466';}
-.pf-f8::after{content:'\u2467';}
-.pf-f9::after{content:'\u2468';}
-.pf-f10::after{content:'\u2469';}
-.pf-f11::after{content:'\u246A';}
-.pf-f12::after{content:'\u246B';}
-.pf-empty-keycap::after{content:'\u248F';}
-.pf-1::after{content:'\u24F5';}
-.pf-2::after{content:'\u24F6';}
-.pf-3::after{content:'\u24F7';}
-.pf-4::after{content:'\u24F8';}
-.pf-5::after{content:'\u24F9';}
-.pf-6::after{content:'\u24FA';}
-.pf-7::after{content:'\u24FB';}
-.pf-8::after{content:'\u24FC';}
-.pf-9::after{content:'\u24FD';}
-.pf-0::after{content:'\u24FF';}
-.pf-star::after{content:'\u2605';}
-.pf-skull::after{content:'\u2620';}
-.pf-frown::after{content:'\u2639';}
-.pf-smile::after{content:'\u263A';}
-.pf-empty-heart::after{content:'\u2661';}
-.pf-heart::after{content:'\u2665';}
-.pf-d4::after{content:'\u2673';}
-.pf-d6::after{content:'\u2674';}
-.pf-d8::after{content:'\u2675';}
-.pf-d10::after{content:'\u2676';}
-.pf-d12::after{content:'\u2677';}
-.pf-d20::after{content:'\u2678';}
-.pf-d6-1::after{content:'\u2680';}
-.pf-d6-2::after{content:'\u2681';}
-.pf-d6-3::after{content:'\u2682';}
-.pf-d6-4::after{content:'\u2683';}
-.pf-d6-5::after{content:'\u2684';}
-.pf-d6-6::after{content:'\u2685';}
-.pf-flag::after{content:'\u2691';}
-.pf-gears-options-settings::after{content:'\u2699';}
-.pf-cross::after{content:'\u2717';}
-.pf-question::after{content:'\u2753';}
-.pf-exclamation::after{content:'\u2757';}
-.pf-mouse-button-1::after{content:'\u278A';}
-.pf-mouse-button-2::after{content:'\u278B';}
-.pf-mouse-button-3::after{content:'\u278C';}
-.pf-mouse-button-4::after{content:'\u278D';}
-.pf-mouse-button-5::after{content:'\u278E';}
-.pf-mouse-button-6::after{content:'\u278F';}
-.pf-mouse-button-7::after{content:'\u2790';}
-.pf-mouse-button-8::after{content:'\u2791';}
-.pf-scroll-up::after{content:'\u27F0';}
-.pf-scroll-down::after{content:'\u27F1';}
-.pf-left-click::after{content:'\u27F5';}
-.pf-right-click::after{content:'\u27F6';}
-.pf-middle-click::after{content:'\u27F7';}
-.pf-mouse-left-right::after{content:'\u27FA';}
-.pf-mouse-up-down::after{content:'\u27FB';}
-.pf-mouse-any::after{content:'\u27FC';}
-.pf-box-crate::after{content:'\u2B1B';}
-.pf-playstation::after{content:'\uE000';}
-.pf-xbox::after{content:'\uE001';}
-.pf-nintendo-switch::after{content:'\uE002';}
-.pf-ayaneo::after{content:'\uE003';}
-.pf-lenovo-legion::after{content:'\uE004';}
-.pf-rog-ally-armoury::after{content:'\uE005';}
-.pf-rog-alloy-command::after{content:'\uE006';}
-.pf-apple-mac::after{content:'\uE007';}
-.pf-windows::after{content:'\uE008';}
-.pf-linux::after{content:'\uE009';}
-.pf-bsd::after{content:'\uE00A';}
-.pf-key-0::after{content:'\uFF10';}
-.pf-key-1::after{content:'\uFF11';}
-.pf-key-2::after{content:'\uFF12';}
-.pf-key-3::after{content:'\uFF13';}
-.pf-key-4::after{content:'\uFF14';}
-.pf-key-5::after{content:'\uFF15';}
-.pf-key-6::after{content:'\uFF16';}
-.pf-key-7::after{content:'\uFF17';}
-.pf-key-8::after{content:'\uFF18';}
-.pf-key-9::after{content:'\uFF19';}
-.pf-key-a::after{content:'\uFF21';}
-.pf-key-b::after{content:'\uFF22';}
-.pf-key-c::after{content:'\uFF23';}
-.pf-key-d::after{content:'\uFF24';}
-.pf-key-e::after{content:'\uFF25';}
-.pf-key-f::after{content:'\uFF26';}
-.pf-key-g::after{content:'\uFF27';}
-.pf-key-h::after{content:'\uFF28';}
-.pf-key-i::after{content:'\uFF29';}
-.pf-key-j::after{content:'\uFF2A';}
-.pf-key-k::after{content:'\uFF2B';}
-.pf-key-l::after{content:'\uFF2C';}
-.pf-key-m::after{content:'\uFF2D';}
-.pf-key-n::after{content:'\uFF2E';}
-.pf-key-o::after{content:'\uFF2F';}
-.pf-key-p::after{content:'\uFF30';}
-.pf-key-q::after{content:'\uFF31';}
-.pf-key-r::after{content:'\uFF32';}
-.pf-key-s::after{content:'\uFF33';}
-.pf-key-t::after{content:'\uFF34';}
-.pf-key-u::after{content:'\uFF35';}
-.pf-key-v::after{content:'\uFF36';}
-.pf-key-w::after{content:'\uFF37';}
-.pf-key-x::after{content:'\uFF38';}
-.pf-key-y::after{content:'\uFF39';}
-.pf-key-z::after{content:'\uFF3A';}
-.pf-headphones::after{content:'\u1F3A7';}
-.pf-music::after{content:'\u1F3B6';}
-.pf-fish::after{content:'\u1F41F';}
-.pf-dance-pad::after{content:'\u1F483';}
-.pf-laptop::after{content:'\u1F4BB';}
-.pf-diskette::after{content:'\u1F4BE';}
-.pf-write::after{content:'\u1F4DD';}
-.pf-phone::after{content:'\u1F4F1';}
-.pf-camera::after{content:'\u1F4F7';}
-.pf-speaker::after{content:'\u1F508';}
-.pf-light-gun::after{content:'\u1F52B';}
-.pf-sfx-sound-effect-noise::after{content:'\u1F56C';}
-.pf-steering-wheel::after{content:'\u1F578';}
-.pf-fight-stick-joystick::after{content:'\u1F579';}
-.pf-vr-headset::after{content:'\u1F57B';}
-.pf-vr-controller::after{content:'\u1F57C';}
-.pf-flight-stick::after{content:'\u1F57D';}
-.pf-cpu-processor::after{content:'\u1F5A5';}
-.pf-web-internet-link::after{content:'\u1F5A7';}
-.pf-gpu-graphics-card::after{content:'\u1F5A8';}
-.pf-ram-memory::after{content:'\u1F5AA';}
-.pf-usb-stick::after{content:'\u1F5AB';}
-.pf-database::after{content:'\u1F5AC';}
-.pf-hard-disk-drive::after{content:'\u1F5B4';}
-.pf-screen-video::after{content:'\u1F5B5';}
-.pf-text-entry-edit::after{content:'\u1F5B9';}
-.pf-speaking-voice::after{content:'\u1F5E3';}
-.pf-language::after{content:'\u1F5E9';}
-.pf-exit-quit-leave::after{content:'\u1F6AA';}
-.pf-information::after{content:'\u1F6C8';}
-.pf-shopping-cart::after{content:'\u1F6D2';}
diff --git a/assets/recomp.rcss b/assets/recomp.rcss
index 488f346..a6daef7 100644
--- a/assets/recomp.rcss
+++ b/assets/recomp.rcss
@@ -1,2511 +1,6 @@
-/* stylelint-disable color-no-hex, color-hex-length */
-h1 {
- font-size: 68dp;
- letter-spacing: 4.76dp;
- line-height: 68dp;
- font-style: normal;
- font-weight: 700;
-}
-
-h2 {
- font-size: 52dp;
- letter-spacing: 3.64dp;
- line-height: 52dp;
- font-style: normal;
- font-weight: 700;
-}
-
-h3, .tab {
- font-size: 36dp;
- letter-spacing: 2.52dp;
- line-height: 36dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-lg, .menu-list-item__label, .button--large {
- font-size: 36dp;
- letter-spacing: 3.96dp;
- line-height: 36dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-md, .config-debug-option__label, .button, .config-option__title, .config-option--hz .config-option__title, .config-group__title, .control-option__label {
- font-size: 28dp;
- letter-spacing: 3.08dp;
- line-height: 28dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-sm, .config-debug__select-wrapper .config-debug__select-label, .subtitle-title__disclaimer, .config-option__range-label, .config-option-range__label, .config-option__radio-tabs .config-option__tab-label,
-.config-option__list .config-option__tab-label, .centered-page__controls > label {
- font-size: 20dp;
- letter-spacing: 2.8dp;
- line-height: 20dp;
- font-style: normal;
- font-weight: 700;
- text-transform: uppercase;
-}
-
-.config-option__details {
- font-size: 18dp;
- letter-spacing: 2.52dp;
- line-height: 18dp;
- font-style: normal;
- font-weight: 400;
-}
-
-.config-debug__select-wrapper select, .config-debug__select-wrapper input, .config-description__contents, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config__wrapper p, body {
- font-size: 20dp;
- letter-spacing: 0dp;
- line-height: 20dp;
- font-style: normal;
- font-weight: 400;
-}
-
-.toggle__icon {
- font-family: promptfont;
- font-size: 56dp;
- font-style: normal;
- font-weight: 400;
- line-height: 56dp;
-}
-
-.prompt-font {
- font-family: promptfont;
- font-size: 40dp;
- font-style: normal;
- font-weight: 400;
- line-height: 40dp;
-}
-
-.prompt-font-sm, .input-viz__mappings div {
- font-family: promptfont;
- font-size: 32dp;
- font-style: normal;
- font-weight: 400;
- line-height: 32dp;
-}
/*
-@include trans-colors;
+ In order for rml to parse the base style sheet and combine with this one, any style needs to at least be present.
+ If you add styles to this file later, you can clear the current contents of this file.
*/
-/*
-@include trans-colors-opa;
-*/
-/*
-@include trans-colors-svg;
-*/
-/*
-@include trans-colors-border;
-*/
-.nav-vert, .nav-dir, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- nav-up: auto;
- nav-down: auto;
-}
-
-.nav-horiz, .nav-dir, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- nav-right: auto;
- nav-left: auto;
-}
-
-.nav-foc, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- focus: auto;
- tab-index: auto;
-}
-
-/*
-@include set-color(COLOR);
-*/
-/* stylelint-disable color-no-hex, color-hex-length */
-h1 {
- font-size: 68dp;
- letter-spacing: 4.76dp;
- line-height: 68dp;
- font-style: normal;
- font-weight: 700;
-}
-
-h2 {
- font-size: 52dp;
- letter-spacing: 3.64dp;
- line-height: 52dp;
- font-style: normal;
- font-weight: 700;
-}
-
-h3, .tab {
- font-size: 36dp;
- letter-spacing: 2.52dp;
- line-height: 36dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-lg, .menu-list-item__label, .button--large {
- font-size: 36dp;
- letter-spacing: 3.96dp;
- line-height: 36dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-md, .config-debug-option__label, .button, .config-option__title, .config-option--hz .config-option__title, .config-group__title, .control-option__label {
- font-size: 28dp;
- letter-spacing: 3.08dp;
- line-height: 28dp;
- font-style: normal;
- font-weight: 700;
-}
-
-.label-sm, .config-debug__select-wrapper .config-debug__select-label, .subtitle-title__disclaimer, .config-option__range-label, .config-option-range__label, .config-option__radio-tabs .config-option__tab-label,
-.config-option__list .config-option__tab-label, .centered-page__controls > label {
- font-size: 20dp;
- letter-spacing: 2.8dp;
- line-height: 20dp;
- font-style: normal;
- font-weight: 700;
- text-transform: uppercase;
-}
-
-.config-option__details {
- font-size: 18dp;
- letter-spacing: 2.52dp;
- line-height: 18dp;
- font-style: normal;
- font-weight: 400;
-}
-
-.config-debug__select-wrapper select, .config-debug__select-wrapper input, .config-description__contents, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config__wrapper p, body {
- font-size: 20dp;
- letter-spacing: 0dp;
- line-height: 20dp;
- font-style: normal;
- font-weight: 400;
-}
-
-.toggle__icon {
- font-family: promptfont;
- font-size: 56dp;
- font-style: normal;
- font-weight: 400;
- line-height: 56dp;
-}
-
-.prompt-font {
- font-family: promptfont;
- font-size: 40dp;
- font-style: normal;
- font-weight: 400;
- line-height: 40dp;
-}
-
-.prompt-font-sm, .input-viz__mappings div {
- font-family: promptfont;
- font-size: 32dp;
- font-style: normal;
- font-weight: 400;
- line-height: 32dp;
-}
-
-/*
-@include trans-colors;
-*/
-/*
-@include trans-colors-opa;
-*/
-/*
-@include trans-colors-svg;
-*/
-/*
-@include trans-colors-border;
-*/
-.nav-vert, .nav-dir, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- nav-up: auto;
- nav-down: auto;
-}
-
-.nav-horiz, .nav-dir, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- nav-right: auto;
- nav-left: auto;
-}
-
-.nav-foc, .nav-all, .config-debug__select-wrapper select selectbox option, .config-debug__select-wrapper select, .config-debug__select-wrapper input, .toggle, .subtitle-title:not(:disabled, [disabled]), .menu-list-item:not(:disabled, [disabled]), .icon-button:not([disabled]), .button:not([disabled]), .button, .config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option, .config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper, .config-option__radio-tabs input.radio,
-.config-option__list input.radio, .config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox, .tab, .control-option__binding:not([disabled]) {
- focus: auto;
- tab-index: auto;
-}
-
-/*
-@include set-color(COLOR);
-*/
-body {
- box-sizing: border-box;
- color: Text;
- font-family: "Suplexmentary Comic NC";
-}
-
-/* stylelint-disable color-no-hex */
-/* stylelint-disable selector-max-id */
-* {
- box-sizing: border-box;
-}
-
-hr {
- display: block;
- padding: 1.5dp;
- background: Background1;
-}
-
-body {
- color: #fff;
- font-size: 20dp;
- font-style: normal;
- font-weight: normal;
-}
-
-/* div {
- focus:none;
- tab-index:none;
-} */
-div#window {
- position: relative;
- box-sizing: border-box;
- width: 100%;
- height: 100%;
- border-color: Border;
- background-color: Background2;
-}
-
-div#content {
- z-index: 2;
- width: auto;
- height: 100%;
- overflow: hidden auto;
- text-align: center;
-}
-
-p {
- text-align: left;
-}
-
-input.submit {
- margin-left: 0;
-}
-
-input.text,
-input.password {
- box-sizing: border-box;
- height: 31dp;
- padding: 11dp 10dp 0;
- text-align: left;
- cursor: text;
-}
-
-textarea {
- padding: 14dp 12dp 10dp;
- text-align: left;
- cursor: text;
-}
-
-input.text,
-input.password,
-select,
-textarea {
- /* color: #333; */
- /* font-size: 13dp */
- height: auto;
-}
-
-table input.text {
- box-sizing: border-box;
- width: 100%;
- height: auto;
- /* height: 18dp; */
- margin: 0;
- border-width: 1.1dp;
- border-color: #000;
- background-color: #fff;
- font-size: 15dp;
- /* padding: 0 5dp; */
- line-height: 1;
- decorator: none;
- /* vertical-align: center; */
-}
-
-input.radio {
- flex: 0;
- width: 0dp;
- nav-up: auto;
- nav-right: auto;
- nav-down: auto;
- nav-left: auto;
- tab-index: auto;
- focus: auto;
-}
-
-input.checkbox {
- width: 20dp;
- height: 20dp;
- nav-up: auto;
- nav-right: auto;
- nav-down: auto;
- nav-left: auto;
- tab-index: auto;
- focus: auto;
-}
-
-scrollbarvertical, scrollbarhorizontal {
- margin: 0;
- border: 0;
-}
-scrollbarvertical slidertrack, scrollbarhorizontal slidertrack {
- background: PrimaryL;
- opacity: 0.05;
-}
-scrollbarvertical sliderbar, scrollbarhorizontal sliderbar {
- border-radius: 5dp;
- background: PrimaryL;
- opacity: 0.1;
-}
-scrollbarvertical sliderbar:hover:not(:active), scrollbarhorizontal sliderbar:hover:not(:active) {
- opacity: 0.2;
-}
-scrollbarvertical sliderbar:active, scrollbarhorizontal sliderbar:active {
- opacity: 0.3;
-}
-scrollbarvertical sliderarrowdec, scrollbarvertical sliderarrowinc, scrollbarhorizontal sliderarrowdec, scrollbarhorizontal sliderarrowinc {
- width: 0;
- height: 0;
-}
-
-scrollbarvertical {
- width: 12dp;
-}
-scrollbarvertical slidertrack {
- width: 12dp;
-}
-scrollbarvertical sliderbar {
- width: 12dp;
-}
-
-scrollbarhorizontal {
- height: 12dp;
-}
-scrollbarhorizontal slidertrack {
- height: 12dp;
-}
-scrollbarhorizontal sliderbar {
- height: 12dp;
-}
-
-.centered-page {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- padding: 64dp;
- background-color: BorderSoft;
-}
-
-.centered-page__modal {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: 1692.4444444444dp;
- height: 100%;
- margin: auto;
- border-width: 1.1dp;
- border-radius: 16dp;
- border-color: Border;
- background: ModalOverlay;
-}
-.centered-page__modal > .tabs {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: 1692.4444444444dp;
- height: 100%;
- margin: auto;
-}
-.centered-page__modal panels {
- flex: 1 1 100%;
-}
-
-.centered-page__controls {
- display: flex;
- position: absolute;
- bottom: 24dp;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- width: 100%;
- max-width: 1692.4444444444dp;
- height: auto;
- margin: 0 auto;
-}
-.centered-page__controls > label {
- display: inline-block;
- align-items: center;
- justify-content: space-between;
- width: auto;
- height: 24dp;
-}
-.centered-page__controls > label:not(:last-child) {
- margin-right: 40dp;
-}
-.centered-page__controls > label > span:first-child {
- margin-right: 4dp;
-}
-
-.control-option {
- color: TextDim;
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- height: auto;
- padding: 4dp 16dp 4dp 20dp;
- border-radius: 8dp;
- background-color: rgba(0, 0, 0, 0);
-}
-.control-option svg {
- image-color: TextDim;
-}
-.control-option svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.control-option:focus-visible:not(:disabled, [disabled]), .control-option:hover:not(:disabled, [disabled]) {
- color: Text;
- background-color: BGOverlay;
-}
-.control-option:focus-visible:not(:disabled, [disabled]) svg, .control-option:hover:not(:disabled, [disabled]) svg {
- image-color: Text;
-}
-.control-option:disabled, .control-option[disabled] {
- opacity: 0.5;
-}
-[cur-binding-slot="0"] .control-option--active .control-option__binding[bind-slot="0"] {
- border-color: Danger;
-}
-[cur-binding-slot="0"] .control-option--active .control-option__binding[bind-slot="0"] .control-option__binding-icon {
- opacity: 0;
-}
-[cur-binding-slot="0"] .control-option--active .control-option__binding[bind-slot="0"] .control-option__binding-recording {
- opacity: 1;
-}
-[cur-binding-slot="1"] .control-option--active .control-option__binding[bind-slot="1"] {
- border-color: Danger;
-}
-[cur-binding-slot="1"] .control-option--active .control-option__binding[bind-slot="1"] .control-option__binding-icon {
- opacity: 0;
-}
-[cur-binding-slot="1"] .control-option--active .control-option__binding[bind-slot="1"] .control-option__binding-recording {
- opacity: 1;
-}
-.control-option .icon-button {
- flex: 1 1 auto;
-}
-
-.control-option__label {
- flex: 2 1 300dp;
- height: auto;
- white-space: nowrap;
-}
-
-.control-option__bindings {
- display: flex;
- position: relative;
- flex: 2 1 400dp;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- height: 56dp;
- padding: 0 12dp 0 4dp;
-}
-
-.control-option__binding {
- color: TextDim;
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out, border-color 0.05s linear-in-out;
- display: flex;
- position: relative;
- flex: 1 1 100%;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: 56dp;
- margin: 0 4dp;
- padding: 8dp;
- border-width: 1.1dp;
- border-radius: 8dp;
- border-color: BGOverlay;
- background-color: BGOverlay;
-}
-.control-option__binding svg {
- image-color: TextDim;
-}
-.control-option__binding svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.control-option__binding:focus, .control-option__binding:hover {
- color: Text;
- border-color: Text;
- background-color: BorderSoft;
-}
-.control-option__binding:focus svg, .control-option__binding:hover svg {
- image-color: Text;
-}
-.control-option__binding:active {
- color: TextActive;
-}
-.control-option__binding:active svg {
- image-color: TextActive;
-}
-.control-option__binding:disabled, .control-option__binding[disabled] {
- color: TextDim;
- opacity: 0.5;
-}
-.control-option__binding:disabled svg, .control-option__binding[disabled] svg {
- image-color: TextDim;
-}
-.control-option__binding:not([disabled]) {
- cursor: pointer;
-}
-
-.control-option__binding-icon {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- opacity: 1;
-}
-
-@keyframes control-option__binding-recording-scale {
- 0% {
- transform: scale(1);
- }
- 50% {
- transform: scale(0.85);
- }
- 100% {
- transform: scale(1);
- }
-}
-.control-option__binding-recording {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
- opacity: 0;
-}
-.control-option__binding-recording .control-option__binding-circle {
- width: 24dp;
- height: 24dp;
- animation: 1.5s sine-in-out infinite control-option__binding-recording-scale;
- border-radius: 24dp;
- background-color: Danger;
-}
-.control-option__binding-recording .control-option__binding-edge {
- position: absolute;
- top: 50%;
- left: 50%;
- width: 36dp;
- height: 36dp;
- transform: translate(-50%, -50%);
-}
-.control-option__binding-recording .control-option__binding-edge > svg.control-option__binding-edge-svg {
- width: 36dp;
- height: 36dp;
- image-color: Danger;
-}
-
-/*
- Example:
-
- Graphics
-
-
-*/
-.tabs tabs {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
-}
-
-.tab {
- display: block;
- position: relative;
- margin: 0;
- padding: 20dp 24dp;
- transition: color 0.05s linear-in-out;
- opacity: 0.9;
- background-color: rgba(0, 0, 0, 0);
- color: TextInactive;
-}
-.tab:selected {
- color: Text;
-}
-.tab:selected .tab__indicator {
- background-color: BorderSolid;
-}
-.tab:selected:hover {
- cursor: default;
-}
-.rmlui-window:not([mouse-active]) .tab:focus {
- transition: none;
- animation: blue-pulse 0.75s infinite;
-}
-.rmlui-window:not([mouse-active]) .tab:focus:selected .tab__indicator {
- animation: blue-pulse-background 0.75s infinite;
-}
-.tab:focus, .tab:hover {
- opacity: 1;
- color: Text;
- cursor: pointer;
-}
-
-.tab__indicator {
- position: absolute;
- right: 0;
- bottom: 2dp;
- left: 0;
- height: 2dp;
- background-color: rgba(0, 0, 0, 0);
-}
-
-.config__icon-buttons {
- display: flex;
- position: absolute;
- top: 8dp;
- right: 0dp;
- flex-direction: row;
- align-items: center;
- justify-content: flex-end;
- width: auto;
-}
-.config__icon-buttons .icon-button {
- margin: 0 8dp;
-}
-
-.config__form {
- border-top-width: 1.1dp;
- border-top-color: BorderSoft;
- display: flex;
- flex: 1 1 100%;
- flex-direction: column;
- justify-content: space-between;
- width: 100%;
- height: 100%;
- border-bottom-right-radius: 16dp;
- border-bottom-left-radius: 16dp;
-}
-
-.config__wrapper {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: 16dp;
- border-radius: 0dp;
- border-bottom-right-radius: 16dp;
- border-bottom-left-radius: 16dp;
- background-color: BGShadow;
- text-align: left;
-}
-.config__wrapper p {
- padding: 16dp;
- line-height: 28dp;
- white-space: pre-line;
-}
-.config__wrapper p b {
- color: Primary;
-}
-.config__wrapper p i {
- color: Warning;
- font-style: normal;
-}
-
-.config__hz-wrapper {
- display: flex;
- flex: 1 1 100%;
- flex-direction: row;
- width: 100%;
- height: 100%;
- border-radius: 0dp;
- text-align: left;
-}
-
-.config__header, .config__footer {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- background-color: BGShadow;
-}
-
-.config__header {
- border-bottom-width: 1.1dp;
- border-bottom-color: BorderSoft;
- padding: 12dp 20dp;
-}
-
-.config__footer {
- border-top-width: 1.1dp;
- border-top-color: BorderSoft;
- padding: 20dp 20dp;
- border-bottom-right-radius: 16dp;
- border-bottom-left-radius: 16dp;
-}
-
-.config__header-left {
- display: flex;
- flex: 1 1 auto;
- flex-direction: row;
-}
-.config__header-left > :not(:first-child) {
- margin-left: 8dp;
-}
-
-.config__row {
- display: flex;
- flex-direction: row;
-}
-
-.config-group {
- position: relative;
-}
-.config-group--scrollable {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: 0 0 0 16dp;
-}
-.config-group--scrollable .config-group__wrapper {
- max-height: 100%;
- overflow-y: auto;
-}
-.config-group__title {
- color: Primary;
-}
-.config-group__title--hidden {
- display: none;
-}
-.config-group__wrapper {
- padding: 16dp 0;
-}
-
-.config-option {
- display: flex;
- flex: 1;
- flex-direction: column;
- align-items: flex-start;
- justify-content: flex-start;
- margin: 16dp 0dp 24dp;
-}
-.config-option--hz {
- flex-direction: row-reverse;
- align-items: center;
- margin-top: 4dp;
- margin-bottom: 4dp;
-}
-.config-option--hz .config-option__title {
- flex: 1 1 100%;
-}
-.config-option--hz .config-option__list {
- flex: 1 1 auto;
- width: auto;
-}
-.config-option--hz:first-child {
- margin-top: 0;
-}
-.config-option--hz:last-child {
- margin-bottom: 0;
-}
-
-.config-option__title {
- padding: 0 12dp;
-}
-
-.config-option__radio-tabs,
-.config-option__list {
- display: flex;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- height: auto;
- padding: 0;
-}
-.config-option__radio-tabs input:first-of-type,
-.config-option__list input:first-of-type {
- nav-left: none;
-}
-.config-option__radio-tabs input:last-of-type,
-.config-option__list input:last-of-type {
- nav-right: none;
-}
-.config-option__radio-tabs .config-option__tab-label,
-.config-option__list .config-option__tab-label {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- display: block;
- position: relative;
- height: auto;
- margin: 4dp 12dp 0;
- padding: 8dp 0;
- color: TextInactive;
- tab-index: none;
-}
-.config-option__radio-tabs .config-option__tab-label:hover,
-.config-option__list .config-option__tab-label:hover {
- color: Text;
- cursor: pointer;
-}
-.config-option__radio-tabs .config-option__checkbox-wrapper,
-.config-option__list .config-option__checkbox-wrapper {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- width: 32dp;
- height: 32dp;
- margin: 4dp 12dp 0;
- border-radius: 8dp;
- opacity: 0.5;
- background-color: BGOverlay;
- cursor: pointer;
-}
-.config-option__radio-tabs .config-option__checkbox-wrapper:hover,
-.config-option__list .config-option__checkbox-wrapper:hover {
- opacity: 1;
-}
-.config-option__radio-tabs .config-option__checkbox-wrapper[checked],
-.config-option__list .config-option__checkbox-wrapper[checked] {
- background-color: A;
-}
-.config-option__radio-tabs .config-option__checkbox,
-.config-option__list .config-option__checkbox {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- visibility: visible;
- width: 0;
- height: 0;
-}
-.config-option__radio-tabs input.radio,
-.config-option__list input.radio {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- visibility: visible;
- width: 0;
- height: 0;
-}
-.config-option__radio-tabs input.radio:not(:disabled):checked + .config-option__tab-label,
-.config-option__list input.radio:not(:disabled):checked + .config-option__tab-label {
- border-bottom: 1dp;
- border-color: Text;
- color: Text;
-}
-.config-option__radio-tabs input.radio:not(:disabled):checked + .config-option__tab-label:hover,
-.config-option__list input.radio:not(:disabled):checked + .config-option__tab-label:hover {
- cursor: default;
-}
-.rmlui-window:not([mouse-active]) .config-option__radio-tabs input.radio:not(:disabled):focus + .config-option__tab-label,
-.rmlui-window:not([mouse-active]) .config-option__list input.radio:not(:disabled):focus + .config-option__tab-label {
- transition: none;
- animation: blue-pulse 0.75s infinite;
- border-color: Secondary;
- color: Secondary;
-}
-.config-option__radio-tabs input.radio:not(:disabled):focus + .config-option__tab-label, .config-option__radio-tabs input.radio:not(:disabled):hover + .config-option__tab-label,
-.config-option__list input.radio:not(:disabled):focus + .config-option__tab-label,
-.config-option__list input.radio:not(:disabled):hover + .config-option__tab-label {
- color: Text;
-}
-.config-option__radio-tabs input.radio:disabled + .config-option__tab-label,
-.config-option__list input.radio:disabled + .config-option__tab-label {
- opacity: 0.5;
-}
-.config-option__radio-tabs input.radio:disabled + .config-option__tab-label:hover,
-.config-option__list input.radio:disabled + .config-option__tab-label:hover {
- cursor: default;
-}
-.config-option__radio-tabs input.range slidertrack,
-.config-option__list input.range slidertrack {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- height: 2dp;
- margin-top: 8dp;
- background-color: Border;
-}
-.config-option__radio-tabs input.range sliderbar,
-.config-option__list input.range sliderbar {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- width: 16dp;
- height: 16dp;
- margin-top: 1dp;
- margin-right: -8dp;
- margin-left: -8dp;
- transition: background-color 0.05s linear-in-out;
- border-radius: 8dp;
- background-color: TextDim;
-}
-.rmlui-window:not([mouse-active]) .config-option__radio-tabs input.range sliderbar:focus,
-.rmlui-window:not([mouse-active]) .config-option__list input.range sliderbar:focus {
- border-width: 1.1dp;
- border-color: A;
- animation: blue-pulse-background 0.75s infinite;
-}
-.config-option__radio-tabs input.range sliderbar:hover,
-.config-option__list input.range sliderbar:hover {
- background-color: Text;
- cursor: pointer;
-}
-.config-option__radio-tabs input.range sliderbar:active,
-.config-option__radio-tabs input.range slidertrack:active + sliderbar,
-.config-option__list input.range sliderbar:active,
-.config-option__list input.range slidertrack:active + sliderbar {
- background-color: Secondary;
-}
-.config-option__radio-tabs input.range sliderarrowdec,
-.config-option__radio-tabs input.range sliderarrowinc,
-.config-option__list input.range sliderarrowdec,
-.config-option__list input.range sliderarrowinc {
- display: none;
-}
-
-.config-option__details {
- height: 18dp;
- margin: 14dp 12dp 0;
- color: Primary;
-}
-
-.config-option-color {
- width: 100%;
- max-width: 360dp;
- height: auto;
- margin-top: 4dp;
- margin-left: 12dp;
- padding: 0;
-}
-.config-option-color__preview-wrapper {
- display: flex;
- flex-direction: row;
- width: 100%;
- height: 72dp;
-}
-.config-option-color__preview-block {
- display: block;
- width: 88dp;
- height: 100%;
- border-width: 1.1dp;
- border-radius: 16dp;
- border-color: Border;
-}
-.config-option-color__hsv-wrapper {
- display: flex;
- flex: 1 1 100%;
- flex-direction: column;
- width: auto;
- height: auto;
- padding-left: 8dp;
-}
-.config-option-color__hsv-wrapper .config-option-range {
- flex: 1 1 auto;
-}
-.config-option-color__hsv-wrapper .config-option-range label {
- min-width: 72dp;
-}
-.config-option-color__hsv-wrapper .config-option-range input {
- flex: 1 1 auto;
-}
-
-.config-option-range {
- display: flex;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- max-width: 360dp;
- height: auto;
- margin-top: 4dp;
- padding: 0;
-}
-.config-option-range__label {
- display: block;
- width: 56dp;
- margin: 0 12dp;
- margin-right: 16dp;
- padding: 0;
- color: Text;
- tab-index: none;
-}
-.config-option-range__range-input {
- flex: 1;
-}
-.config-option-range__range-input slidertrack {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- height: 2dp;
- margin-top: 8dp;
- background-color: Border;
-}
-.config-option-range__range-input sliderbar {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- width: 16dp;
- height: 16dp;
- margin-top: 1dp;
- margin-right: -8dp;
- margin-left: -8dp;
- transition: background-color 0.05s linear-in-out;
- border-radius: 8dp;
- background-color: TextDim;
-}
-.rmlui-window:not([mouse-active]) .config-option-range__range-input sliderbar:focus {
- border-width: 1.1dp;
- border-color: A;
- animation: blue-pulse-background 0.75s infinite;
-}
-.config-option-range__range-input sliderbar:hover {
- background-color: Text;
- cursor: pointer;
-}
-.config-option-range__range-input sliderbar:active,
-.config-option-range__range-input slidertrack:active + sliderbar {
- background-color: Secondary;
-}
-.config-option-range__range-input sliderarrowdec,
-.config-option-range__range-input sliderarrowinc {
- display: none;
-}
-
-.config-option__range-wrapper {
- max-width: 360dp;
- margin-top: 4dp;
-}
-
-.config-option__range-label {
- display: block;
- width: 56dp;
- margin: 0 12dp;
- margin-right: 16dp;
- padding: 0;
- color: Text;
- tab-index: none;
-}
-
-.config-option-dropdown, .config-option-textfield {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- width: auto;
- height: auto;
- padding: 8dp 24dp 8dp 12dp;
-}
-.config-option-dropdown__select, .config-option-textfield__select {
- display: block;
- height: 48dp;
- padding: 14dp;
- cursor: pointer;
-}
-.config-option-dropdown__wrapper, .config-option-textfield__wrapper {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: 100%;
- height: auto;
- padding: 2dp 0 12dp;
- cursor: text;
-}
-.config-option-dropdown__wrapper input, .config-option-textfield__wrapper input {
- width: 100%;
- height: auto;
- vertical-align: middle;
-}
-.config-option-dropdown__select, .config-option-dropdown__wrapper, .config-option-textfield__select, .config-option-textfield__wrapper {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out, border-color 0.05s linear-in-out;
- border-width: 1.1dp;
- border-color: WhiteA50;
- position: relative;
- box-sizing: border-box;
- flex: 1 1 100%;
- width: auto;
- border-radius: 12dp;
- background-color: WhiteA5;
-}
-.config-option-dropdown__select svg, .config-option-dropdown__wrapper svg, .config-option-textfield__select svg, .config-option-textfield__wrapper svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.config-option-dropdown__select:hover, .config-option-dropdown__select:focus, .config-option-dropdown__wrapper:hover, .config-option-dropdown__wrapper:focus, .config-option-textfield__select:hover, .config-option-textfield__select:focus, .config-option-textfield__wrapper:hover, .config-option-textfield__wrapper:focus {
- border-width: 1.1dp;
- border-color: WhiteA80;
- background-color: WhiteA20;
-}
-.config-option-dropdown__select selectvalue, .config-option-dropdown__wrapper selectvalue, .config-option-textfield__select selectvalue, .config-option-textfield__wrapper selectvalue {
- display: inline;
- height: auto;
- margin: auto 0;
-}
-.config-option-dropdown__select selectbox, .config-option-dropdown__wrapper selectbox, .config-option-textfield__select selectbox, .config-option-textfield__wrapper selectbox {
- border-width: 1.1dp;
- border-color: Border;
- margin-top: 2dp;
- padding: 4dp 0;
- border-radius: 12dp;
- background-color: Background3;
-}
-.config-option-dropdown__select selectbox option, .config-option-dropdown__wrapper selectbox option, .config-option-textfield__select selectbox option, .config-option-textfield__wrapper selectbox option {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- padding: 8dp 12dp;
- background-color: Transparent;
- color: TextDim;
- font-weight: 400;
-}
-.config-option-dropdown__select selectbox option:hover, .config-option-dropdown__select selectbox option:focus, .config-option-dropdown__wrapper selectbox option:hover, .config-option-dropdown__wrapper selectbox option:focus, .config-option-textfield__select selectbox option:hover, .config-option-textfield__select selectbox option:focus, .config-option-textfield__wrapper selectbox option:hover, .config-option-textfield__wrapper selectbox option:focus {
- background-color: WhiteA20;
-}
-.config-option-dropdown__select selectbox option:hover:not(:checked), .config-option-dropdown__wrapper selectbox option:hover:not(:checked), .config-option-textfield__select selectbox option:hover:not(:checked), .config-option-textfield__wrapper selectbox option:hover:not(:checked) {
- cursor: pointer;
-}
-.config-option-dropdown__select selectbox option:checked, .config-option-dropdown__wrapper selectbox option:checked, .config-option-textfield__select selectbox option:checked, .config-option-textfield__wrapper selectbox option:checked {
- background-color: WhiteA5;
- color: White;
-}
-
-.config-description {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: 16dp;
- border-radius: 0dp;
- border-bottom-right-radius: 16dp;
- border-bottom-left-radius: 16dp;
- background-color: BGShadow;
- text-align: left;
-}
-.config-description__contents {
- padding: 16dp;
- line-height: 28dp;
- white-space: pre-line;
-}
-.config-description__contents b {
- color: Primary;
-}
-.config-description__contents i {
- color: Warning;
- font-style: normal;
-}
-
-.input-config {
- padding: 0;
-}
-
-.input-config__horizontal-split {
- display: flex;
- position: relative;
- flex-direction: row;
- height: 100%;
-}
-
-.input-config__mappings {
- display: block;
- flex: 1 1 auto;
- min-width: 640dp;
- height: 100%;
-}
-
-.input-config__mappings-scroll {
- display: block;
- width: 100%;
- max-height: 100%;
- overflow-y: auto;
-}
-
-.input-config__mappings-wrapper {
- padding: 8dp;
-}
-
-.input-config__visual-wrapper {
- display: block;
- flex: 1 1 100%;
- width: auto;
- max-width: 1040.4444444444dp;
- height: auto;
- max-height: 780.3333333333dp;
- margin: auto 0;
-}
-
-.input-config__visual-aspect {
- position: relative;
- width: 100%;
- margin: auto 0;
- padding-bottom: 75%;
- background-color: BGShadow;
-}
-
-.input-config__visual {
- display: flex;
- position: absolute;
- top: 16dp;
- right: 16dp;
- bottom: 16dp;
- left: 16dp;
- flex-direction: column;
- border-radius: 108dp;
- background-color: WhiteA5;
-}
-
-.input-config__visual-half {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: row;
- padding: 6%;
-}
-.input-config__visual-half--bottom {
- align-items: flex-end;
- justify-content: space-between;
-}
-
-.input-config__visual-quarter-left {
- display: flex;
- flex: 1 1 50%;
- align-items: flex-start;
- justify-content: flex-start;
- width: auto;
-}
-
-.input-config__visual-quarter-right {
- display: flex;
- flex: 1 1 100%;
- align-items: flex-start;
- justify-content: flex-end;
-}
-
-.input-config__visual-stick-wrapper {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
-}
-
-.input-viz {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- display: flex;
- position: relative;
- align-items: center;
- justify-content: center;
-}
-.input-viz > svg:not(.input-viz__dpad-arrow) {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
-}
-[cur-input=NONE] .input-viz[visual-input] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=A] {
- opacity: 0.25;
-}
-[cur-input=A] .input-viz[visual-input~=A] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=B] {
- opacity: 0.25;
-}
-[cur-input=B] .input-viz[visual-input~=B] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=Z] {
- opacity: 0.25;
-}
-[cur-input=Z] .input-viz[visual-input~=Z] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=START] {
- opacity: 0.25;
-}
-[cur-input=START] .input-viz[visual-input~=START] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=DPAD_UP] {
- opacity: 0.25;
-}
-[cur-input=DPAD_UP] .input-viz[visual-input~=DPAD_UP] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=DPAD_DOWN] {
- opacity: 0.25;
-}
-[cur-input=DPAD_DOWN] .input-viz[visual-input~=DPAD_DOWN] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=DPAD_LEFT] {
- opacity: 0.25;
-}
-[cur-input=DPAD_LEFT] .input-viz[visual-input~=DPAD_LEFT] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=DPAD_RIGHT] {
- opacity: 0.25;
-}
-[cur-input=DPAD_RIGHT] .input-viz[visual-input~=DPAD_RIGHT] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=L] {
- opacity: 0.25;
-}
-[cur-input=L] .input-viz[visual-input~=L] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=R] {
- opacity: 0.25;
-}
-[cur-input=R] .input-viz[visual-input~=R] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=C_UP] {
- opacity: 0.25;
-}
-[cur-input=C_UP] .input-viz[visual-input~=C_UP] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=C_DOWN] {
- opacity: 0.25;
-}
-[cur-input=C_DOWN] .input-viz[visual-input~=C_DOWN] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=C_LEFT] {
- opacity: 0.25;
-}
-[cur-input=C_LEFT] .input-viz[visual-input~=C_LEFT] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=C_RIGHT] {
- opacity: 0.25;
-}
-[cur-input=C_RIGHT] .input-viz[visual-input~=C_RIGHT] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=X_AXIS_NEG] {
- opacity: 0.25;
-}
-[cur-input=X_AXIS_NEG] .input-viz[visual-input~=X_AXIS_NEG] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=X_AXIS_POS] {
- opacity: 0.25;
-}
-[cur-input=X_AXIS_POS] .input-viz[visual-input~=X_AXIS_POS] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=Y_AXIS_NEG] {
- opacity: 0.25;
-}
-[cur-input=Y_AXIS_NEG] .input-viz[visual-input~=Y_AXIS_NEG] {
- opacity: 1;
-}
-
-.input-viz[visual-input~=Y_AXIS_POS] {
- opacity: 0.25;
-}
-[cur-input=Y_AXIS_POS] .input-viz[visual-input~=Y_AXIS_POS] {
- opacity: 1;
-}
-
-.input-viz__button {
- color: Text;
-}
-.input-viz__button svg {
- image-color: Text;
-}
-.input-viz__button--sm {
- width: 64dp;
- height: 64dp;
-}
-.input-viz__button--sm > svg {
- width: 64dp;
- height: 64dp;
-}
-.input-viz__button--md {
- width: 76dp;
- height: 76dp;
-}
-.input-viz__button--md > svg {
- width: 76dp;
- height: 76dp;
-}
-.input-viz__button--lg {
- width: 84dp;
- height: 84dp;
-}
-.input-viz__button--lg > svg {
- width: 84dp;
- height: 84dp;
-}
-.input-viz__button--C svg {
- image-color: Warning;
-}
-.input-viz__button--A {
- margin-top: auto;
-}
-.input-viz__button--A svg {
- image-color: A;
-}
-.input-viz__button--B svg {
- image-color: Success;
-}
-.input-viz__button--Start svg {
- image-color: Danger;
-}
-
-.input-viz__Z {
- width: 136dp;
- height: 136dp;
-}
-.input-viz__Z svg {
- image-color: Warning;
-}
-.input-viz__Z > svg {
- width: 136dp;
- height: 136dp;
-}
-
-.input-viz.input-viz__dpad {
- width: 192dp;
- height: 192dp;
- position: relative;
-}
-.input-viz.input-viz__dpad svg {
- image-color: Text;
-}
-.input-viz.input-viz__dpad > svg {
- width: 192dp;
- height: 192dp;
-}
-
-.input-config__visual-stick {
- display: flex;
- position: relative;
- align-items: center;
- justify-content: center;
- width: 200dp;
- height: 200dp;
- border-radius: 100dp;
- background-color: WhiteA5;
-}
-
-.input-viz__dpad-split,
-.input-viz__stick-split {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- display: flex;
- width: 100%;
- height: 100%;
-}
-.input-viz__dpad-split--vertical,
-.input-viz__stick-split--vertical {
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
-}
-.input-viz__dpad-split--horizontal,
-.input-viz__stick-split--horizontal {
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
-}
-.input-viz__dpad-split > div,
-.input-viz__stick-split > div {
- display: flex;
- flex: 1 1 100%;
- flex-direction: row;
- align-items: center;
- justify-content: center;
-}
-
-.input-viz__dpad-split > div {
- width: 64dp;
- height: 64dp;
-}
-
-.input-viz__stick-split > div {
- width: 66.6666666667dp;
- height: 66.6666666667dp;
-}
-
-.input-viz__dpad-arrow {
- position: absolute;
- width: 60dp;
- height: 60dp;
-}
-.input-viz__dpad-arrow--up {
- top: 4dp;
- margin: 0 auto;
-}
-.input-viz__dpad-arrow--down {
- bottom: 4dp;
- margin: 0 auto;
- transform: rotate(180deg);
-}
-.input-viz__dpad-arrow--left {
- left: 4dp;
- margin: auto 0;
- transform: rotate(-90deg);
-}
-.input-viz__dpad-arrow--right {
- right: 4dp;
- margin: auto 0;
- transform: rotate(90deg);
-}
-
-.input-viz__R {
- width: 96dp;
- height: 96dp;
-}
-.input-viz__R svg {
- image-color: White;
-}
-.input-viz__R > svg {
- width: 96dp;
- height: 96dp;
-}
-
-.input-viz__L {
- width: 136dp;
- height: 136dp;
-}
-.input-viz__L svg {
- image-color: Secondary;
-}
-.input-viz__L > svg {
- width: 136dp;
- height: 136dp;
-}
-
-.input-config__c-buttons {
- position: relative;
- width: 208dp;
- height: 132dp;
-}
-.input-config__c-buttons-lr, .input-config__c-buttons-du {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
-}
-.input-config__c-buttons-lr {
- flex-direction: row;
- align-items: flex-start;
- justify-content: space-between;
-}
-.input-config__c-buttons-du {
- flex-direction: column-reverse;
- align-items: center;
- justify-content: space-between;
-}
-.input-config__c-buttons .input-viz[visual-input=C_UP] {
- margin-top: -32dp;
-}
-
-.input-config__main-buttons {
- display: flex;
- position: relative;
- flex-direction: row;
- justify-content: space-between;
- width: 268dp;
- height: 128dp;
- margin-right: 10dp;
-}
-
-.button {
- border-color: PrimaryA80;
- background-color: PrimaryA5;
- color: TextDim;
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- display: block;
- width: auto;
- height: auto;
- padding: 23dp;
- border-width: 1.1dp;
- border-radius: 12dp;
-}
-.button:focus, .button:hover {
- border-color: Primary;
- background-color: PrimaryA30;
- color: Text;
-}
-.button:disabled, .button[disabled] {
- color: TextInactive;
-}
-.button:active {
- background-color: PrimaryA20;
- color: TextActive;
-}
-.button--primary {
- border-color: PrimaryA80;
- background-color: PrimaryA5;
- color: TextDim;
-}
-.button--primary:focus, .button--primary:hover {
- border-color: Primary;
- background-color: PrimaryA30;
- color: Text;
-}
-.button--primary:disabled, .button--primary[disabled] {
- color: TextInactive;
-}
-.button--primary:active {
- background-color: PrimaryA20;
- color: TextActive;
-}
-.button--secondary {
- border-color: SecondaryA80;
- background-color: SecondaryA5;
- color: TextDim;
-}
-.button--secondary:focus, .button--secondary:hover {
- border-color: Secondary;
- background-color: SecondaryA30;
- color: Text;
-}
-.button--secondary:disabled, .button--secondary[disabled] {
- color: TextInactive;
-}
-.button--secondary:active {
- background-color: SecondaryA20;
- color: TextActive;
-}
-.button--tertiary {
- border-color: TextA80;
- background-color: TextA5;
- color: TextDim;
-}
-.button--tertiary:focus, .button--tertiary:hover {
- border-color: Text;
- background-color: TextA30;
- color: Text;
-}
-.button--tertiary:disabled, .button--tertiary[disabled] {
- color: TextInactive;
-}
-.button--tertiary:active {
- background-color: TextA20;
- color: TextActive;
-}
-.button--success {
- border-color: SuccessA80;
- background-color: SuccessA5;
- color: TextDim;
-}
-.button--success:focus, .button--success:hover {
- border-color: Success;
- background-color: SuccessA30;
- color: Text;
-}
-.button--success:disabled, .button--success[disabled] {
- color: TextInactive;
-}
-.button--success:active {
- background-color: SuccessA20;
- color: TextActive;
-}
-.button--danger {
- border-color: DangerA80;
- background-color: DangerA5;
- color: TextDim;
-}
-.button--danger:focus, .button--danger:hover {
- border-color: Danger;
- background-color: DangerA30;
- color: Text;
-}
-.button--danger:disabled, .button--danger[disabled] {
- color: TextInactive;
-}
-.button--danger:active {
- background-color: DangerA20;
- color: TextActive;
-}
-.button--warning {
- border-color: WarningA80;
- background-color: WarningA5;
- color: TextDim;
-}
-.button--warning:focus, .button--warning:hover {
- border-color: Warning;
- background-color: WarningA30;
- color: Text;
-}
-.button--warning:disabled, .button--warning[disabled] {
- color: TextInactive;
-}
-.button--warning:active {
- background-color: WarningA20;
- color: TextActive;
-}
-.button:not([disabled]) {
- cursor: pointer;
-}
-.button:disabled, .button[disabled] {
- opacity: 0.5;
-}
-.button__label {
- width: auto;
- height: auto;
-}
-
-/*
-
-*/
-.icon-button {
- color: TextDim;
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out, border-color 0.05s linear-in-out;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 53.8dp;
- min-width: 53.8dp;
- max-width: 53.8dp;
- height: 53.8dp;
- min-height: 53.8dp;
- max-height: 53.8dp;
- border-width: 1.1dp;
- border-radius: 26.9dp;
- border-color: Transparent;
- background-color: Transparent;
-}
-.icon-button svg {
- image-color: TextDim;
-}
-.icon-button svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.icon-button:focus, .icon-button:hover {
- color: Text;
- background-color: Border;
-}
-.icon-button:focus svg, .icon-button:hover svg {
- image-color: Text;
-}
-.icon-button:active {
- color: TextActive;
- background-color: BorderSoft;
-}
-.icon-button:active svg {
- image-color: TextActive;
-}
-.icon-button:disabled, .icon-button[disabled] {
- color: TextDim;
- opacity: 0.5;
-}
-.icon-button:disabled svg, .icon-button[disabled] svg {
- image-color: TextDim;
-}
-.icon-button:not([disabled]) {
- cursor: pointer;
-}
-.icon-button svg {
- width: 32dp;
- height: 32dp;
-}
-.icon-button--primary {
- border-color: PrimaryA80;
- background-color: PrimaryA5;
-}
-.icon-button--primary:focus, .icon-button--primary:hover {
- border-color: Primary;
- background-color: PrimaryA30;
-}
-.icon-button--primary:active {
- background-color: PrimaryA20;
-}
-.icon-button--secondary {
- border-color: SecondaryA80;
- background-color: SecondaryA5;
-}
-.icon-button--secondary:focus, .icon-button--secondary:hover {
- border-color: Secondary;
- background-color: SecondaryA30;
-}
-.icon-button--secondary:active {
- background-color: SecondaryA20;
-}
-.icon-button--tertiary {
- border-color: TextA80;
- background-color: TextA5;
-}
-.icon-button--tertiary:focus, .icon-button--tertiary:hover {
- border-color: Text;
- background-color: TextA30;
-}
-.icon-button--tertiary:active {
- background-color: TextA20;
-}
-.icon-button--success {
- border-color: SuccessA80;
- background-color: SuccessA5;
-}
-.icon-button--success:focus, .icon-button--success:hover {
- border-color: Success;
- background-color: SuccessA30;
-}
-.icon-button--success:active {
- background-color: SuccessA20;
-}
-.icon-button--danger {
- border-color: DangerA80;
- background-color: DangerA5;
-}
-.icon-button--danger:focus, .icon-button--danger:hover {
- border-color: Danger;
- background-color: DangerA30;
-}
-.icon-button--danger:active {
- background-color: DangerA20;
-}
-.icon-button--warning {
- border-color: WarningA80;
- background-color: WarningA5;
-}
-.icon-button--warning:focus, .icon-button--warning:hover {
- border-color: Warning;
- background-color: WarningA30;
-}
-.icon-button--warning:active {
- background-color: WarningA20;
-}
-
-.launcher {
- display: block;
- position: relative;
- flex-direction: row;
- justify-content: space-between;
- width: 100%;
- height: 100%;
- background-color: Background1;
-}
-
-.launcher__vertical-split {
- display: flex;
- position: absolute;
- top: 0;
- right: 50%;
- bottom: 0;
- left: 0;
- flex-direction: column;
- align-items: flex-start;
- justify-content: space-between;
-}
-.launcher__vertical-split--right {
- right: 0;
- left: 50%;
- align-items: flex-end;
-}
-
-@keyframes slide-mm-bg-over {
- 0% {
- transform: translateX(100dp);
- }
- 100% {
- transform: translateX(0dp);
- }
-}
-.launcher__background-wrapper {
- display: flex;
- position: absolute;
- top: -55vw;
- right: -100%;
- bottom: -50vw;
- left: -70vw;
- align-items: center;
- justify-content: flex-start;
- transform: translateX(0dp);
- animation: 25s cubic-out 1 slide-mm-bg-over;
-}
-
-@keyframes fade-mm-in {
- 0% {
- opacity: 0;
- }
- 100% {
- opacity: 0.1;
- }
-}
-.launcher__background-bk {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- width: auto;
- height: 100%;
- animation: 2.5s cubic-in-out 1 fade-mm-in;
- opacity: 0.1;
-}
-
-.launcher__title-quadrant {
- flex: 1 1 auto;
- width: auto;
- height: auto;
- padding-top: 96dp;
- padding-left: 96dp;
-}
-.launcher__title-quadrant--right {
- padding-right: 96dp;
- padding-left: 0;
-}
-
-.launcher__content-quadrant {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- align-items: flex-start;
- justify-content: flex-end;
- width: 100%;
- height: auto;
- padding: 32dp;
-}
-
-/*
- Example layout:
-
- - Variants:
- .menu-list-item--right (align to right side)
- - Optional:
- -
Coming Soon™
-
-*/
-.menu-list-item {
- color: TextDim;
- display: flex;
- flex-direction: row;
- align-items: center;
- width: 100%;
- height: auto;
- padding: 16dp;
- border-radius: 8dp;
- background-color: rgba(0, 0, 0, 0);
- cursor: pointer;
-}
-.menu-list-item svg {
- image-color: TextDim;
-}
-.menu-list-item--right {
- flex-direction: row-reverse;
- align-content: flex-end;
-}
-.menu-list-item--right .menu-list-item__bullet {
- margin-left: 12dp;
- opacity: 1;
-}
-.menu-list-item--right.menu-list-item:focus:not(:disabled, [disabled]), .menu-list-item--right.menu-list-item:hover:not(:disabled, [disabled]) {
- background-color: WhiteA5;
-}
-.menu-list-item:focus:not(:disabled, [disabled]), .menu-list-item:hover:not(:disabled, [disabled]) {
- color: Primary;
- background-color: WhiteA5;
-}
-.menu-list-item:focus:not(:disabled, [disabled]) svg, .menu-list-item:hover:not(:disabled, [disabled]) svg {
- image-color: Primary;
-}
-.menu-list-item:focus:not(:disabled, [disabled]) .menu-list-item__bullet, .menu-list-item:hover:not(:disabled, [disabled]) .menu-list-item__bullet {
- opacity: 1;
-}
-.menu-list-item:disabled, .menu-list-item[disabled] {
- opacity: 0.5;
- tab-index: none;
- cursor: default;
-}
-
-.menu-list-item__bullet {
- margin-right: 12dp;
- opacity: 0;
-}
-
-/*
- Example layout:
-
-
- - Variants:
- .subtitle-title--right (align to right side)
- - Optional:
- - Coming Soon™
-
-*/
-.subtitle-title {
- display: block;
- position: relative;
- flex-direction: column;
- align-content: flex-start;
- align-items: flex-start;
- width: auto;
- height: auto;
- padding: 0;
- background-color: rgba(0, 0, 0, 0);
- color: TextDim;
- text-align: left;
- cursor: pointer;
-}
-.subtitle-title--right {
- align-content: flex-end;
-}
-.subtitle-title--right, .subtitle-title--right > * {
- text-align: right;
-}
-.subtitle-title[selected] {
- color: Text;
- cursor: default;
-}
-.subtitle-title:focus:not(:disabled, [disabled]), .subtitle-title:hover:not(:disabled, [disabled], [selected]) {
- color: Primary;
-}
-.subtitle-title:disabled, .subtitle-title[disabled] {
- opacity: 0.5;
- cursor: default;
- tab-index: none;
-}
-.subtitle-title h3 {
- margin-bottom: 6dp;
-}
-.subtitle-title h1 {
- margin-top: 6dp;
-}
-.subtitle-title__disclaimer {
- margin-top: 16dp;
-}
-
-.toggle {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: 162dp;
- height: 72dp;
- border-radius: 36dp;
- opacity: 0.9;
- background: Transparent;
- cursor: pointer;
-}
-.toggle:hover, .toggle:focus-visible, .toggle:focus {
- opacity: 1;
- background-color: SecondaryA30;
-}
-.toggle:active {
- opacity: 1;
- background-color: SecondaryA5;
-}
-.toggle .toggle__border {
- position: absolute;
- top: 1.1dp;
- right: 1.1dp;
- bottom: 1.1dp;
- left: 1.1dp;
- border-width: 1.1dp;
- border-color: SecondaryL;
- display: block;
- border-radius: 36dp;
-}
-.toggle .toggle__floater {
- position: absolute;
- top: 50%;
- left: 4dp;
- width: 80dp;
- height: 64dp;
- transform: translateY(-50%);
- border-radius: 32dp;
- background: SecondaryD;
-}
-.toggle--checked .toggle__floater {
- left: 78dp;
-}
-.toggle--checked .toggle__icon.toggle__icon--left {
- opacity: 0.9;
- color: SecondaryL;
-}
-.toggle--checked .toggle__icon.toggle__icon--right {
- opacity: 1;
- color: Text;
-}
-
-.toggle__icons {
- display: flex;
- position: absolute;
- top: 50%;
- right: 16dp;
- left: 16dp;
- align-items: center;
- justify-content: space-between;
- height: 56dp;
- transform: translateY(-50%);
-}
-
-.toggle__icon {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 56dp;
- height: 56dp;
- color: Text;
-}
-.toggle__icon--right {
- opacity: 1;
- color: SecondaryL;
-}
-
-.bottom-left {
- display: flex;
- position: absolute;
- bottom: 4dp;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- max-width: 1692.4444444444dp;
- height: auto;
- margin: 0 4dp;
-}
-
-.prompt__overlay {
- background-color: BGOverlay;
- pointer-events: auto;
-}
-.prompt__overlay, .prompt__content-wrapper {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
-}
-.prompt__content-wrapper {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
-}
-.prompt__content {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: 700dp;
- height: auto;
- margin: auto;
- border-width: 1.1dp;
- border-radius: 16dp;
- border-color: Border;
- background: ModalOverlay;
-}
-.prompt__content h3, .prompt__content p {
- margin: 24dp;
-}
-.prompt__content p {
- margin-top: 0;
-}
-.prompt__controls {
- display: flex;
- flex-direction: row;
- justify-content: center;
- padding: 24dp 12dp;
- border-top-width: 1.1dp;
- border-top-color: BorderSoft;
-}
-.prompt__controls .button {
- min-width: 233.3333333333dp;
- margin: 0 12dp;
- text-align: center;
- nav-up: none;
- nav-down: none;
-}
-
-.config-debug {
- display: block;
- position: relative;
- width: 100%;
- max-height: 100%;
- padding: 8dp;
-}
-
-.config-debug__scroll {
- display: block;
- position: relative;
- width: 100%;
- max-height: 100%;
- overflow-y: auto;
-}
-
-.config-debug-option {
- color: TextDim;
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out;
- border-bottom-width: 1.1dp;
- border-bottom-color: BorderSoft;
- display: block;
- position: relative;
- flex-direction: column;
- width: 100%;
- height: auto;
- padding: 12dp 4dp;
- background-color: rgba(0, 0, 0, 0);
-}
-.config-debug-option svg {
- image-color: TextDim;
-}
-.config-debug-option svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.config-debug-option:focus:not(:disabled, [disabled]), .config-debug-option:focus-visible:not(:disabled, [disabled]), .config-debug-option:hover:not(:disabled, [disabled]) {
- color: Text;
- background-color: BGOverlay;
-}
-.config-debug-option:focus:not(:disabled, [disabled]) svg, .config-debug-option:focus-visible:not(:disabled, [disabled]) svg, .config-debug-option:hover:not(:disabled, [disabled]) svg {
- image-color: Text;
-}
-.config-debug-option:disabled, .config-debug-option[disabled] {
- opacity: 0.5;
-}
-.config-debug-option .icon-button {
- margin-left: 8dp;
-}
-
-.config-debug__option-split {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
-}
-
-.config-debug-option__label {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- padding: 4dp 16dp 12dp;
- width: auto;
- height: auto;
- white-space: nowrap;
-}
-
-.config-debug__option-controls {
- display: block;
- position: relative;
- flex: 1 1 auto;
- height: auto;
- width: auto;
- max-width: 800dp;
- padding: 0 12dp;
-}
-
-.config-debug__option-trigger {
- flex: 1 1 auto;
-}
-
-.config-debug__select-wrapper {
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- flex: 1 1 100%;
- width: auto;
- max-width: 800dp;
- height: auto;
- padding: 4dp;
-}
-.config-debug__select-wrapper .config-debug__select-label {
- padding-right: 16dp;
- flex: auto;
- width: 196dp;
-}
-.config-debug__select-wrapper .config-debug__select-label > div {
- display: inline;
- width: auto;
- height: auto;
-}
-.config-debug__select-wrapper input {
- display: block;
- position: relative;
- box-sizing: border-box;
- padding: 0;
- flex: 1 1 100%;
- width: auto;
- height: 20dp;
- margin: auto 0;
-}
-.config-debug__select-wrapper select {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out, opacity 0.05s linear-in-out, border-color 0.05s linear-in-out;
- border-width: 1.1dp;
- border-color: WhiteA50;
- display: block;
- position: relative;
- box-sizing: border-box;
- padding: 0;
- flex: 1 1 100%;
- width: auto;
- height: 48dp;
- border-radius: 12dp;
- background-color: WhiteA5;
- cursor: pointer;
- align-items: center;
- justify-content: flex-start;
- padding: 14dp;
-}
-.config-debug__select-wrapper select svg {
- transition: image-color 0.05s linear-in-out, background-color 0.05s linear-in-out;
-}
-.config-debug__select-wrapper select:hover, .config-debug__select-wrapper select:focus {
- border-width: 1.1dp;
- border-color: WhiteA80;
- background-color: WhiteA20;
-}
-.config-debug__select-wrapper select selectvalue {
- display: inline;
- margin: auto 0;
- height: auto;
-}
-.config-debug__select-wrapper select selectbox {
- border-width: 1.1dp;
- border-color: WhiteA80;
- background-color: Background3;
- padding: 4dp 0;
- margin-top: 2dp;
- border-radius: 12dp;
-}
-.config-debug__select-wrapper select selectbox option {
- transition: color 0.05s linear-in-out, background-color 0.05s linear-in-out;
- padding: 8dp 12dp;
- background-color: Transparent;
- color: TextDim;
- font-weight: 400;
-}
-.config-debug__select-wrapper select selectbox option:hover, .config-debug__select-wrapper select selectbox option:focus {
- background-color: WhiteA20;
-}
-.config-debug__select-wrapper select selectbox option:hover:not(:checked) {
- cursor: pointer;
-}
-.config-debug__select-wrapper select selectbox option:checked {
- color: White;
- background-color: WhiteA5;
-}
-
-.rmlui-window {
- opacity: 1;
-}
-.rmlui-window--hidden {
- opacity: 0;
-}
-.rmlui-window:not([mouse-active]) {
- pointer-events: none;
-}
-
-*, *:before, *:after {
- box-sizing: border-box;
-}
-
-button {
- background-color: PrimaryD;
-}
-
-@keyframes blue-pulse {
- 0% {
- color: Secondary;
- }
- 50% {
- color: SecondaryL;
- }
- 100% {
- color: Secondary;
- }
-}
-@keyframes blue-pulse-with-border {
- 0% {
- border-color: Secondary;
- color: Secondary;
- }
- 50% {
- border-color: SecondaryL;
- color: SecondaryL;
- }
- 100% {
- border-color: Secondary;
- color: Secondary;
- }
-}
-@keyframes blue-pulse-background {
- 0% {
- background-color: Secondary;
- }
- 50% {
- background-color: SecondaryL;
- }
- 100% {
- background-color: Secondary;
- }
-}
+.rml-needs-something-in-this-file {}
diff --git a/assets/rml.rcss b/assets/rml.rcss
deleted file mode 100644
index 0905b24..0000000
--- a/assets/rml.rcss
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-* Default styles for all the basic elements.
-*/
-
-div
-{
- display: block;
-}
-
-p
-{
- display: block;
-}
-
-h1
-{
- display: block;
-}
-
-em
-{
- font-style: italic;
-}
-
-strong
-{
- font-weight: bold;
-}
-
-select
-{
- text-align: left;
-}
-
-tabset tabs
-{
- display: block;
-}
-
-table {
- box-sizing: border-box;
- display: table;
-}
-tr {
- box-sizing: border-box;
- display: table-row;
-}
-td {
- box-sizing: border-box;
- display: table-cell;
-}
-col {
- box-sizing: border-box;
- display: table-column;
-}
-colgroup {
- display: table-column-group;
-}
-thead, tbody, tfoot {
- display: table-row-group;
-}
diff --git a/assets/scss/.nvmrc b/assets/scss/.nvmrc
deleted file mode 100644
index b7586d6..0000000
--- a/assets/scss/.nvmrc
+++ /dev/null
@@ -1 +0,0 @@
-iron
diff --git a/assets/scss/.stylelintrc b/assets/scss/.stylelintrc
deleted file mode 100644
index 60ad85f..0000000
--- a/assets/scss/.stylelintrc
+++ /dev/null
@@ -1,99 +0,0 @@
-{
- "extends": [
- "stylelint-config-recommended",
- "stylelint-config-standard",
- "stylelint-config-sass-guidelines",
- "stylelint-config-property-sort-order-smacss",
- "stylelint-config-standard-scss"
- ],
- "plugins": ["stylelint-scss"],
- "overrides": [{
- "files": ["**/*.scss"],
- "customSyntax": "postcss-scss"
- }],
- "rules": {
- "no-descending-specificity": null,
- "declaration-empty-line-before": null,
- "declaration-colon-newline-after": null,
- "declaration-block-no-duplicate-properties": true,
- "declaration-block-trailing-semicolon": null,
- "declaration-no-important": true,
- "declaration-property-value-disallowed-list": {
- "/^transition/": ["/all/"]
- },
- "block-closing-brace-newline-after": null,
- "max-empty-lines": null,
- "selector-list-comma-newline-after": null,
- "at-rule-empty-line-before": null,
- "at-rule-semicolon-newline-after": null,
- "selector-pseudo-element-colon-notation": "single",
- "color-no-hex": true,
- "function-url-quotes": "always",
- "max-nesting-depth": [
- 4,
- {
- "ignoreAtRules": ["each", "media", "supports", "include"],
- "severity": "warning"
- }
- ],
- "number-leading-zero": null,
- "order/order": [
- [
- "custom-properties",
- "dollar-variables",
- {
- "type": "at-rule",
- "name": "extend"
- },
- {
- "type": "at-rule",
- "name": "include"
- },
- "declarations",
- "rules"
- ]
- ],
- "order/properties-alphabetical-order": null,
- "property-no-vendor-prefix": [
- true,
- {
- "severity": "warning"
- }
- ],
- "value-no-vendor-prefix": [
- true,
- {
- "severity": "warning"
- }
- ],
- "scss/selector-no-redundant-nesting-selector": null,
- "selector-class-pattern": null,
- "selector-max-compound-selectors": [
- 4,
- {
- "severity": "warning"
- }
- ],
- "selector-no-qualifying-type": null,
- "string-quotes": null,
- "max-line-length": null,
- "keyframes-name-pattern": null,
- "scss/double-slash-comment-empty-line-before": null,
- "scss/double-slash-comment-whitespace-inside": null,
- "scss/dollar-variable-empty-line-before": null,
- "scss/dollar-variable-pattern": "[a-z-]",
- "scss/at-import-partial-extension": null,
- "declaration-block-no-redundant-longhand-properties": null,
- "color-function-notation": null,
- "alpha-value-notation": null,
- "at-rule-no-unknown": null,
- "property-no-unknown": null,
- "scss/at-rule-no-unknown": true,
- "selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["selected"] }],
- "font-family-no-missing-generic-family-keyword": null,
- "scss/no-global-function-names": null,
- "unit-no-unknown": [true, { "ignoreUnits": ["dp"] }],
- "selector-type-no-unknown": [true, { "ignore": ["custom-elements", "default-namespace"] }],
- "value-keyword-case": null
- }
-}
diff --git a/assets/scss/main.scss b/assets/scss/main.scss
deleted file mode 100644
index 9d03ad3..0000000
--- a/assets/scss/main.scss
+++ /dev/null
@@ -1,2 +0,0 @@
-@import "styles/base";
-@import "styles/global";
diff --git a/assets/scss/package-lock.json b/assets/scss/package-lock.json
deleted file mode 100644
index 78ab77a..0000000
--- a/assets/scss/package-lock.json
+++ /dev/null
@@ -1,2261 +0,0 @@
-{
- "name": "mmrecomp-ui-scss",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "mmrecomp-ui-scss",
- "version": "1.0.0",
- "license": "ISC",
- "dependencies": {
- "sass": "^1.75.0"
- },
- "devDependencies": {
- "postcss-scss": "^4.0.9",
- "stylelint": "^15.11.0",
- "stylelint-config-property-sort-order-smacss": "^9.1.0",
- "stylelint-config-sass-guidelines": "^10.0.0",
- "stylelint-config-scss": "^1.0.0-security",
- "stylelint-config-standard": "^34.0.0",
- "stylelint-config-standard-scss": "^11.1.0",
- "stylelint-scss": "^5.3.1"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.23.5",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
- "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.23.4",
- "chalk": "^2.4.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.20",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
- "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.23.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
- "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.22.20",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@csstools/css-parser-algorithms": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz",
- "integrity": "sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/csstools"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/csstools"
- }
- ],
- "engines": {
- "node": "^14 || ^16 || >=18"
- },
- "peerDependencies": {
- "@csstools/css-tokenizer": "^2.2.1"
- }
- },
- "node_modules/@csstools/css-tokenizer": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.1.tgz",
- "integrity": "sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/csstools"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/csstools"
- }
- ],
- "engines": {
- "node": "^14 || ^16 || >=18"
- }
- },
- "node_modules/@csstools/media-query-list-parser": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.5.tgz",
- "integrity": "sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/csstools"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/csstools"
- }
- ],
- "engines": {
- "node": "^14 || ^16 || >=18"
- },
- "peerDependencies": {
- "@csstools/css-parser-algorithms": "^2.3.2",
- "@csstools/css-tokenizer": "^2.2.1"
- }
- },
- "node_modules/@csstools/selector-specificity": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz",
- "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/csstools"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/csstools"
- }
- ],
- "engines": {
- "node": "^14 || ^16 || >=18"
- },
- "peerDependencies": {
- "postcss-selector-parser": "^6.0.13"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@types/minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
- "dev": true
- },
- "node_modules/@types/normalize-package-data": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
- "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
- "dev": true
- },
- "node_modules/ajv": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
- "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/arrify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
- "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/astral-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
- "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/balanced-match": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
- "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
- "dev": true
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/brace-expansion/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/camelcase-keys": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz",
- "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==",
- "dev": true,
- "dependencies": {
- "camelcase": "^6.3.0",
- "map-obj": "^4.1.0",
- "quick-lru": "^5.1.1",
- "type-fest": "^1.2.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/colord": {
- "version": "2.9.3",
- "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
- "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
- "dev": true
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/cosmiconfig": {
- "version": "8.3.6",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
- "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
- "dev": true,
- "dependencies": {
- "import-fresh": "^3.3.0",
- "js-yaml": "^4.1.0",
- "parse-json": "^5.2.0",
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/d-fischer"
- },
- "peerDependencies": {
- "typescript": ">=4.9.5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/css-functions-list": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz",
- "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==",
- "dev": true,
- "engines": {
- "node": ">=12 || >=16"
- }
- },
- "node_modules/css-property-sort-order-smacss": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/css-property-sort-order-smacss/-/css-property-sort-order-smacss-2.2.0.tgz",
- "integrity": "sha512-nXutswsivIEBOrPo/OZw2KQjFPLvtg68aovJf6Kqrm3L6FmTvvFPaeDrk83hh0+pRJGuP3PeKJwMS0E6DFipdQ==",
- "dev": true
- },
- "node_modules/css-tree": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
- "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
- "dev": true,
- "dependencies": {
- "mdn-data": "2.0.30",
- "source-map-js": "^1.0.1"
- },
- "engines": {
- "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
- }
- },
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decamelize": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz",
- "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/decamelize-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
- "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
- "dev": true,
- "dependencies": {
- "decamelize": "^1.1.0",
- "map-obj": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/decamelize-keys/node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/decamelize-keys/node_modules/map-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
- "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fastest-levenshtein": {
- "version": "1.0.16",
- "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
- "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
- "dev": true,
- "engines": {
- "node": ">= 4.9.1"
- }
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/file-entry-cache": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz",
- "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==",
- "dev": true,
- "dependencies": {
- "flat-cache": "^3.2.0"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat-cache": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
- "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
- "dev": true,
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
- "dev": true
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/global-modules": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
- "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
- "dev": true,
- "dependencies": {
- "global-prefix": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/global-prefix": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
- "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
- "dev": true,
- "dependencies": {
- "ini": "^1.3.5",
- "kind-of": "^6.0.2",
- "which": "^1.3.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/globjoin": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
- "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
- "dev": true
- },
- "node_modules/hard-rejection": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
- "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
- "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/hosted-git-info": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
- "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/html-tags": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
- "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ignore": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
- "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/immutable": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
- "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw=="
- },
- "node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/import-fresh/node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/import-lazy": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
- "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/indent-string": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz",
- "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true
- },
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
- "dev": true,
- "dependencies": {
- "hasown": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-plain-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
- "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true
- },
- "node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/known-css-properties": {
- "version": "0.29.0",
- "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz",
- "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==",
- "dev": true
- },
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash.truncate": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
- "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
- "dev": true
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/map-obj": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
- "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/mathml-tag-names": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
- "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/mdn-data": {
- "version": "2.0.30",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
- "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
- "dev": true
- },
- "node_modules/meow": {
- "version": "10.1.5",
- "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz",
- "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==",
- "dev": true,
- "dependencies": {
- "@types/minimist": "^1.2.2",
- "camelcase-keys": "^7.0.0",
- "decamelize": "^5.0.0",
- "decamelize-keys": "^1.1.0",
- "hard-rejection": "^2.1.0",
- "minimist-options": "4.1.0",
- "normalize-package-data": "^3.0.2",
- "read-pkg-up": "^8.0.0",
- "redent": "^4.0.0",
- "trim-newlines": "^4.0.2",
- "type-fest": "^1.2.2",
- "yargs-parser": "^20.2.9"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/min-indent": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
- "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minimist-options": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
- "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
- "dev": true,
- "dependencies": {
- "arrify": "^1.0.1",
- "is-plain-obj": "^1.1.0",
- "kind-of": "^6.0.3"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/normalize-package-data": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
- "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
- "dev": true,
- "dependencies": {
- "hosted-git-info": "^4.0.1",
- "is-core-module": "^2.5.0",
- "semver": "^7.3.4",
- "validate-npm-package-license": "^3.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.32",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
- "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-media-query-parser": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
- "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
- "dev": true
- },
- "node_modules/postcss-resolve-nested-selector": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
- "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==",
- "dev": true
- },
- "node_modules/postcss-safe-parser": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
- "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
- "dev": true,
- "engines": {
- "node": ">=12.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.3.3"
- }
- },
- "node_modules/postcss-scss": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz",
- "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss-scss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "engines": {
- "node": ">=12.0"
- },
- "peerDependencies": {
- "postcss": "^8.4.29"
- }
- },
- "node_modules/postcss-selector-parser": {
- "version": "6.0.13",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
- "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postcss-sorting": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz",
- "integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==",
- "dev": true,
- "peerDependencies": {
- "postcss": "^8.4.20"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/quick-lru": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
- "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/read-pkg": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz",
- "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==",
- "dev": true,
- "dependencies": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^3.0.2",
- "parse-json": "^5.2.0",
- "type-fest": "^1.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/read-pkg-up": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz",
- "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==",
- "dev": true,
- "dependencies": {
- "find-up": "^5.0.0",
- "read-pkg": "^6.0.0",
- "type-fest": "^1.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/redent": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz",
- "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==",
- "dev": true,
- "dependencies": {
- "indent-string": "^5.0.0",
- "strip-indent": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/sass": {
- "version": "1.75.0",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.75.0.tgz",
- "integrity": "sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==",
- "dependencies": {
- "chokidar": ">=3.0.0 <4.0.0",
- "immutable": "^4.0.0",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/slice-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
- "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
- "node_modules/slice-ansi/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/slice-ansi/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/slice-ansi/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/spdx-correct": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
- "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
- "dev": true,
- "dependencies": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
- },
- "node_modules/spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "dependencies": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-license-ids": {
- "version": "3.0.16",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
- "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
- "dev": true
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-indent": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz",
- "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==",
- "dev": true,
- "dependencies": {
- "min-indent": "^1.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/style-search": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
- "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
- "dev": true
- },
- "node_modules/stylelint": {
- "version": "15.11.0",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz",
- "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==",
- "dev": true,
- "dependencies": {
- "@csstools/css-parser-algorithms": "^2.3.1",
- "@csstools/css-tokenizer": "^2.2.0",
- "@csstools/media-query-list-parser": "^2.1.4",
- "@csstools/selector-specificity": "^3.0.0",
- "balanced-match": "^2.0.0",
- "colord": "^2.9.3",
- "cosmiconfig": "^8.2.0",
- "css-functions-list": "^3.2.1",
- "css-tree": "^2.3.1",
- "debug": "^4.3.4",
- "fast-glob": "^3.3.1",
- "fastest-levenshtein": "^1.0.16",
- "file-entry-cache": "^7.0.0",
- "global-modules": "^2.0.0",
- "globby": "^11.1.0",
- "globjoin": "^0.1.4",
- "html-tags": "^3.3.1",
- "ignore": "^5.2.4",
- "import-lazy": "^4.0.0",
- "imurmurhash": "^0.1.4",
- "is-plain-object": "^5.0.0",
- "known-css-properties": "^0.29.0",
- "mathml-tag-names": "^2.1.3",
- "meow": "^10.1.5",
- "micromatch": "^4.0.5",
- "normalize-path": "^3.0.0",
- "picocolors": "^1.0.0",
- "postcss": "^8.4.28",
- "postcss-resolve-nested-selector": "^0.1.1",
- "postcss-safe-parser": "^6.0.0",
- "postcss-selector-parser": "^6.0.13",
- "postcss-value-parser": "^4.2.0",
- "resolve-from": "^5.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "style-search": "^0.1.0",
- "supports-hyperlinks": "^3.0.0",
- "svg-tags": "^1.0.0",
- "table": "^6.8.1",
- "write-file-atomic": "^5.0.1"
- },
- "bin": {
- "stylelint": "bin/stylelint.mjs"
- },
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/stylelint"
- }
- },
- "node_modules/stylelint-config-property-sort-order-smacss": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-property-sort-order-smacss/-/stylelint-config-property-sort-order-smacss-9.1.0.tgz",
- "integrity": "sha512-TijYeDoDgHAFjpn9NnziQrmUCGrm2AM4e1HzsdI2mCWBRkQRuewc343YqDwdFgQ5eHoMZ3JRL02i72W3vktuDA==",
- "dev": true,
- "dependencies": {
- "css-property-sort-order-smacss": "~2.2.0",
- "stylelint-order": "^6.0.2"
- },
- "peerDependencies": {
- "stylelint": "^14.0.0 || ^15.0.0"
- }
- },
- "node_modules/stylelint-config-recommended": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz",
- "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==",
- "dev": true,
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- },
- "peerDependencies": {
- "stylelint": "^15.10.0"
- }
- },
- "node_modules/stylelint-config-recommended-scss": {
- "version": "13.1.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-13.1.0.tgz",
- "integrity": "sha512-8L5nDfd+YH6AOoBGKmhH8pLWF1dpfY816JtGMePcBqqSsLU+Ysawx44fQSlMOJ2xTfI9yTGpup5JU77c17w1Ww==",
- "dev": true,
- "dependencies": {
- "postcss-scss": "^4.0.9",
- "stylelint-config-recommended": "^13.0.0",
- "stylelint-scss": "^5.3.0"
- },
- "peerDependencies": {
- "postcss": "^8.3.3",
- "stylelint": "^15.10.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- }
- }
- },
- "node_modules/stylelint-config-sass-guidelines": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-sass-guidelines/-/stylelint-config-sass-guidelines-10.0.0.tgz",
- "integrity": "sha512-+Rr2Dd4b72CWA4qoj1Kk+y449nP/WJsrD0nzQAWkmPPIuyVcy2GMIcfNr0Z8JJOLjRvtlkKxa49FCNXMePBikQ==",
- "dev": true,
- "dependencies": {
- "postcss-scss": "^4.0.6",
- "stylelint-scss": "^4.4.0"
- },
- "engines": {
- "node": "^14.13.1 || >=16.13.0 || >=18.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.4.21",
- "stylelint": "^15.2.0"
- }
- },
- "node_modules/stylelint-config-sass-guidelines/node_modules/stylelint-scss": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.7.0.tgz",
- "integrity": "sha512-TSUgIeS0H3jqDZnby1UO1Qv3poi1N8wUYIJY6D1tuUq2MN3lwp/rITVo0wD+1SWTmRm0tNmGO0b7nKInnqF6Hg==",
- "dev": true,
- "dependencies": {
- "postcss-media-query-parser": "^0.2.3",
- "postcss-resolve-nested-selector": "^0.1.1",
- "postcss-selector-parser": "^6.0.11",
- "postcss-value-parser": "^4.2.0"
- },
- "peerDependencies": {
- "stylelint": "^14.5.1 || ^15.0.0"
- }
- },
- "node_modules/stylelint-config-scss": {
- "version": "1.0.0-security",
- "resolved": "https://registry.npmjs.org/stylelint-config-scss/-/stylelint-config-scss-1.0.0-security.tgz",
- "integrity": "sha512-8Pgul2mNpzTeK2KCuyV5RcDC1BgzWzU7dCLVJWuxpkKgmxrMqCvjqgyosaKbAVZy2AiaMU0zfHBt7prg7/NaxA==",
- "dev": true
- },
- "node_modules/stylelint-config-standard": {
- "version": "34.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz",
- "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==",
- "dev": true,
- "dependencies": {
- "stylelint-config-recommended": "^13.0.0"
- },
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- },
- "peerDependencies": {
- "stylelint": "^15.10.0"
- }
- },
- "node_modules/stylelint-config-standard-scss": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-11.1.0.tgz",
- "integrity": "sha512-5gnBgeNTgRVdchMwiFQPuBOtj9QefYtfXiddrOMJA2pI22zxt6ddI2s+e5Oh7/6QYl7QLJujGnaUR5YyGq72ow==",
- "dev": true,
- "dependencies": {
- "stylelint-config-recommended-scss": "^13.1.0",
- "stylelint-config-standard": "^34.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.3.3",
- "stylelint": "^15.10.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- }
- }
- },
- "node_modules/stylelint-order": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.3.tgz",
- "integrity": "sha512-1j1lOb4EU/6w49qZeT2SQVJXm0Ht+Qnq9GMfUa3pMwoyojIWfuA+JUDmoR97Bht1RLn4ei0xtLGy87M7d29B1w==",
- "dev": true,
- "dependencies": {
- "postcss": "^8.4.21",
- "postcss-sorting": "^8.0.2"
- },
- "peerDependencies": {
- "stylelint": "^14.0.0 || ^15.0.0"
- }
- },
- "node_modules/stylelint-scss": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-5.3.1.tgz",
- "integrity": "sha512-5I9ZDIm77BZrjOccma5WyW2nJEKjXDd4Ca8Kk+oBapSO4pewSlno3n+OyimcyVJJujQZkBN2D+xuMkIamSc6hA==",
- "dev": true,
- "dependencies": {
- "known-css-properties": "^0.29.0",
- "postcss-media-query-parser": "^0.2.3",
- "postcss-resolve-nested-selector": "^0.1.1",
- "postcss-selector-parser": "^6.0.13",
- "postcss-value-parser": "^4.2.0"
- },
- "peerDependencies": {
- "stylelint": "^14.5.1 || ^15.0.0"
- }
- },
- "node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/supports-hyperlinks": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
- "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0",
- "supports-color": "^7.0.0"
- },
- "engines": {
- "node": ">=14.18"
- }
- },
- "node_modules/supports-hyperlinks/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-hyperlinks/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/svg-tags": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
- "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
- "dev": true
- },
- "node_modules/table": {
- "version": "6.8.1",
- "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
- "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
- "dev": true,
- "dependencies": {
- "ajv": "^8.0.1",
- "lodash.truncate": "^4.4.2",
- "slice-ansi": "^4.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/trim-newlines": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz",
- "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/type-fest": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
- "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "dependencies": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/write-file-atomic": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
- "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
- "dev": true,
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "node_modules/yargs-parser": {
- "version": "20.2.9",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
- "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- }
- }
-}
diff --git a/assets/scss/package.json b/assets/scss/package.json
deleted file mode 100644
index 1055122..0000000
--- a/assets/scss/package.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "name": "mmrecomp-ui-scss",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "start": "npm run watch",
- "watch": "sass --no-source-map --no-charset --style=compressed main.scss ..\\recomp.rcss --watch",
- "watch:debug": "sass --no-source-map --no-charset main.scss ..\\recomp.rcss --watch",
- "build": "sass --no-source-map --no-charset --style=compressed main.scss ..\\recomp.rcss",
- "build:debug": "sass --no-source-map --no-charset main.scss ..\\recomp.rcss",
- "lint": "stylelint '.\\**\\*.scss'"
- },
- "author": "",
- "license": "ISC",
- "devDependencies": {
- "postcss-scss": "^4.0.9",
- "stylelint": "^15.11.0",
- "stylelint-config-property-sort-order-smacss": "^9.1.0",
- "stylelint-config-sass-guidelines": "^10.0.0",
- "stylelint-config-scss": "^1.0.0-security",
- "stylelint-config-standard": "^34.0.0",
- "stylelint-config-standard-scss": "^11.1.0",
- "stylelint-scss": "^5.3.1"
- },
- "dependencies": {
- "sass": "^1.75.0"
- }
-}
diff --git a/assets/scss/styles/base.scss b/assets/scss/styles/base.scss
deleted file mode 100644
index 88e158e..0000000
--- a/assets/scss/styles/base.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-@use 'sass:math';
-@import "./functions/spacing";
-@import "./vars/spacing";
-@import "./vars/colors";
-@import "./vars/borders";
-@import "./vars/gradients";
-@import "./vars/transitions";
-@import "./vars/animations";
-@import "./mixins/typography";
-@import "./mixins/transitions";
-@import "./mixins/helpers";
diff --git a/assets/scss/styles/components/BottomLeft.scss b/assets/scss/styles/components/BottomLeft.scss
deleted file mode 100644
index 28821c8..0000000
--- a/assets/scss/styles/components/BottomLeft.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-@use 'sass:math';
-
-.bottom-left {
- display: flex;
- position: absolute;
- bottom: space(4);
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- max-width: space($base-modal-max-width);
- height: auto;
- margin: 0 space(4);
-}
diff --git a/assets/scss/styles/components/Button.scss b/assets/scss/styles/components/Button.scss
deleted file mode 100644
index b7f8086..0000000
--- a/assets/scss/styles/components/Button.scss
+++ /dev/null
@@ -1,81 +0,0 @@
-@use 'sass:color';
-
-@mixin create-button-variation($base-col, $base-col-05, $base-col-20, $base-col-30, $base-col-80) {
- border-color: $base-col-80;
- background-color: $base-col-05;
- color: $color-text-dim;
-
- &:focus, &:hover {
- border-color: $base-col;
- background-color: $base-col-30;
- color: $color-text;
- }
-
- &:disabled,&[disabled] {
- color: $color-text-inactive;
- }
-
- &:active {
- background-color: $base-col-20;
- color: $color-text-active;
- }
-}
-
-.button {
- @extend %label-md;
- @extend %nav-all;
- @include create-button-variation($color-primary, $color-primary-a5, $color-primary-a20, $color-primary-a30, $color-primary-a80);
- @include trans-colors;
-
- display: block;
- width: auto;
- height: auto;
- // leave 1dp room for border expansion
- padding: space(24 - 1);
- border-width: $border-width-thickness;
-
- border-radius: $border-radius-md;
-
- // Setting it by default for convenience
- &--primary {
- @include create-button-variation($color-primary, $color-primary-a5, $color-primary-a20, $color-primary-a30, $color-primary-a80);
- }
-
- &--large {
- @extend %label-lg;
- }
-
- &--secondary {
- @include create-button-variation($color-secondary, $color-secondary-a5, $color-secondary-a20, $color-secondary-a30, $color-secondary-a80);
- }
-
- &--tertiary {
- @include create-button-variation($color-text, $color-text-a5, $color-text-a20, $color-text-a30, $color-text-a80);
- }
-
- &--success {
- @include create-button-variation($color-success, $color-success-a5, $color-success-a20, $color-success-a30, $color-success-a80);
- }
-
- &--danger {
- @include create-button-variation($color-danger, $color-danger-a5, $color-danger-a20, $color-danger-a30, $color-danger-a80);
- }
-
- &--warning {
- @include create-button-variation($color-warning, $color-warning-a5, $color-warning-a20, $color-warning-a30, $color-warning-a80);
- }
-
- &:not([disabled]) {
- @extend %nav-all;
- cursor: pointer;
- }
-
- &:disabled,&[disabled] {
- opacity: 0.5;
- }
-
- &__label {
- width: auto;
- height: auto;
- }
-}
diff --git a/assets/scss/styles/components/CenteredPage.scss b/assets/scss/styles/components/CenteredPage.scss
deleted file mode 100644
index a724472..0000000
--- a/assets/scss/styles/components/CenteredPage.scss
+++ /dev/null
@@ -1,73 +0,0 @@
-@use 'sass:math';
-
-.centered-page {
- display: flex;
- // visibility: hidden;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- padding: space($page-margin);
- background-color: $color-border-soft;
-}
-
-.centered-page__modal {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: space($base-modal-max-width);
- height: 100%;
- margin: auto;
- border-width: $border-width-thickness;
- border-radius: $border-radius-modal;
- border-color: $color-border;
- background: $color-modal-overlay;
-
- > .tabs {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: space($base-modal-max-width);
- height: 100%;
- margin: auto;
- }
-
- panels {
- flex: 1 1 100%;
- }
-}
-
-.centered-page__controls {
- display: flex;
- position: absolute;
- bottom: space(24);
- flex-direction: row;
- align-items: center;
- justify-content: center;
- width: 100%;
- max-width: space($base-modal-max-width);
- height: auto;
- margin: 0 auto;
-
- > label {
- @extend %label-sm;
- display: inline-block;
- align-items: center;
- justify-content: space-between;
- width: auto;
- height: space(24);
-
- &:not(:last-child) {
- margin-right: space(40);
- }
-
- > span:first-child {
- margin-right: space(4);
- }
- }
-}
diff --git a/assets/scss/styles/components/Config.scss b/assets/scss/styles/components/Config.scss
deleted file mode 100644
index 54c6e1d..0000000
--- a/assets/scss/styles/components/Config.scss
+++ /dev/null
@@ -1,101 +0,0 @@
-
-.config__icon-buttons {
- display: flex;
- position: absolute;
- top: space(8);
- right: space(0);
- flex-direction: row;
- align-items: center;
- justify-content: flex-end;
- width: auto;
-
- .icon-button {
- margin: 0 space(8);
- }
-}
-
-.config__form {
- @include border-top($color-border-soft);
- display: flex;
- flex: 1 1 100%;
- flex-direction: column;
- justify-content: space-between;
- width: 100%;
- height: 100%;
- border-bottom-right-radius: $border-radius-modal;
- border-bottom-left-radius: $border-radius-modal;
-}
-
-.config__wrapper {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: space(16);
- border-radius: 0dp;
- border-bottom-right-radius: $border-radius-modal;
- border-bottom-left-radius: $border-radius-modal;
- background-color: $color-bg-shadow;
- text-align: left;
-
- p {
- @extend %body;
- padding: space(16);
- line-height: space(28);
- white-space: pre-line;
-
- b {
- color: $color-primary;
- }
-
- i {
- color: $color-warning;
- font-style: normal;
- }
- }
-}
-
-.config__hz-wrapper {
- display: flex;
- flex: 1 1 100%;
- flex-direction: row;
- width: 100%;
- height: 100%;
- border-radius: 0dp;
- text-align: left;
-}
-
-.config__header, .config__footer {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- background-color: $color-bg-shadow;
-}
-
-.config__header {
- @include border-bottom($color-border-soft);
- padding: space(12) space(20);
-}
-
-.config__footer {
- @include border-top($color-border-soft);
- padding: space(20) space(20);
- border-bottom-right-radius: $border-radius-modal;
- border-bottom-left-radius: $border-radius-modal;
-}
-
-.config__header-left {
- display: flex;
- flex: 1 1 auto;
- flex-direction: row;
-
- > :not(:first-child) {
- margin-left: space(8);
- }
-}
-
-.config__row {
- display: flex;
- flex-direction: row;
-}
-
diff --git a/assets/scss/styles/components/ConfigDescription.scss b/assets/scss/styles/components/ConfigDescription.scss
deleted file mode 100644
index 2f4966f..0000000
--- a/assets/scss/styles/components/ConfigDescription.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.config-description {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: space(16);
- border-radius: 0dp;
- border-bottom-right-radius: $border-radius-modal;
- border-bottom-left-radius: $border-radius-modal;
- background-color: $color-bg-shadow;
- text-align: left;
-
- &__contents {
- @extend %body;
- padding: space(16);
- line-height: space(28);
- white-space: pre-line;
-
- b {
- color: $color-primary;
- }
-
- i {
- color: $color-warning;
- font-style: normal;
- }
- }
-}
diff --git a/assets/scss/styles/components/ConfigGroup.scss b/assets/scss/styles/components/ConfigGroup.scss
deleted file mode 100644
index 9f6444b..0000000
--- a/assets/scss/styles/components/ConfigGroup.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-
-.config-group {
- position: relative;
-
- &--scrollable {
- flex: 1 1 100%;
- width: auto;
- height: auto;
- padding: 0 0 0 space(16);
-
- .config-group__wrapper {
- max-height: 100%;
- overflow-y: auto;
- }
- }
-
- &__title {
- @extend %label-md;
- color: $color-primary;
-
- &--hidden {
- display: none;
- }
- }
-
- &__wrapper {
- padding: space(16) 0;
- }
-}
diff --git a/assets/scss/styles/components/ConfigOption.scss b/assets/scss/styles/components/ConfigOption.scss
deleted file mode 100644
index 26acd85..0000000
--- a/assets/scss/styles/components/ConfigOption.scss
+++ /dev/null
@@ -1,413 +0,0 @@
-.config-option {
- display: flex;
- flex: 1;
- flex-direction: column;
- align-items: flex-start;
- justify-content: flex-start;
- margin: space(16) space(0) space(24);
-
- &--hz {
- flex-direction: row-reverse;
- align-items: center;
- margin-top: space(4);
- margin-bottom: space(4);
-
- .config-option__title {
- @extend %label-md;
- flex: 1 1 100%;
- }
-
- .config-option__list {
- flex: 1 1 auto;
- width: auto;
- }
-
- &:first-child {
- margin-top: 0;
- }
-
- &:last-child {
- margin-bottom: 0;
- }
- }
-}
-
-.config-option__title {
- @extend %label-md;
- padding: 0 space(12);
-}
-
-.config-option__radio-tabs,
-.config-option__list {
- display: flex;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- height: auto;
- padding: 0;
-
- input:first-of-type {
- nav-left: none;
- }
-
- input:last-of-type {
- nav-right: none;
- }
-
- .config-option__tab-label {
- @extend %label-sm;
- @include trans-colors-opa;
- display: block;
- position: relative;
- height: auto;
- margin: space(4) space(12) 0;
- padding: space(8) 0;
- color: $color-text-inactive;
- tab-index: none;
-
- &:hover {
- color: $color-text;
- cursor: pointer;
- }
- }
-
- .config-option__checkbox-wrapper {
- @include trans-colors-opa;
- width: space(32);
- height: space(32);
- margin: space(4) space(12) 0;
- border-radius: $border-radius-sm;
- opacity: 0.5;
- background-color: $color-bg-overlay;
- cursor: pointer;
-
- &:hover {
- opacity: 1;
- }
-
- &[checked] {
- background-color: $color-a;
- }
- }
-
- .config-option__checkbox {
- @extend %nav-all;
- @include trans-colors-opa;
- visibility: visible;
- width: 0;
- height: 0;
- }
-
- // TODO: Remove & Replace old stylings
- input.radio {
- @extend %nav-all;
- @include trans-colors-opa;
- visibility: visible;
- width: 0;
- height: 0;
-
- &:not(:disabled) {
- &:checked + .config-option__tab-label {
- border-bottom: 1dp;
- border-color: $color-text;
- color: $color-text;
-
- &:hover {
- cursor: default;
- }
- }
-
- .rmlui-window:not([mouse-active]) &:focus + .config-option__tab-label {
- transition: none;
- animation: $focus-anim-border;
- border-color: $color-secondary;
- color: $color-secondary;
- }
-
- &:focus + .config-option__tab-label,
- &:hover + .config-option__tab-label {
- color: $color-text;
- }
- }
-
- &:disabled + .config-option__tab-label {
- opacity: 0.5;
-
- &:hover {
- cursor: default;
- }
- }
- }
-
- input.range slidertrack {
- @include trans-colors;
- height: 2dp;
- margin-top: space(8);
- background-color: $color-border;
- }
-
- input.range sliderbar {
- @include trans-colors;
- width: space(16);
- height: space(16);
- margin-top: space(1);
- margin-right: space(-8);
- margin-left: space(-8);
- transition: background-color $transition-quick;
- border-radius: 8dp;
- background-color: $color-text-dim;
-
- .rmlui-window:not([mouse-active]) &:focus {
- @include border($color-a);
- animation: $focus-anim-bg;
- }
-
- &:hover {
- background-color: $color-text;
- cursor: pointer;
- }
- }
-
- input.range sliderbar:active,
- input.range slidertrack:active + sliderbar {
- background-color: $color-secondary;
- }
-
- input.range sliderarrowdec,
- input.range sliderarrowinc {
- display: none;
- }
-}
-
-.config-option__details {
- @extend %label-xs;
- height: space(18);
- margin: space(14) space(12) 0;
- color: $color-primary;
-}
-
-.config-option-color {
- width: 100%;
- max-width: space(360);
- height: auto;
- margin-top: space(4);
- margin-left: space(12);
- padding: 0;
-
- &__preview-wrapper {
- display: flex;
- flex-direction: row;
- width: 100%;
- height: space(8 * 9);
- }
-
- &__preview-block {
- display: block;
- width: space(8 * 11);
- height: 100%;
- border-width: $border-width-thickness;
- border-radius: $border-radius-lg;
- border-color: $color-border;
- }
-
- &__hsv-wrapper {
- display: flex;
- flex: 1 1 100%;
- flex-direction: column;
- width: auto;
- height: auto;
- padding-left: space(8);
-
- .config-option-range {
- flex: 1 1 auto;
-
- label {
- min-width: space(72);
- }
-
- input {
- flex: 1 1 auto;
- }
- }
- }
-}
-
-.config-option-range {
- display: flex;
- flex-direction: row;
- align-items: flex-start;
- justify-content: flex-start;
- width: 100%;
- max-width: space(360);
- height: auto;
- margin-top: space(4);
- padding: 0;
-
- &__label {
- @extend %label-sm;
-
- display: block;
- width: space(56);
- margin: 0 12dp;
- margin-right: space(16);
- padding: 0;
- color: $color-text;
- tab-index: none;
- }
-
- &__range-input {
- flex: 1;
-
- slidertrack {
- @include trans-colors;
- height: 2dp;
- margin-top: space(8);
- background-color: $color-border;
- }
-
- sliderbar {
- @include trans-colors;
- width: space(16);
- height: space(16);
- margin-top: space(1);
- margin-right: space(-8);
- margin-left: space(-8);
- transition: background-color $transition-quick;
- border-radius: 8dp;
- background-color: $color-text-dim;
-
- .rmlui-window:not([mouse-active]) &:focus {
- @include border($color-a);
- animation: $focus-anim-bg;
- }
-
- &:hover {
- background-color: $color-text;
- cursor: pointer;
- }
- }
-
- sliderbar:active,
- slidertrack:active + sliderbar {
- background-color: $color-secondary;
- }
-
- sliderarrowdec,
- sliderarrowinc {
- display: none;
- }
- }
-
-}
-
-.config-option__range-wrapper {
- max-width: space(360);
- margin-top: space(4);
-}
-
-.config-option__range-label {
- @extend %label-sm;
-
- display: block;
- // flex: 0 0 space(32);
- width: space(56);
- margin: 0 12dp;
- margin-right: space(16);
- padding: 0;
- color: $color-text;
- tab-index: none;
-}
-
-.config-option-dropdown, .config-option-textfield {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- width: auto;
- height: auto;
- padding: space(8) space(24) space(8) space(12);
-
- &__select {
- display: block;
- height: space(48);
- padding: space(14);
- cursor: pointer;
- }
-
- &__wrapper {
- // Cursed guess & check so that this appears to be the same height as the select
- $extra-space: 2;
-
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: 100%;
- height: auto;
- padding: space(0 + $extra-space) 0 space(10 + $extra-space);
- cursor: text;
-
- input {
- width: 100%;
- height: auto;
- vertical-align: middle;
- }
- }
-
- &__select, &__wrapper {
- @extend %body;
- @extend %nav-all;
- @include trans-colors-border;
- @include border($color-white-a50);
- position: relative;
- box-sizing: border-box;
- flex: 1 1 100%;
-
- width: auto;
- border-radius: $border-radius-md;
- background-color: $color-white-a5;
-
- &:hover, &:focus {
- @include border($color-white-a80);
- background-color: $color-white-a20;
- }
-
- selectvalue {
- display: inline;
- height: auto;
- margin: auto 0;
- }
-
- selectbox {
- @include border($color-border);
- margin-top: space(2);
- padding: space(4) 0;
- border-radius: $border-radius-md;
- background-color: $color-background-3;
-
- option {
- @extend %nav-all;
- @include trans-colors;
- padding: space(8) space(12);
- background-color: $color-transparent;
- color: $color-text-dim;
- font-weight: 400;
-
- &:hover, &:focus {
- background-color: $color-white-a20;
- }
-
- &:hover:not(:checked) {
- cursor: pointer;
- }
-
- &:checked {
- background-color: $color-white-a5;
- color: $color-white;
- }
- }
- }
- }
-}
diff --git a/assets/scss/styles/components/ControlOption.scss b/assets/scss/styles/components/ControlOption.scss
deleted file mode 100644
index 16c086e..0000000
--- a/assets/scss/styles/components/ControlOption.scss
+++ /dev/null
@@ -1,170 +0,0 @@
-@use 'sass:color';
-@use 'sass:math';
-
-.control-option {
- @include set-color($color-text-dim);
- @include trans-colors-svg;
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- height: auto;
- padding: space(4) space(16) space(4) space(20);
- border-radius: $border-radius-sm;
- background-color: rgba(0, 0, 0, 0);
-
- &:focus-visible:not(:disabled, [disabled]),
- &:hover:not(:disabled, [disabled]) {
- @include set-color($color-text);
- background-color: $color-bg-overlay;
- }
-
- &:disabled, &[disabled] {
- opacity: 0.5;
- }
-
- &--active {
- // while actively looking for inputs, set styles to the correct slots
- $valid-binding-slots: 0, 1;
- @each $slot in $valid-binding-slots {
- // global attr -> this active row -> binding slot
- [cur-binding-slot="#{$slot}"] & .control-option__binding[bind-slot="#{$slot}"] {
- border-color: $color-danger;
-
- .control-option__binding-icon {
- opacity: 0;
- }
-
- .control-option__binding-recording {
- opacity: 1;
- }
- }
- }
- }
-
- .icon-button {
- flex: 1 1 auto;
- }
-}
-
-.control-option__label {
- @extend %label-md;
- flex: 2 1 space(300);
- height: auto;
- white-space: nowrap;
-}
-
-.control-option__bindings {
- display: flex;
- position: relative;
- flex: 2 1 space(400);
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- height: space(56);
- padding: 0 space(12) 0 space(4);
-}
-
-.control-option__binding {
- @include set-color($color-text-dim);
- @include trans-colors-border;
- display: flex;
- position: relative;
-
- flex: 1 1 100%;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: space(56);
- margin: 0 space(4);
- padding: space(8);
- border-width: $border-width-thickness;
- border-radius: $border-radius-sm;
- border-color: $color-bg-overlay;
- background-color: $color-bg-overlay;
-
- &:focus, &:hover {
- @include set-color($color-text);
- border-color: $color-text;
- background-color: $color-border-soft;
- }
-
- &:active {
- @include set-color($color-text-active);
- }
-
- &:disabled, &[disabled] {
- @include set-color($color-text-dim);
- opacity: 0.5;
- }
-
- &:not([disabled]) {
- @extend %nav-all;
- cursor: pointer;
- }
-}
-
-.control-option__binding-icon {
- @include trans-colors-opa;
- opacity: 1;
-}
-
-@keyframes control-option__binding-recording-scale {
- 0% {
- transform: scale(1);
- }
-
- 50% {
- transform: scale(0.85);
- }
-
- 100% {
- transform: scale(1);
- }
-}
-
-.control-option__binding-recording {
- @include trans-colors-opa;
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
- opacity: 0;
-
- .control-option__binding-circle {
- $rec-size: 24;
-
- width: space($rec-size);
- height: space($rec-size);
- animation: 1.5s sine-in-out infinite control-option__binding-recording-scale;
- border-radius: space($rec-size);
- background-color: $color-danger;
- }
-
- .control-option__binding-edge {
- $edge-size: 36;
- $h-edge-size: math.div($edge-size, 2);
-
- position: absolute;
-
- top: 50%;
- left: 50%;
- width: space($edge-size);
- height: space($edge-size);
-
- transform: translate(-50%, -50%);
-
- > svg.control-option__binding-edge-svg {
- width: space($edge-size);
- height: space($edge-size);
- image-color: $color-danger;
- }
- }
-}
diff --git a/assets/scss/styles/components/IconButton.scss b/assets/scss/styles/components/IconButton.scss
deleted file mode 100644
index fc22121..0000000
--- a/assets/scss/styles/components/IconButton.scss
+++ /dev/null
@@ -1,92 +0,0 @@
-@use 'sass:color';
-
-/*
-
-*/
-@mixin create-icon-button-variation($base-col, $base-col-05, $base-col-20, $base-col-30, $base-col-80) {
- border-color: $base-col-80;
- background-color: $base-col-05;
-
- &:focus, &:hover {
- border-color: $base-col;
- background-color: $base-col-30;
- }
-
- &:active {
- background-color: $base-col-20;
- }
-}
-
-$icon-button-size: 56 - ($border-width-thickness-num * 2);
-
-.icon-button {
- @include set-color($color-text-dim);
- @include trans-colors-border;
-
- display: flex;
- align-items: center;
- justify-content: center;
- width: space($icon-button-size);
- min-width: space($icon-button-size);
- max-width: space($icon-button-size);
- height: space($icon-button-size);
- min-height: space($icon-button-size);
- max-height: space($icon-button-size);
- border-width: $border-width-thickness;
- border-radius: space($icon-button-size * 0.5);
- border-color: $color-transparent;
- background-color: $color-transparent;
-
- &:focus, &:hover {
- @include set-color($color-text);
- background-color: $color-border;
- }
-
- &:active {
- @include set-color($color-text-active);
- background-color: $color-border-soft;
- }
-
- &:disabled,&[disabled] {
- @include set-color($color-text-dim);
- opacity: 0.5;
- }
-
- &:not([disabled]) {
- @extend %nav-all;
- cursor: pointer;
- }
-
- svg {
- width: space(32);
- height: space(32);
- }
-
- &--primary {
- @include create-icon-button-variation($color-primary, $color-primary-a5, $color-primary-a20, $color-primary-a30, $color-primary-a80);
- }
-
- &--secondary {
- @include create-icon-button-variation($color-secondary, $color-secondary-a5, $color-secondary-a20, $color-secondary-a30, $color-secondary-a80);
- }
-
- &--tertiary {
- @include create-icon-button-variation($color-text, $color-text-a5, $color-text-a20, $color-text-a30, $color-text-a80);
- }
-
- &--success {
- @include create-icon-button-variation($color-success, $color-success-a5, $color-success-a20, $color-success-a30, $color-success-a80);
- }
-
- &--danger {
- @include create-icon-button-variation($color-danger, $color-danger-a5, $color-danger-a20, $color-danger-a30, $color-danger-a80);
- }
-
- &--warning {
- @include create-icon-button-variation($color-warning, $color-warning-a5, $color-warning-a20, $color-warning-a30, $color-warning-a80);
- }
-}
diff --git a/assets/scss/styles/components/InputConfig.scss b/assets/scss/styles/components/InputConfig.scss
deleted file mode 100644
index b2cae6d..0000000
--- a/assets/scss/styles/components/InputConfig.scss
+++ /dev/null
@@ -1,347 +0,0 @@
-@use 'sass:math';
-
-// Probably will need to adjust for other langs...
-$mapping-min-width: 80 * 8;
-$visual-max-width: $base-modal-max-width - $mapping-min-width - $scrollbar-width;
-
-.input-config {
- padding: 0;
-}
-
-.input-config__horizontal-split {
- display: flex;
- position: relative;
- flex-direction: row;
- height: 100%;
-}
-
-.input-config__mappings {
- display: block;
- flex: 1 1 auto;
- min-width: space($mapping-min-width);
- height: 100%;
-}
-
-.input-config__mappings-scroll {
- display: block;
- width: 100%;
- max-height: 100%;
- overflow-y: auto;
-}
-
-.input-config__mappings-wrapper {
- padding: space(8);
-}
-
-.input-config__visual-wrapper {
- display: block;
- flex: 1 1 100%;
- width: auto;
- max-width: space($visual-max-width);
- height: auto;
- max-height: space(math.div($visual-max-width, 4) * 3);
- margin: auto 0;
-}
-
-.input-config__visual-aspect {
- position: relative;
- width: 100%;
- margin: auto 0;
- padding-bottom: 75%;
- background-color: $color-bg-shadow;
-}
-
-.input-config__visual {
- display: flex;
- position: absolute;
- top: space(16);
- right: space(16);
- bottom: space(16);
- left: space(16);
- flex-direction: column;
- border-radius: space(108);
- background-color: $color-white-a5;
-}
-
-.input-config__visual-half {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: row;
- padding: 6%;
-
- &--bottom {
- align-items: flex-end;
- justify-content: space-between;
- }
-}
-
-.input-config__visual-quarter-left {
- display: flex;
- flex: 1 1 50%;
- align-items: flex-start;
- justify-content: flex-start;
- width: auto;
-}
-
-.input-config__visual-quarter-right {
- display: flex;
- flex: 1 1 100%;
- align-items: flex-start;
- justify-content: flex-end;
-}
-
-.input-config__visual-stick-wrapper {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
-}
-
-.input-viz {
- @include trans-colors-opa;
- display: flex;
- position: relative;
- align-items: center;
- justify-content: center;
-
- > svg:not(.input-viz__dpad-arrow) {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- }
-
- &__mappings div {
- @extend %prompt-font-sm;
- }
-}
-
-$all-inputs: A,
- B,
- Z,
- START,
- DPAD_UP,
- DPAD_DOWN,
- DPAD_LEFT,
- DPAD_RIGHT,
- L,
- R,
- C_UP,
- C_DOWN,
- C_LEFT,
- C_RIGHT,
- X_AXIS_NEG,
- X_AXIS_POS,
- Y_AXIS_NEG,
- Y_AXIS_POS;
-
-// Show default state while no inputs are active
-[cur-input="NONE"] .input-viz[visual-input] {
- opacity: 1;
-}
-
-@each $inp in $all-inputs {
- .input-viz[visual-input~="#{$inp}"] {
- opacity: 0.25;
-
- [cur-input="#{$inp}"] & {
- opacity: 1.0;
- }
- }
-}
-
-@mixin set-sizes($sz) {
- width: space($sz);
- height: space($sz);
-
- > svg {
- width: space($sz);
- height: space($sz);
- }
-}
-
-.input-viz__button {
- @include set-color($color-text);
-
- &--sm {
- @include set-sizes(64);
- }
-
- &--md {
- @include set-sizes(76);
- }
-
- &--lg {
- @include set-sizes(84);
- }
-
- &--C {
- @include set-svgs-color($color-warning);
- }
-
- &--A {
- @include set-svgs-color($color-a);
- margin-top: auto;
- }
-
- &--B {
- @include set-svgs-color($color-success);
- }
-
- &--Start {
- @include set-svgs-color($color-danger);
- }
-}
-
-.input-viz__Z {
- @include set-svgs-color($color-warning);
- @include set-sizes(136);
-}
-
-$dpad-size: 192;
-
-.input-viz.input-viz__dpad {
- @include set-svgs-color($color-text);
- @include set-sizes($dpad-size);
- position: relative;
-}
-
-$stick-size: 200;
-
-.input-config__visual-stick {
- display: flex;
- position: relative;
- align-items: center;
- justify-content: center;
- width: space($stick-size);
- height: space($stick-size);
- border-radius: space(math.div($stick-size, 2));
- background-color: $color-white-a5;
-}
-
-.input-viz__dpad-split,
-.input-viz__stick-split {
- @include inset-block(0);
- display: flex;
- width: 100%;
- height: 100%;
-
- &--vertical {
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
- }
-
- &--horizontal {
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- }
-
- > div {
- display: flex;
- flex: 1 1 100%;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- }
-}
-
-.input-viz__dpad-split > div {
- width: space(math.div($dpad-size, 3));
- height: space(math.div($dpad-size, 3));
-}
-
-.input-viz__stick-split > div {
- width: space(math.div($stick-size, 3));
- height: space(math.div($stick-size, 3));
-}
-
-.input-viz__dpad-arrow {
- $edge-dist: space(4);
- position: absolute;
- width: space(60);
- height: space(60);
-
- &--up {
- top: $edge-dist;
- margin: 0 auto;
- }
-
- &--down {
- bottom: $edge-dist;
- margin: 0 auto;
- transform: rotate(180deg);
- }
-
- &--left {
- left: $edge-dist;
- margin: auto 0;
- transform: rotate(-90deg);
- }
-
- &--right {
- right: $edge-dist;
- margin: auto 0;
- transform: rotate(90deg);
- }
-}
-
-.input-viz__R {
- @include set-svgs-color($color-white);
- @include set-sizes(96);
-}
-
-.input-viz__L {
- @include set-svgs-color($color-secondary);
- @include set-sizes(136);
-}
-
-.input-config__c-buttons {
- position: relative;
- width: space(76 + 76 + 56);
- height: space(76 + 56);
-
- &-lr, &-du {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- }
-
- &-lr {
- flex-direction: row;
- align-items: flex-start;
- justify-content: space-between;
- }
-
- &-du {
- flex-direction: column-reverse;
- align-items: center;
- justify-content: space-between;
- }
-
- .input-viz {
- &[visual-input="C_UP"] {
- margin-top: space(-32);
- }
- }
-}
-
-.input-config__main-buttons {
- display: flex;
- position: relative;
- flex-direction: row;
- justify-content: space-between;
- width: space(268);
- height: space(128);
- margin-right: space(10);
-}
diff --git a/assets/scss/styles/components/Launcher.scss b/assets/scss/styles/components/Launcher.scss
deleted file mode 100644
index 9f33626..0000000
--- a/assets/scss/styles/components/Launcher.scss
+++ /dev/null
@@ -1,108 +0,0 @@
-
-// TODO: Affect all elements with launcher fade-in
-// @keyframes fade-launcher-in {
-// 0% {
-// opacity: 0;
-// }
-// to {
-// opacity: 1;
-// }
-// }
-
-.launcher {
- display: block;
- position: relative;
- flex-direction: row;
- justify-content: space-between;
- width: 100%;
- height: 100%;
- background-color: $color-background-1;
-}
-
-.launcher__vertical-split {
- display: flex;
- position: absolute;
- top: 0;
- right: 50%;
- bottom: 0;
- left: 0;
- flex-direction: column;
- align-items: flex-start;
- justify-content: space-between;
-
- &--right {
- right: 0;
- left: 50%;
- align-items: flex-end;
- }
-}
-
-
-@keyframes slide-mm-bg-over {
- 0% {
- transform: translateX(space(100));
- }
-
- 100% {
- transform: translateX(space(0));
- }
-}
-
-.launcher__background-wrapper {
- display: flex;
- position: absolute;
- top: -55vw;
- right: -100%;
- bottom: -50vw;
- left: -70vw;
- align-items: center;
- justify-content: flex-start;
- transform: translateX(space(0));
- animation: 25s cubic-out 1 slide-mm-bg-over;
-}
-
-@keyframes fade-mm-in {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 0.1;
- }
-}
-
-.launcher__background-bk {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- width: auto;
- height: 100%;
- animation: 2.5s cubic-in-out 1 fade-mm-in;
- opacity: 0.1;
-}
-
-.launcher__title-quadrant {
- flex: 1 1 auto;
- width: auto;
- height: auto;
- padding-top: space(96);
- padding-left: space(96);
-
- &--right {
- padding-right: space(96);
- padding-left: 0;
- }
-}
-
-.launcher__content-quadrant {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- align-items: flex-start;
- justify-content: flex-end;
- width: 100%;
- height: auto;
- padding: space(32);
-}
diff --git a/assets/scss/styles/components/MenuListItem.scss b/assets/scss/styles/components/MenuListItem.scss
deleted file mode 100644
index 4fb63aa..0000000
--- a/assets/scss/styles/components/MenuListItem.scss
+++ /dev/null
@@ -1,73 +0,0 @@
-
-/*
- Example layout:
-
- - Variants:
- .menu-list-item--right (align to right side)
- - Optional:
- - Coming Soon™
-
-*/
-
-.menu-list-item {
- @include set-color($color-text-dim);
- display: flex;
- flex-direction: row;
- align-items: center;
- width: 100%;
- height: auto;
- padding: space(16);
- border-radius: $border-radius-sm;
- background-color: rgba(0, 0, 0, 0);
- cursor: pointer;
-
- &--right {
- flex-direction: row-reverse;
- align-content: flex-end;
-
- .menu-list-item__bullet {
- margin-left: space(12);
- opacity: 1;
- }
-
- &.menu-list-item:focus:not(:disabled, [disabled]),
- &.menu-list-item:hover:not(:disabled, [disabled]) {
- // decorator: $primary-rl-fade;
- background-color: $color-white-a5;
- }
- }
-
- &:focus:not(:disabled, [disabled]),
- &:hover:not(:disabled, [disabled]) {
- @include set-color($color-primary);
- // decorator: $primary-lr-fade;
- background-color: $color-white-a5;
-
- .menu-list-item__bullet {
- opacity: 1;
- }
- }
-
- &:not(:disabled, [disabled]) {
- @extend %nav-all;
- }
-
- &:disabled, &[disabled] {
- opacity: 0.5;
- tab-index: none;
- cursor: default;
- }
-
-}
-
-.menu-list-item__label {
- @extend %label-lg;
-}
-
-.menu-list-item__bullet {
- margin-right: space(12);
- opacity: 0;
-}
diff --git a/assets/scss/styles/components/Prompt.scss b/assets/scss/styles/components/Prompt.scss
deleted file mode 100644
index d7b4a1d..0000000
--- a/assets/scss/styles/components/Prompt.scss
+++ /dev/null
@@ -1,70 +0,0 @@
-@use 'sass:math';
-
-$prompt-space: 24;
-
-.prompt {
- &__overlay {
- background-color: $color-bg-overlay;
- pointer-events: auto;
- }
-
- &__overlay,
- &__content-wrapper {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- }
-
- &__content-wrapper {
- display: flex;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- align-items: center;
- justify-content: center;
- }
-
- &__content {
- display: flex;
- position: relative;
- flex: 1 1 100%;
- flex-direction: column;
- width: 100%;
- max-width: space(700);
- height: auto;
- margin: auto;
- border-width: $border-width-thickness;
- border-radius: $border-radius-modal;
- border-color: $color-border;
- background: $color-modal-overlay;
-
- h3, p {
- margin: space($prompt-space);
- }
-
- p {
- margin-top: 0;
- }
- }
-
- &__controls {
- display: flex;
- flex-direction: row;
- justify-content: center;
- padding: space($prompt-space) space(math.div($prompt-space, 2));
- border-top-width: $border-width-thickness;
- border-top-color: $color-border-soft;
-
- .button {
- min-width: space(math.div(700, 3));
- margin: 0 space(math.div($prompt-space, 2));
- text-align: center;
- nav-up: none;
- nav-down: none;
- }
- }
-}
diff --git a/assets/scss/styles/components/SubtitleTitle.scss b/assets/scss/styles/components/SubtitleTitle.scss
deleted file mode 100644
index c04def6..0000000
--- a/assets/scss/styles/components/SubtitleTitle.scss
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- Example layout:
-
-
- - Variants:
- .subtitle-title--right (align to right side)
- - Optional:
- - Coming Soon™
-
-*/
-
-.subtitle-title {
- display: block;
- position: relative;
- flex-direction: column;
- align-content: flex-start;
- align-items: flex-start;
- width: auto;
- height: auto;
- padding: 0;
- background-color: rgba(0, 0, 0, 0);
- color: $color-text-dim;
- text-align: left;
- cursor: pointer;
-
- &--right {
- align-content: flex-end;
- }
-
- &--right, &--right > * {
- text-align: right;
- }
-
- &[selected] {
- color: $color-text;
- cursor: default;
- }
-
- &:focus:not(:disabled, [disabled]),
- &:hover:not(:disabled, [disabled], [selected]) {
- color: $color-primary;
- }
-
- &:not(:disabled, [disabled]) {
- @extend %nav-all;
- }
-
- &:disabled, &[disabled] {
- opacity: 0.5;
- cursor: default;
- tab-index: none;
- }
-
- h3 {
- margin-bottom: space(6);
- }
-
- h1 {
- margin-top: space(6);
- }
-
- &__disclaimer {
- @extend %label-sm;
-
- margin-top: space(16);
- }
-}
diff --git a/assets/scss/styles/components/Tabs.scss b/assets/scss/styles/components/Tabs.scss
deleted file mode 100644
index f98c65b..0000000
--- a/assets/scss/styles/components/Tabs.scss
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- Example:
-
- Graphics
-
-
-*/
-
-.tabs tabs {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
-}
-
-.tab {
- @extend %nav-all;
- @extend %header-3;
- display: block;
- position: relative;
- margin: 0;
- padding: space(20) space(24);
- transition: color $transition-quick;
- opacity: 0.9;
- background-color: rgba(0,0,0,0);
- color: $color-text-inactive;
-
- &:selected {
- color: $color-text;
-
- .tab__indicator {
- background-color: $color-border-solid;
- }
-
- &:hover {
- cursor: default;
- }
- }
-
- .rmlui-window:not([mouse-active]) &:focus {
- transition: none;
- animation: $focus-anim-border;
-
- &:selected .tab__indicator {
- animation: $focus-anim-bg;
- }
- }
-
- &:focus, &:hover {
- opacity: 1;
- color: $color-text;
- cursor: pointer;
- }
-}
-
-.tab__indicator {
- position: absolute;
- right: 0;
- bottom: 2dp;
- left: 0;
- height: 2dp;
- background-color: rgba(0, 0, 0, 0);
-}
diff --git a/assets/scss/styles/components/Toggle.scss b/assets/scss/styles/components/Toggle.scss
deleted file mode 100644
index 065f92d..0000000
--- a/assets/scss/styles/components/Toggle.scss
+++ /dev/null
@@ -1,97 +0,0 @@
-@use "sass:math";
-
-$toggle-width: 162;
-$toggle-height: 72;
-
-$toggle-floater-width: 80;
-$toggle-floater-height: 64;
-$toggle-floater-margin: 4;
-$toggle-checked-left-offset: $toggle-width - $toggle-floater-margin - $toggle-floater-width;
-
-.toggle {
- @extend %nav-all;
- @include trans-colors-opa;
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- width: space($toggle-width);
- height: space($toggle-height);
- border-radius: space(math.div($toggle-height, 2));
- opacity: 0.9;
- background: $color-transparent;
- cursor: pointer;
-
- &:hover, &:focus-visible, &:focus {
- opacity: 1;
- background-color: $color-secondary-a30;
- }
-
- &:active {
- opacity: 1;
- background-color: $color-secondary-a5;
- }
-
- .toggle__border {
- @include inner-border-block($color-secondary-l);
- border-radius: space(math.div($toggle-height, 2));
- }
-
- .toggle__floater {
- position: absolute;
- top: 50%;
- left: space($toggle-floater-margin);
- width: space($toggle-floater-width);
- height: space($toggle-floater-height);
- transform: translateY(-50%);
- border-radius: space(math.div($toggle-floater-height, 2));
- background: $color-secondary-d;
- }
-
- &--checked {
- .toggle__floater {
- left: space($toggle-checked-left-offset);
- }
-
- .toggle__icon {
- &.toggle__icon--left {
- opacity: 0.9;
- color: $color-secondary-l;
- }
-
- &.toggle__icon--right {
- opacity: 1.0;
- color: $color-text;
- }
- }
- }
-}
-
-.toggle__icons {
- display: flex;
- position: absolute;
- top: 50%;
- right: space(16);
- left: space(16);
- align-items: center;
- justify-content: space-between;
- height: space(56);
- transform: translateY(-50%);
-}
-
-.toggle__icon {
- @extend %prompt-font-lg;
- @include trans-colors;
- display: flex;
- align-items: center;
- justify-content: center;
- width: space(56);
- height: space(56);
- color: $color-text;
-
- &--right {
- opacity: 1;
- color: $color-secondary-l;
- }
-}
diff --git a/assets/scss/styles/components/_components.scss b/assets/scss/styles/components/_components.scss
deleted file mode 100644
index b4a936e..0000000
--- a/assets/scss/styles/components/_components.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-@import "./CenteredPage";
-@import "./ControlOption";
-@import "./Tabs";
-@import "./Config";
-@import "./ConfigGroup";
-@import "./ConfigOption";
-@import "./ConfigDescription";
-@import "./InputConfig";
-@import "./Button";
-@import "./IconButton";
-@import "./Launcher";
-@import "./MenuListItem";
-@import "./SubtitleTitle";
-@import "./Toggle";
-@import "./BottomLeft";
-@import "./Prompt";
diff --git a/assets/scss/styles/functions/_spacing.scss b/assets/scss/styles/functions/_spacing.scss
deleted file mode 100644
index 437a7ac..0000000
--- a/assets/scss/styles/functions/_spacing.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-
-@function space($amt) {
- @return #{$amt}dp;
-}
diff --git a/assets/scss/styles/global.scss b/assets/scss/styles/global.scss
deleted file mode 100644
index 08242f4..0000000
--- a/assets/scss/styles/global.scss
+++ /dev/null
@@ -1,134 +0,0 @@
-@import "./base";
-
-body
-{
- @extend %body;
- box-sizing: border-box;
- color: $color-text;
- font-family: $font-stack;
-}
-
-@import "./globals/old";
-@import "./globals/scrollbars";
-@import "./components/components";
-@import "./pages/pages";
-
-$font-size: 20dp;
-
-
-.rmlui-window {
- opacity: 1;
-
- &--hidden {
- opacity: 0;
- }
-
- &:not([mouse-active]) {
- pointer-events: none;
- }
-}
-
-.nav-vert {
- @extend %nav-vert;
-}
-
-.nav-horiz {
- @extend %nav-horiz;
-}
-
-.nav-dir {
- @extend %nav-dir;
-}
-
-.nav-foc {
- @extend %nav-foc;
-}
-
-.nav-all {
- @extend %nav-all;
-}
-
-*, *:before, *:after {
- box-sizing: border-box;
-}
-
-h1 {
- @extend %header-1;
-}
-
-h2 {
- @extend %header-2;
-}
-
-h3 {
- @extend %header-3;
-}
-
-.label-lg {
- @extend %label-lg;
-}
-
-.label-md {
- @extend %label-md;
-}
-
-.label-sm {
- @extend %label-sm;
-}
-
-.prompt-font {
- @extend %prompt-font;
-}
-
-.prompt-font-sm {
- @extend %prompt-font-sm;
-}
-
-button {
- background-color: $color-primary-d;
-}
-
-@keyframes blue-pulse {
- 0% {
- color: $color-secondary;
- }
-
- 50% {
- color: $color-secondary-l;
- }
-
- 100% {
- color: $color-secondary;
- }
-}
-
-@keyframes blue-pulse-with-border {
- 0% {
- border-color: $color-secondary;
- color: $color-secondary;
- }
-
- 50% {
- border-color: $color-secondary-l;
- color: $color-secondary-l;
- }
-
- 100% {
- border-color: $color-secondary;
- color: $color-secondary;
- }
-}
-
-@keyframes blue-pulse-background {
- 0% {
- background-color: $color-secondary;
- }
-
- 50% {
- background-color: $color-secondary-l;
- }
-
- 100% {
- background-color: $color-secondary;
- }
-}
diff --git a/assets/scss/styles/globals/_old.scss b/assets/scss/styles/globals/_old.scss
deleted file mode 100644
index 4343b32..0000000
--- a/assets/scss/styles/globals/_old.scss
+++ /dev/null
@@ -1,211 +0,0 @@
-/* stylelint-disable color-no-hex */
-/* stylelint-disable selector-max-id */
-
-* {
- box-sizing:border-box;
-}
-
-hr {
- display:block;
- padding:1.5dp;
- background: $color-background-1;
-}
-
-body {
- color: #fff;
- font-size: 20dp;
- font-style: normal;
- font-weight: normal
-}
-
-/* div {
- focus:none;
- tab-index:none;
-} */
-
-div#window {
- position: relative;
- box-sizing: border-box;
- width: 100%;
- height: 100%;
- border-color: $color-border;
- background-color: $color-background-2;
-}
-
-div#content {
- z-index: 2;
- width: auto;
- height: 100%;
- overflow: hidden auto;
- text-align: center
-}
-
-p {
- text-align: left;
-}
-
-input.submit {
- margin-left: 0
-}
-
-
-input.text,
-input.password {
- box-sizing: border-box;
- height: 31dp;
- padding: 11dp 10dp 0;
- text-align: left;
- cursor: text
-}
-
-textarea {
- padding: 14dp 12dp 10dp;
- text-align: left;
- cursor: text
-}
-
-input.text,
-input.password,
-select,
-textarea {
- /* color: #333; */
-
- /* font-size: 13dp */
- height: auto;
-}
-
-table input.text {
- box-sizing: border-box;
- width: 100%;
- height: auto;
-
- /* height: 18dp; */
- margin: 0;
- border-width: $border-width-thickness;
- border-color: #000;
- background-color: #fff;
- font-size: 15dp;
-
- /* padding: 0 5dp; */
- line-height: 1;
- decorator: none;
-
- /* vertical-align: center; */
-}
-
-select {
- // display: inline-block;
- // /* width: 175dp; */
- // /* height: 37dp; */
- // /* height: auto; */
- // text-align: left;
- // box-sizing:border-box;
- // /* padding: 4dp; */
- // vertical-align: center;
- // padding: 4dp;
- // border-radius: 5dp;
- // background-color: rgb(120, 120, 120);
- // width: 100%;
-}
-// select {
-// @extend %body;
-// display: flex;
-// align-items: center;
-// justify-content: flex-start;
-// box-sizing: border-box;
-// padding: space(16);
-// flex: 1 1 100%;
-// // width: auto;
-// height: space(1000);
-// border-radius: $border-radius-lg;
-// background-color: $color-white-a20;
-// }
-
-// select selectvalue {
-// height: auto;
-// /* padding: 4dp; */
-// /* margin-right: 30dp; */
-// /* height: 25dp; */
-// /* padding: 4dp; */
-// /* decorator: image(selectvalue) */
-// }
-
-// select:hover selectvalue {
-// /* margin-right: 30dp; */
-// /* height: 25dp; */
-// /* padding: 4dp; */
-// background-color: rgb(150, 150, 150);
-// /* decorator: image(selectvalue) */
-// }
-
-// select selectarrow {
-// /* width: 30dp; */
-// /* height: 37dp; */
-// /* decorator: image(selectarrow) */
-// /* background-color: black; */
-// /* appearance: none; */
-// }
-
-// select:hover selectarrow {
-// /* decorator: image(selectarrow-hover) */
-// }
-
-// select:active selectarrow,
-// select selectarrow:checked {
-// /* decorator: image(selectarrow-active) */
-// }
-
-// select selectbox {
-// /* margin-left: 1dp; */
-// /* margin-top: -7dp; */
-// /* margin-bottom: -10dp; */
-// /* width: 162dp; */
-// /* padding: 1dp 4dp 4dp 4dp */
-// }
-
-// select selectbox,
-// tbody {
-// background-color: rgb(120,120,120);
-// /* decorator: tiled-box(selectbox-tl, selectbox-t, selectbox-tr, selectbox-l, selectbox-c, auto, selectbox-bl, selectbox-b, selectbox-br) */
-// }
-
-// select selectbox option {
-// width: auto;
-// background-color: rgb(120, 120, 120)
-// }
-
-// select selectbox option:nth-child(even),
-// tr:nth-child(even) {
-// background-color: rgb(100, 100, 100)
-// }
-
-// select selectbox option:checked {
-// font-weight:bold;
-// color:rgb(255,255,255);
-// }
-
-// select selectbox option:hover {
-// background: rgb(150,150,150)
-// }
-
-input.radio {
- flex: 0;
- width:0dp;
- nav-up:auto;
- nav-right:auto;
- nav-down:auto;
- nav-left:auto;
- tab-index:auto;
- focus:auto;
-}
-
-input.checkbox {
- width: space(20);
- height: space(20);
- nav-up:auto;
- nav-right:auto;
- nav-down:auto;
- nav-left:auto;
- tab-index:auto;
- focus:auto;
-}
diff --git a/assets/scss/styles/globals/_scrollbars.scss b/assets/scss/styles/globals/_scrollbars.scss
deleted file mode 100644
index 375c164..0000000
--- a/assets/scss/styles/globals/_scrollbars.scss
+++ /dev/null
@@ -1,52 +0,0 @@
-@use 'sass:math';
-
-$scrollbar-width: 12;
-
-@mixin _set-scroll-size($size-key) {
- #{$size-key}: space($scrollbar-width);
-
- slidertrack {
- #{$size-key}: space($scrollbar-width);
- }
-
- sliderbar {
- #{$size-key}: space($scrollbar-width);
- }
-}
-
-scrollbarvertical,scrollbarhorizontal {
- margin: 0;
- border: 0;
-
- slidertrack {
- background: $color-primary-l;
- opacity: 0.05;
- }
-
- sliderbar {
- border-radius: space(math.div($scrollbar-width, 2) - 1);
- background: $color-primary-l;
- opacity: 0.1;
-
- &:hover:not(:active) {
- opacity: 0.2;
- }
-
- &:active {
- opacity: 0.3;
- }
- }
-
- sliderarrowdec, sliderarrowinc {
- width: 0;
- height: 0;
- }
-}
-
-scrollbarvertical {
- @include _set-scroll-size(width);
-}
-
-scrollbarhorizontal {
- @include _set-scroll-size(height);
-}
diff --git a/assets/scss/styles/mixins/_helpers.scss b/assets/scss/styles/mixins/_helpers.scss
deleted file mode 100644
index 9759630..0000000
--- a/assets/scss/styles/mixins/_helpers.scss
+++ /dev/null
@@ -1,39 +0,0 @@
-
-%nav-vert {
- nav-up: auto;
- nav-down: auto;
-}
-
-%nav-horiz {
- nav-right: auto;
- nav-left: auto;
-}
-
-%nav-dir {
- @extend %nav-vert;
- @extend %nav-horiz;
-}
-
-%nav-foc {
- focus: auto;
- tab-index: auto;
-}
-
-%nav-all {
- @extend %nav-dir;
- @extend %nav-foc;
-}
-
-@mixin set-svgs-color($col) {
- svg {
- image-color: $col;
- }
-}
-
-/*
-@include set-color(COLOR);
-*/
-@mixin set-color($col) {
- @include set-svgs-color($col);
- color: $col;
-}
diff --git a/assets/scss/styles/mixins/_transitions.scss b/assets/scss/styles/mixins/_transitions.scss
deleted file mode 100644
index 06c8677..0000000
--- a/assets/scss/styles/mixins/_transitions.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-
-/*
-@include trans-colors;
-*/
-@mixin trans-colors {
- transition: color $transition-quick, background-color $transition-quick;
-}
-
-/*
-@include trans-colors-opa;
-*/
-@mixin trans-colors-opa {
- transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick;
-}
-
-/*
-@include trans-colors-svg;
-*/
-@mixin trans-colors-svg {
- transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick;
-
- svg {
- transition: image-color $transition-quick, background-color $transition-quick;
- }
-}
-
-/*
-@include trans-colors-border;
-*/
-@mixin trans-colors-border {
- transition: color $transition-quick, background-color $transition-quick, opacity $transition-quick, border-color $transition-quick;
-
- svg {
- transition: image-color $transition-quick, background-color $transition-quick;
- }
-}
diff --git a/assets/scss/styles/mixins/_typography.scss b/assets/scss/styles/mixins/_typography.scss
deleted file mode 100644
index 384154c..0000000
--- a/assets/scss/styles/mixins/_typography.scss
+++ /dev/null
@@ -1,83 +0,0 @@
-
-$font-stack: 'Suplexmentary Comic NC';
-
-@mixin set-font-sizing($sz, $spacing) {
- // font-family: $font-stack;
- $sz-add: $sz + 4;
- font-size: space($sz-add);
- letter-spacing: space($sz-add * $spacing);
- line-height: space($sz-add);
-}
-
-%header-1 {
- @include set-font-sizing(64, 0.07);
- font-style: normal;
- font-weight: 700;
-}
-
-%header-2 {
- @include set-font-sizing(48, 0.07);
- font-style: normal;
- font-weight: 700;
-}
-
-%header-3 {
- @include set-font-sizing(32, 0.07);
- font-style: normal;
- font-weight: 700;
-}
-
-%label-lg {
- @include set-font-sizing(32, 0.11);
- font-style: normal;
- font-weight: 700;
-}
-
-%label-md {
- @include set-font-sizing(24, 0.11);
- font-style: normal;
- font-weight: 700;
-}
-
-%label-sm {
- @include set-font-sizing(16, 0.14);
- font-style: normal;
- font-weight: 700;
- text-transform: uppercase;
-}
-
-%label-xs {
- @include set-font-sizing(14, 0.14);
- font-style: normal;
- font-weight: 400;
-}
-
-%body {
- @include set-font-sizing(16, 0.0);
- font-style: normal;
- font-weight: 400;
-}
-
-%prompt-font-lg {
- font-family: promptfont;
- font-size: space(56);
- font-style: normal;
- font-weight: 400;
- line-height: space(56);
-}
-
-%prompt-font {
- font-family: promptfont;
- font-size: space(40);
- font-style: normal;
- font-weight: 400;
- line-height: space(40);
-}
-
-%prompt-font-sm {
- font-family: promptfont;
- font-size: space(32);
- font-style: normal;
- font-weight: 400;
- line-height: space(32);
-}
diff --git a/assets/scss/styles/pages/_pages.scss b/assets/scss/styles/pages/_pages.scss
deleted file mode 100644
index 16e2e18..0000000
--- a/assets/scss/styles/pages/_pages.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import "./config/config";
diff --git a/assets/scss/styles/pages/config/_config.scss b/assets/scss/styles/pages/config/_config.scss
deleted file mode 100644
index c4e69bc..0000000
--- a/assets/scss/styles/pages/config/_config.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import "./debug";
diff --git a/assets/scss/styles/pages/config/debug.scss b/assets/scss/styles/pages/config/debug.scss
deleted file mode 100644
index 997bfc0..0000000
--- a/assets/scss/styles/pages/config/debug.scss
+++ /dev/null
@@ -1,178 +0,0 @@
-
-.config-debug {
- display: block;
- position: relative;
- width: 100%;
- max-height: 100%;
- padding: space(8);
-}
-
-.config-debug__scroll {
- display: block;
- position: relative;
- width: 100%;
- max-height: 100%;
- overflow-y: auto;
-}
-
-.config-debug-option {
- @include set-color($color-text-dim);
- @include trans-colors-svg;
- @include border-bottom($color-border-soft);
- display: block;
- position: relative;
- flex-direction: column;
- width: 100%;
- height: auto;
- padding: space(12) space(4);
- background-color: rgba(0, 0, 0, 0);
-
- &:focus:not(:disabled, [disabled]),
- &:focus-visible:not(:disabled, [disabled]),
- &:hover:not(:disabled, [disabled]) {
- @include set-color($color-text);
- background-color: $color-bg-overlay;
- }
-
- &:disabled, &[disabled] {
- opacity: 0.5;
- }
-
- .icon-button {
- margin-left: space(8);
- }
-}
-
-.config-debug__option-split {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
-}
-
-.config-debug-option__label {
- @extend %label-md;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- padding: space(4) space(16) space(12);
- width: auto;
- height: auto;
- white-space: nowrap;
-}
-
-.config-debug__option-controls {
- display: block;
- position: relative;
- flex: 1 1 auto;
- height: auto;
- width: auto;
- max-width: space(800);
- padding: 0 space(12);
-}
-
-.config-debug__option-trigger {
- flex: 1 1 auto;
-}
-
-.config-debug__select-wrapper {
- display: flex;
- position: relative;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- flex: 1 1 100%;
- width: auto;
- max-width: space(800);
- height: auto;
- padding: space(4);
-
- .config-debug__select-label {
- @extend %label-sm;
- padding-right: space(16);
- flex: auto;
- width: space(196);
-
- > div {
- display: inline;
- width: auto;
- height: auto;
- }
- }
-
- input {
- @extend %body;
- @extend %nav-all;
- display: block;
- position: relative;
- box-sizing: border-box;
- padding: 0;
- flex: 1 1 100%;
- width: auto;
- height: space(20);
- margin: auto 0;
- }
-
- select {
- @extend %body;
- @extend %nav-all;
- @include trans-colors-border;
- @include border($color-white-a50);
- display: block;
- position: relative;
- box-sizing: border-box;
- padding: 0;
- flex: 1 1 100%;
- width: auto;
- height: space(48);
- border-radius: $border-radius-md;
- background-color: $color-white-a5;
- cursor: pointer;
-
- align-items: center;
- justify-content: flex-start;
- padding: space(14);
-
- &:hover, &:focus {
- @include border($color-white-a80);
- background-color: $color-white-a20;
- }
-
- selectvalue {
- display: inline;
- margin: auto 0;
- height: auto;
- }
-
- selectbox {
- @include border($color-white-a80);
- background-color: $color-background-3;
- padding: space(4) 0;
- margin-top: space(2);
- border-radius: $border-radius-md;
-
- option {
- @extend %nav-all;
- @include trans-colors;
- padding: space(8) space(12);
- background-color: $color-transparent;
- color: $color-text-dim;
- font-weight: 400;
-
- &:hover, &:focus {
- background-color: $color-white-a20;
- }
-
- &:hover:not(:checked) {
- cursor: pointer;
- }
-
- &:checked {
- color: $color-white;
- background-color: $color-white-a5;
- }
- }
- }
- }
-}
diff --git a/assets/scss/styles/vars/_animations.scss b/assets/scss/styles/vars/_animations.scss
deleted file mode 100644
index 9315f4d..0000000
--- a/assets/scss/styles/vars/_animations.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-
-$focus-anim: blue-pulse-with-border 0.75s infinite;
-$focus-anim-border: blue-pulse 0.75s infinite;
-$focus-anim-bg: blue-pulse-background 0.75s infinite;
diff --git a/assets/scss/styles/vars/_borders.scss b/assets/scss/styles/vars/_borders.scss
deleted file mode 100644
index 5088285..0000000
--- a/assets/scss/styles/vars/_borders.scss
+++ /dev/null
@@ -1,42 +0,0 @@
-
-$border-radius-sm: 8dp;
-$border-radius-md: 12dp;
-// modals/pages
-$border-radius-lg: 16dp;
-
-$border-radius-modal: $border-radius-lg;
-
-$border-width-thickness-num: 1.1;
-// $border-width-thickness-num: 1.5;
-$border-width-thickness: space($border-width-thickness-num);
-
-@mixin border($col: $color-border) {
- border-width: $border-width-thickness;
- border-color: $col;
-}
-
-@mixin border-top($col: $color-border) {
- border-top-width: $border-width-thickness;
- border-top-color: $col;
-}
-
-@mixin border-bottom($col: $color-border) {
- border-bottom-width: $border-width-thickness;
- border-bottom-color: $col;
-}
-
-@mixin inset-block($inset-amt) {
- position: absolute;
- top: $inset-amt;
- right: $inset-amt;
- bottom: $inset-amt;
- left: $inset-amt;
-}
-
-// add this to a child of the container that needs a border.
-// parent must have `position: relative`
-@mixin inner-border-block($col: $color-border) {
- @include inset-block($border-width-thickness);
- @include border($col);
- display: block;
-}
diff --git a/assets/scss/styles/vars/_colors.scss b/assets/scss/styles/vars/_colors.scss
deleted file mode 100644
index 37e3b1e..0000000
--- a/assets/scss/styles/vars/_colors.scss
+++ /dev/null
@@ -1,83 +0,0 @@
-/* stylelint-disable color-no-hex, color-hex-length */
-
-$color-background-1: Background1;
-$color-background-2: Background2;
-$color-background-3: Background3;
-$color-bg-overlay: BGOverlay;
-$color-modal-overlay: ModalOverlay;
-$color-bg-shadow: BGShadow;
-$color-bg-shadow-2: BGShadow2;
-$color-text: Text;
-$color-text-active: TextActive;
-$color-text-dim: TextDim;
-$color-text-inactive: TextInactive;
-$color-text-a5: TextA5;
-$color-text-a20: TextA20;
-$color-text-a30: TextA30;
-$color-text-a50: TextA50;
-$color-text-a80: TextA80;
-$color-primary: Primary;
-$color-primary-l: PrimaryL;
-$color-primary-d: PrimaryD;
-$color-primary-a5: PrimaryA5;
-$color-primary-a20: PrimaryA20;
-$color-primary-a30: PrimaryA30;
-$color-primary-a50: PrimaryA50;
-$color-primary-a80: PrimaryA80;
-$color-secondary: Secondary;
-$color-secondary-l: SecondaryL;
-$color-secondary-d: SecondaryD;
-$color-secondary-a5: SecondaryA5;
-$color-secondary-a20: SecondaryA20;
-$color-secondary-a30: SecondaryA30;
-$color-secondary-a50: SecondaryA50;
-$color-secondary-a80: SecondaryA80;
-$color-warning: Warning;
-$color-warning-l: WarningL;
-$color-warning-d: WarningD;
-$color-warning-a5: WarningA5;
-$color-warning-a20: WarningA20;
-$color-warning-a30: WarningA30;
-$color-warning-a50: WarningA50;
-$color-warning-a80: WarningA80;
-$color-danger: Danger;
-$color-danger-l: DangerL;
-$color-danger-d: DangerD;
-$color-danger-a5: DangerA5;
-$color-danger-a20: DangerA20;
-$color-danger-a30: DangerA30;
-$color-danger-a50: DangerA50;
-$color-danger-a80: DangerA80;
-$color-success: Success;
-$color-success-l: SuccessL;
-$color-success-d: SuccessD;
-$color-success-a5: SuccessA5;
-$color-success-a20: SuccessA20;
-$color-success-a30: SuccessA30;
-$color-success-a50: SuccessA50;
-$color-success-a80: SuccessA80;
-$color-border: Border;
-$color-border-soft: BorderSoft;
-$color-border-hard: BorderHard;
-$color-border-solid: BorderSolid;
-$color-transparent: Transparent;
-$color-a: A;
-$color-a-l: AL;
-$color-a-d: AD;
-$color-a-a5: AA5;
-$color-a-a20: AA20;
-$color-a-a30: AA30;
-$color-a-a50: AA50;
-$color-a-a80: AA80;
-$color-white: White;
-$color-white-a5: WhiteA5;
-$color-white-a20: WhiteA20;
-$color-white-a30: WhiteA30;
-$color-white-a50: WhiteA50;
-$color-white-a80: WhiteA80;
-$color-bw-05: BW05;
-$color-bw-10: BW10;
-$color-bw-25: BW25;
-$color-bw-50: BW50;
-$color-bw-75: BW75;
-$color-bw-90: BW90;
diff --git a/assets/scss/styles/vars/_gradients.scss b/assets/scss/styles/vars/_gradients.scss
deleted file mode 100644
index b3e2305..0000000
--- a/assets/scss/styles/vars/_gradients.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-
-// Not supported yet, need to use decorator: gradient atm
-// $primary-lr-fade: linear-gradient(90deg, rgba($color-primary-l, 0.08) 0%, rgba($color-primary-l, 0.00) 100%);
-// $primary-rl-fade: linear-gradient(90deg, rgba($color-primary-l, 0.00) 0%, rgba($color-primary-l, 0.08) 100%);
-
-// $primary-lr-fade: horizontal-gradient(#{$color-primary-d}14 #{$color-primary-l}00);
-// $primary-rl-fade: horizontal-gradient(#{$color-primary-d}00 #{$color-primary-l}14);
-$primary-lr-fade: horizontal-gradient(#ff000014 #ff000000);
-$primary-rl-fade: horizontal-gradient(#ff000000 #ff000014);
diff --git a/assets/scss/styles/vars/_spacing.scss b/assets/scss/styles/vars/_spacing.scss
deleted file mode 100644
index b61c8e1..0000000
--- a/assets/scss/styles/vars/_spacing.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@use 'sass:math';
-
-// $page-margin: 32;
-$page-margin: 64;
-$base-height: 1080;
-$base-modal-height: $base-height - ($page-margin * 2);
-$base-modal-max-width: math.div($base-modal-height * 16, 9);
diff --git a/assets/scss/styles/vars/_transitions.scss b/assets/scss/styles/vars/_transitions.scss
deleted file mode 100644
index 0586d88..0000000
--- a/assets/scss/styles/vars/_transitions.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// see: lib/RmlUi/Source/Core/PropertyParserAnimation.cpp
-$transition-quick: 0.05s linear-in-out;
-// $transition-quick: 0.033s linear-in-out;
diff --git a/include/banjo_config.h b/include/banjo_config.h
index 3e8057c..cc20b04 100644
--- a/include/banjo_config.h
+++ b/include/banjo_config.h
@@ -2,53 +2,46 @@
#define __BANJO_CONFIG_H__
#include
+#include
#include
-#include "ultramodern/config.hpp"
-#include "recomp_input.h"
+
+#include "json/json.hpp"
namespace banjo {
- constexpr std::u8string_view program_id = u8"BanjoRecompiled";
- constexpr std::string_view program_name = "Banjo: Recompiled";
+ inline const std::u8string program_id = u8"BanjoRecompiled";
+ inline const std::string program_name = "Banjo: Recompiled";
+
+ namespace configkeys {
+ namespace general {
+ inline const std::string note_saving_mode = "note_saving_mode";
+ inline const std::string camera_invert_mode = "camera_invert_mode";
+ inline const std::string analog_cam_mode = "analog_cam_mode";
+ inline const std::string analog_camera_invert_mode = "analog_camera_invert_mode";
+ }
+
+ namespace sound {
+ inline const std::string bgm_volume = "bgm_volume";
+ }
+ }
// TODO: Move loading configs to the runtime once we have a way to allow per-project customization.
- void load_config();
- void save_config();
-
- void reset_input_bindings();
- void reset_cont_input_bindings();
- void reset_kb_input_bindings();
- void reset_single_input_binding(recomp::InputDevice device, recomp::GameInput input);
+ void init_config();
- std::filesystem::path get_app_folder_path();
-
- bool get_debug_mode_enabled();
- void set_debug_mode_enabled(bool enabled);
-
enum class CameraInvertMode {
InvertNone,
InvertX,
InvertY,
- InvertBoth,
- OptionCount
+ InvertBoth
};
- NLOHMANN_JSON_SERIALIZE_ENUM(banjo::CameraInvertMode, {
- {banjo::CameraInvertMode::InvertNone, "InvertNone"},
- {banjo::CameraInvertMode::InvertX, "InvertX"},
- {banjo::CameraInvertMode::InvertY, "InvertY"},
- {banjo::CameraInvertMode::InvertBoth, "InvertBoth"}
- });
-
CameraInvertMode get_camera_invert_mode();
- void set_camera_invert_mode(CameraInvertMode mode);
CameraInvertMode get_analog_camera_invert_mode();
- void set_analog_camera_invert_mode(CameraInvertMode mode);
enum class AnalogCamMode {
On,
Off,
- OptionCount
+ OptionCount
};
NLOHMANN_JSON_SERIALIZE_ENUM(banjo::AnalogCamMode, {
@@ -57,7 +50,6 @@ namespace banjo {
});
AnalogCamMode get_analog_cam_mode();
- void set_analog_cam_mode(AnalogCamMode mode);
enum class NoteSavingMode {
On,
@@ -71,7 +63,6 @@ namespace banjo {
});
NoteSavingMode get_note_saving_mode();
- void set_note_saving_mode(NoteSavingMode mode);
void open_quit_game_prompt();
};
diff --git a/include/banjo_render.h b/include/banjo_render.h
index 36cd718..4bdb6a2 100644
--- a/include/banjo_render.h
+++ b/include/banjo_render.h
@@ -6,6 +6,7 @@
#include "common/rt64_user_configuration.h"
#include "ultramodern/renderer_context.hpp"
+#include "librecomp/config.hpp"
#include "librecomp/mods.hpp"
namespace RT64 {
@@ -54,7 +55,7 @@ namespace banjo {
// Texture pack enable option. Must be an enum with two options.
// The first option is treated as disabled and the second option is treated as enabled.
- bool is_texture_pack_enable_config_option(const recomp::mods::ConfigOption& option, bool show_errors);
+ bool is_texture_pack_enable_config_option(const recomp::config::ConfigOption& option, bool show_errors);
}
}
diff --git a/include/banjo_sound.h b/include/banjo_sound.h
index acebdee..aff5459 100644
--- a/include/banjo_sound.h
+++ b/include/banjo_sound.h
@@ -2,10 +2,6 @@
#define __BANJO_SOUND_H__
namespace banjo {
- void reset_sound_settings();
- void set_main_volume(int volume);
- int get_main_volume();
- void set_bgm_volume(int volume);
int get_bgm_volume();
}
diff --git a/include/recomp_input.h b/include/recomp_input.h
deleted file mode 100644
index e534b5c..0000000
--- a/include/recomp_input.h
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef __RECOMP_INPUT_H__
-#define __RECOMP_INPUT_H__
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "ultramodern/input.hpp"
-
-#include "json/json.hpp"
-
-namespace recomp {
- // x-macros to build input enums and arrays.
- // First parameter is the enum name, second parameter is the bit field for the input (or 0 if there is no associated one), third is the readable name.
- // TODO refactor this to allow projects to rename these, or get rid of the readable name and leave that up to individual projects to map.
- #define DEFINE_N64_BUTTON_INPUTS() \
- DEFINE_INPUT(A, 0x8000, "A") \
- DEFINE_INPUT(B, 0x4000, "B") \
- DEFINE_INPUT(Z, 0x2000, "Z") \
- DEFINE_INPUT(START, 0x1000, "Start") \
- DEFINE_INPUT(L, 0x0020, "L") \
- DEFINE_INPUT(R, 0x0010, "R") \
- DEFINE_INPUT(C_UP, 0x0008, "C Up") \
- DEFINE_INPUT(C_LEFT, 0x0002, "C Left") \
- DEFINE_INPUT(C_DOWN, 0x0004, "C Down") \
- DEFINE_INPUT(C_RIGHT, 0x0001, "C Right") \
- DEFINE_INPUT(DPAD_UP, 0x0800, "D Pad Down") \
- DEFINE_INPUT(DPAD_RIGHT, 0x0100, "D-Pad Down") \
- DEFINE_INPUT(DPAD_DOWN, 0x0400, "D-Pad Down") \
- DEFINE_INPUT(DPAD_LEFT, 0x0200, "D-Pad Down")
-
- #define DEFINE_N64_AXIS_INPUTS() \
- DEFINE_INPUT(Y_AXIS_POS, 0, "Up") \
- DEFINE_INPUT(Y_AXIS_NEG, 0, "Down") \
- DEFINE_INPUT(X_AXIS_NEG, 0, "Left") \
- DEFINE_INPUT(X_AXIS_POS, 0, "Right") \
-
- #define DEFINE_RECOMP_UI_INPUTS() \
- DEFINE_INPUT(TOGGLE_MENU, 0, "Toggle Menu") \
- DEFINE_INPUT(ACCEPT_MENU, 0, "Accept (Menu)") \
- DEFINE_INPUT(APPLY_MENU, 0, "Apply (Menu)")
-
- #define DEFINE_ALL_INPUTS() \
- DEFINE_N64_BUTTON_INPUTS() \
- DEFINE_N64_AXIS_INPUTS() \
- DEFINE_RECOMP_UI_INPUTS()
-
- // Enum containing every recomp input.
- #define DEFINE_INPUT(name, value, readable) name,
- enum class GameInput {
- DEFINE_ALL_INPUTS()
-
- COUNT,
- N64_BUTTON_START = A,
- N64_BUTTON_COUNT = C_RIGHT - N64_BUTTON_START + 1,
- N64_AXIS_START = X_AXIS_NEG,
- N64_AXIS_COUNT = Y_AXIS_POS - N64_AXIS_START + 1,
- };
- #undef DEFINE_INPUT
-
- struct InputField {
- uint32_t input_type;
- int32_t input_id;
- std::string to_string() const;
- auto operator<=>(const InputField& rhs) const = default;
- };
-
- void poll_inputs();
- float get_input_analog(const InputField& field);
- float get_input_analog(const std::span fields);
- bool get_input_digital(const InputField& field);
- bool get_input_digital(const std::span fields);
- void get_gyro_deltas(float* x, float* y);
- void get_mouse_deltas(float* x, float* y);
- void get_right_analog(float* x, float* y);
-
- enum class InputDevice {
- Controller,
- Keyboard,
- COUNT
- };
-
- void start_scanning_input(InputDevice device);
- void stop_scanning_input();
- void finish_scanning_input(InputField scanned_field);
- void cancel_scanning_input();
- void config_menu_set_cont_or_kb(bool cont_interacted);
- InputField get_scanned_input();
- int get_scanned_input_index();
-
- struct DefaultN64Mappings {
- std::vector a;
- std::vector b;
- std::vector l;
- std::vector r;
- std::vector z;
- std::vector start;
-
- std::vector c_left;
- std::vector c_right;
- std::vector c_up;
- std::vector c_down;
-
- std::vector dpad_left;
- std::vector dpad_right;
- std::vector dpad_up;
- std::vector dpad_down;
-
- std::vector analog_left;
- std::vector analog_right;
- std::vector analog_up;
- std::vector analog_down;
-
- std::vector toggle_menu;
- std::vector accept_menu;
- std::vector apply_menu;
- };
-
- inline const std::vector& get_default_mapping_for_input(const DefaultN64Mappings& defaults, const GameInput input) {
- static const std::vector empty_input_field{};
- switch (input) {
- case GameInput::A: return defaults.a;
- case GameInput::B: return defaults.b;
- case GameInput::L: return defaults.l;
- case GameInput::R: return defaults.r;
- case GameInput::Z: return defaults.z;
- case GameInput::START: return defaults.start;
- case GameInput::C_LEFT: return defaults.c_left;
- case GameInput::C_RIGHT: return defaults.c_right;
- case GameInput::C_UP: return defaults.c_up;
- case GameInput::C_DOWN: return defaults.c_down;
- case GameInput::DPAD_LEFT: return defaults.dpad_left;
- case GameInput::DPAD_RIGHT: return defaults.dpad_right;
- case GameInput::DPAD_UP: return defaults.dpad_up;
- case GameInput::DPAD_DOWN: return defaults.dpad_down;
- case GameInput::X_AXIS_NEG: return defaults.analog_left;
- case GameInput::X_AXIS_POS: return defaults.analog_right;
- case GameInput::Y_AXIS_POS: return defaults.analog_up;
- case GameInput::Y_AXIS_NEG: return defaults.analog_down;
- case GameInput::TOGGLE_MENU: return defaults.toggle_menu;
- case GameInput::ACCEPT_MENU: return defaults.accept_menu;
- case GameInput::APPLY_MENU: return defaults.apply_menu;
- default: return empty_input_field;
- }
- }
-
- extern const DefaultN64Mappings default_n64_keyboard_mappings;
- extern const DefaultN64Mappings default_n64_controller_mappings;
-
- constexpr size_t bindings_per_input = 2;
-
- size_t get_num_inputs();
- const std::string& get_input_name(GameInput input);
- const std::string& get_input_enum_name(GameInput input);
- GameInput get_input_from_enum_name(const std::string_view name);
- InputField& get_input_binding(GameInput input, size_t binding_index, InputDevice device);
- void set_input_binding(GameInput input, size_t binding_index, InputDevice device, InputField value);
-
- bool get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out);
- void set_rumble(int controller_num, bool);
- void update_rumble();
- void handle_events();
-
- ultramodern::input::connected_device_info_t get_connected_device_info(int controller_num);
-
- // Rumble strength ranges from 0 to 100.
- int get_rumble_strength();
- void set_rumble_strength(int strength);
-
- // Gyro and mouse sensitivities range from 0 to 100.
- int get_gyro_sensitivity();
- int get_mouse_sensitivity();
- int get_joystick_deadzone();
- void set_gyro_sensitivity(int strength);
- void set_mouse_sensitivity(int strength);
- void set_joystick_deadzone(int strength);
- void apply_joystick_deadzone(float x_in, float y_in, float* x_out, float* y_out);
- void set_right_analog_suppressed(bool suppressed);
-
- enum class BackgroundInputMode {
- On,
- Off,
- OptionCount
- };
-
- NLOHMANN_JSON_SERIALIZE_ENUM(recomp::BackgroundInputMode, {
- {recomp::BackgroundInputMode::On, "On"},
- {recomp::BackgroundInputMode::Off, "Off"}
- });
-
- BackgroundInputMode get_background_input_mode();
- void set_background_input_mode(BackgroundInputMode mode);
-
- bool game_input_disabled();
- bool all_input_disabled();
-}
-
-#endif
diff --git a/include/recomp_ui.h b/include/recomp_ui.h
deleted file mode 100644
index 1856ab0..0000000
--- a/include/recomp_ui.h
+++ /dev/null
@@ -1,138 +0,0 @@
-#ifndef __RECOMP_UI__
-#define __RECOMP_UI__
-
-#include
-#include
-#include
-#include
-
-// TODO move this file into src/ui
-
-#include "SDL.h"
-#include "RmlUi/Core.h"
-
-#include "../src/ui/util/hsv.h"
-#include "../src/ui/util/bem.h"
-#include "../src/ui/elements/ui_button.h"
-#include "../src/ui/elements/ui_theme.h"
-
-#include "../src/ui/core/ui_context.h"
-
-namespace Rml {
- class ElementDocument;
- class EventListenerInstancer;
- class Context;
- class Event;
-}
-
-namespace recompui {
- class UiEventListenerInstancer;
-
- // TODO remove this once the UI has been ported over to the new system.
- class MenuController {
- public:
- virtual ~MenuController() {}
- virtual void load_document() = 0;
- virtual void register_events(UiEventListenerInstancer& listener) = 0;
- virtual void make_bindings(Rml::Context* context) = 0;
- };
-
- std::unique_ptr create_launcher_menu();
- std::unique_ptr create_config_menu();
-
- using event_handler_t = void(const std::string& param, Rml::Event&);
-
- void queue_event(const SDL_Event& event);
- bool try_deque_event(SDL_Event& out);
-
- std::unique_ptr make_event_listener_instancer();
- void register_event(UiEventListenerInstancer& listener, const std::string& name, event_handler_t* handler);
-
- void show_context(ContextId context, std::string_view param);
- void hide_context(ContextId context);
- void hide_all_contexts();
- bool is_context_shown(ContextId context);
- bool is_context_capturing_input();
- bool is_context_capturing_mouse();
- bool is_any_context_shown();
- ContextId try_close_current_context();
-
- ContextId get_launcher_context_id();
- ContextId get_config_context_id();
- ContextId get_config_sub_menu_context_id();
-
- enum class ConfigTab {
- General,
- Controls,
- Graphics,
- Sound,
- Mods,
- Debug,
- };
-
- void set_config_tab(ConfigTab tab);
- int config_tab_to_index(ConfigTab tab);
- Rml::ElementTabSet* get_config_tabset();
- Rml::Element* get_mod_tab();
- void set_config_tabset_mod_nav();
- void focus_mod_configure_button();
-
- void init_styling(const std::filesystem::path& rcss_file);
- void init_prompt_context();
- void open_choice_prompt(
- const std::string& header_text,
- const std::string& content_text,
- const std::string& confirm_label_text,
- const std::string& cancel_label_text,
- std::function confirm_action,
- std::function cancel_action,
- ButtonStyle confirm_variant = ButtonStyle::Success,
- ButtonStyle cancel_variant = ButtonStyle::Danger,
- bool focus_on_cancel = true,
- const std::string& return_element_id = ""
- );
- void open_info_prompt(
- const std::string& header_text,
- const std::string& content_text,
- const std::string& okay_label_text,
- std::function okay_action,
- ButtonStyle okay_variant = ButtonStyle::Danger,
- const std::string& return_element_id = ""
- );
- void open_notification(
- const std::string& header_text,
- const std::string& content_text,
- const std::string& return_element_id = ""
- );
- void close_prompt();
- bool is_prompt_open();
- void update_mod_list(bool scan_mods = true);
- void process_game_started();
-
- void apply_color_hack();
- void get_window_size(int& width, int& height);
- void set_cursor_visible(bool visible);
- void update_supported_options();
- void toggle_fullscreen();
-
- bool get_cont_active(void);
- void set_cont_active(bool active);
- void activate_mouse();
-
- void message_box(const char* msg);
-
- void set_render_hooks();
-
- Rml::ElementPtr create_custom_element(Rml::Element* parent, std::string tag);
- Rml::ElementDocument* load_document(const std::filesystem::path& path);
- Rml::ElementDocument* create_empty_document();
- Rml::Element* get_child_by_tag(Rml::Element* parent, const std::string& tag);
-
- void queue_image_from_bytes_rgba32(const std::string &src, const std::vector &bytes, uint32_t width, uint32_t height);
- void queue_image_from_bytes_file(const std::string &src, const std::vector &bytes);
- void release_image(const std::string &src);
-
- void drop_files(const std::list &file_list);
-}
-
-#endif
diff --git a/lib/FindFreetype.cmake b/lib/FindFreetype.cmake
deleted file mode 100644
index 1e50bcd..0000000
--- a/lib/FindFreetype.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-set(FREETYPE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include)
-set(FREETYPE_LIBRARIES "${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/release static/vs2015-2022/win64/freetype.lib")
-add_library(Freetype::Freetype STATIC IMPORTED)
-set_target_properties(Freetype::Freetype PROPERTIES
- IMPORTED_LOCATION ${FREETYPE_LIBRARIES}
-)
-target_include_directories(Freetype::Freetype INTERFACE
- ${FREETYPE_INCLUDE_DIRS}
-)
diff --git a/lib/GamepadMotionHelpers/.gitignore b/lib/GamepadMotionHelpers/.gitignore
deleted file mode 100644
index 259148f..0000000
--- a/lib/GamepadMotionHelpers/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-# Prerequisites
-*.d
-
-# Compiled Object files
-*.slo
-*.lo
-*.o
-*.obj
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Compiled Dynamic libraries
-*.so
-*.dylib
-*.dll
-
-# Fortran module files
-*.mod
-*.smod
-
-# Compiled Static libraries
-*.lai
-*.la
-*.a
-*.lib
-
-# Executables
-*.exe
-*.out
-*.app
diff --git a/lib/GamepadMotionHelpers/CMakeLists.txt b/lib/GamepadMotionHelpers/CMakeLists.txt
deleted file mode 100644
index 27f7748..0000000
--- a/lib/GamepadMotionHelpers/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-cmake_minimum_required(VERSION 3.8)
-
-project(GamepadMotionHelpers LANGUAGES CXX)
-
-add_library(${PROJECT_NAME} INTERFACE)
-add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
-target_include_directories(${PROJECT_NAME}
- INTERFACE
- $
- $)
-
\ No newline at end of file
diff --git a/lib/GamepadMotionHelpers/GamepadMotion.hpp b/lib/GamepadMotionHelpers/GamepadMotion.hpp
deleted file mode 100644
index 02497ac..0000000
--- a/lib/GamepadMotionHelpers/GamepadMotion.hpp
+++ /dev/null
@@ -1,1312 +0,0 @@
-// Copyright (c) 2020-2023 Julian "Jibb" Smart
-// Released under the MIT license. See https://github.com/JibbSmart/GamepadMotionHelpers/blob/main/LICENSE for more info
-// Version 9
-
-#pragma once
-
-#define _USE_MATH_DEFINES
-#include
-#include // std::min, std::max and std::clamp
-
-// You don't need to look at these. These will just be used internally by the GamepadMotion class declared below.
-// You can ignore anything in namespace GamepadMotionHelpers.
-class GamepadMotionSettings;
-class GamepadMotion;
-
-namespace GamepadMotionHelpers
-{
- struct GyroCalibration
- {
- float X;
- float Y;
- float Z;
- float AccelMagnitude;
- int NumSamples;
- };
-
- struct Quat
- {
- float w;
- float x;
- float y;
- float z;
-
- Quat();
- Quat(float inW, float inX, float inY, float inZ);
- void Set(float inW, float inX, float inY, float inZ);
- Quat& operator*=(const Quat& rhs);
- friend Quat operator*(Quat lhs, const Quat& rhs);
- void Normalize();
- Quat Normalized() const;
- void Invert();
- Quat Inverse() const;
- };
-
- struct Vec
- {
- float x;
- float y;
- float z;
-
- Vec();
- Vec(float inValue);
- Vec(float inX, float inY, float inZ);
- void Set(float inX, float inY, float inZ);
- float Length() const;
- float LengthSquared() const;
- void Normalize();
- Vec Normalized() const;
- float Dot(const Vec& other) const;
- Vec Cross(const Vec& other) const;
- Vec Min(const Vec& other) const;
- Vec Max(const Vec& other) const;
- Vec Abs() const;
- Vec Lerp(const Vec& other, float factor) const;
- Vec Lerp(const Vec& other, const Vec& factor) const;
- Vec& operator+=(const Vec& rhs);
- friend Vec operator+(Vec lhs, const Vec& rhs);
- Vec& operator-=(const Vec& rhs);
- friend Vec operator-(Vec lhs, const Vec& rhs);
- Vec& operator*=(const float rhs);
- friend Vec operator*(Vec lhs, const float rhs);
- Vec& operator/=(const float rhs);
- friend Vec operator/(Vec lhs, const float rhs);
- Vec& operator*=(const Quat& rhs);
- friend Vec operator*(Vec lhs, const Quat& rhs);
- Vec operator-() const;
- };
-
- struct SensorMinMaxWindow
- {
- Vec MinGyro;
- Vec MaxGyro;
- Vec MeanGyro;
- Vec MinAccel;
- Vec MaxAccel;
- Vec MeanAccel;
- Vec StartAccel;
- int NumSamples = 0;
- float TimeSampled = 0.f;
-
- SensorMinMaxWindow();
- void Reset(float remainder);
- void AddSample(const Vec& inGyro, const Vec& inAccel, float deltaTime);
- Vec GetMidGyro();
- };
-
- struct AutoCalibration
- {
- SensorMinMaxWindow MinMaxWindow;
- Vec SmoothedAngularVelocityGyro;
- Vec SmoothedAngularVelocityAccel;
- Vec SmoothedPreviousAccel;
- Vec PreviousAccel;
-
- AutoCalibration();
- void Reset();
- bool AddSampleStillness(const Vec& inGyro, const Vec& inAccel, float deltaTime, bool doSensorFusion);
- void NoSampleStillness();
- bool AddSampleSensorFusion(const Vec& inGyro, const Vec& inAccel, float deltaTime);
- void NoSampleSensorFusion();
- void SetCalibrationData(GyroCalibration* calibrationData);
- void SetSettings(GamepadMotionSettings* settings);
-
- float Confidence = 0.f;
- bool IsSteady() { return bIsSteady; }
-
- private:
- Vec MinDeltaGyro = Vec(1.f);
- Vec MinDeltaAccel = Vec(0.25f);
- float RecalibrateThreshold = 1.f;
- float SensorFusionSkippedTime = 0.f;
- float TimeSteadySensorFusion = 0.f;
- float TimeSteadyStillness = 0.f;
- bool bIsSteady = false;
-
- GyroCalibration* CalibrationData;
- GamepadMotionSettings* Settings;
- };
-
- struct Motion
- {
- Quat Quaternion;
- Vec Accel;
- Vec Grav;
-
- Vec SmoothAccel = Vec();
- float Shakiness = 0.f;
- const float ShortSteadinessHalfTime = 0.25f;
- const float LongSteadinessHalfTime = 1.f;
-
- Motion();
- void Reset();
- void Update(float inGyroX, float inGyroY, float inGyroZ, float inAccelX, float inAccelY, float inAccelZ, float gravityLength, float deltaTime);
- void SetSettings(GamepadMotionSettings* settings);
-
- private:
- GamepadMotionSettings* Settings;
- };
-
- enum CalibrationMode
- {
- Manual = 0,
- Stillness = 1,
- SensorFusion = 2,
- };
-
- // https://stackoverflow.com/a/1448478/1130520
- inline CalibrationMode operator|(CalibrationMode a, CalibrationMode b)
- {
- return static_cast(static_cast(a) | static_cast(b));
- }
-
- inline CalibrationMode operator&(CalibrationMode a, CalibrationMode b)
- {
- return static_cast(static_cast(a) & static_cast(b));
- }
-
- inline CalibrationMode operator~(CalibrationMode a)
- {
- return static_cast(~static_cast(a));
- }
-
- // https://stackoverflow.com/a/23152590/1130520
- inline CalibrationMode& operator|=(CalibrationMode& a, CalibrationMode b)
- {
- return (CalibrationMode&)((int&)(a) |= static_cast(b));
- }
-
- inline CalibrationMode& operator&=(CalibrationMode& a, CalibrationMode b)
- {
- return (CalibrationMode&)((int&)(a) &= static_cast(b));
- }
-}
-
-// Note that I'm using a Y-up coordinate system. This is to follow the convention set by the motion sensors in
-// PlayStation controllers, which was what I was using when writing in this. But for the record, Z-up is
-// better for most games (XY ground-plane in 3D games simplifies using 2D vectors in navigation, for example).
-
-// Gyro units should be degrees per second. Accelerometer should be g-force (approx. 9.8 m/s^2 = 1 g). If you're using
-// radians per second, meters per second squared, etc, conversion should be simple.
-
-class GamepadMotionSettings
-{
-public:
- int MinStillnessSamples = 10;
- float MinStillnessCollectionTime = 0.5f;
- float MinStillnessCorrectionTime = 2.f;
- float MaxStillnessError = 2.f;
- float StillnessSampleDeteriorationRate = 0.2f;
- float StillnessErrorClimbRate = 0.1f;
- float StillnessErrorDropOnRecalibrate = 0.1f;
- float StillnessCalibrationEaseInTime = 3.f;
- float StillnessCalibrationHalfTime = 0.1f;
- float StillnessConfidenceRate = 1.f;
-
- float StillnessGyroDelta = -1.f;
- float StillnessAccelDelta = -1.f;
-
- float SensorFusionCalibrationSmoothingStrength = 2.f;
- float SensorFusionAngularAccelerationThreshold = 20.f;
- float SensorFusionCalibrationEaseInTime = 3.f;
- float SensorFusionCalibrationHalfTime = 0.1f;
- float SensorFusionConfidenceRate = 1.f;
-
- float GravityCorrectionShakinessMaxThreshold = 0.4f;
- float GravityCorrectionShakinessMinThreshold = 0.01f;
-
- float GravityCorrectionStillSpeed = 1.f;
- float GravityCorrectionShakySpeed = 0.1f;
-
- float GravityCorrectionGyroFactor = 0.1f;
- float GravityCorrectionGyroMinThreshold = 0.05f;
- float GravityCorrectionGyroMaxThreshold = 0.25f;
-
- float GravityCorrectionMinimumSpeed = 0.01f;
-};
-
-class GamepadMotion
-{
-public:
- GamepadMotion();
-
- void Reset();
-
- void ProcessMotion(float gyroX, float gyroY, float gyroZ,
- float accelX, float accelY, float accelZ, float deltaTime);
-
- // reading the current state
- void GetCalibratedGyro(float& x, float& y, float& z);
- void GetGravity(float& x, float& y, float& z);
- void GetProcessedAcceleration(float& x, float& y, float& z);
- void GetOrientation(float& w, float& x, float& y, float& z);
- void GetPlayerSpaceGyro(float& x, float& y, const float yawRelaxFactor = 1.41f);
- static void CalculatePlayerSpaceGyro(float& x, float& y, const float gyroX, const float gyroY, const float gyroZ, const float gravX, const float gravY, const float gravZ, const float yawRelaxFactor = 1.41f);
- void GetWorldSpaceGyro(float& x, float& y, const float sideReductionThreshold = 0.125f);
- static void CalculateWorldSpaceGyro(float& x, float& y, const float gyroX, const float gyroY, const float gyroZ, const float gravX, const float gravY, const float gravZ, const float sideReductionThreshold = 0.125f);
-
- // gyro calibration functions
- void StartContinuousCalibration();
- void PauseContinuousCalibration();
- void ResetContinuousCalibration();
- void GetCalibrationOffset(float& xOffset, float& yOffset, float& zOffset);
- void SetCalibrationOffset(float xOffset, float yOffset, float zOffset, int weight);
- float GetAutoCalibrationConfidence();
- void SetAutoCalibrationConfidence(float newConfidence);
- bool GetAutoCalibrationIsSteady();
-
- GamepadMotionHelpers::CalibrationMode GetCalibrationMode();
- void SetCalibrationMode(GamepadMotionHelpers::CalibrationMode calibrationMode);
-
- void ResetMotion();
-
- GamepadMotionSettings Settings;
-
-private:
- GamepadMotionHelpers::Vec Gyro;
- GamepadMotionHelpers::Vec RawAccel;
- GamepadMotionHelpers::Motion Motion;
- GamepadMotionHelpers::GyroCalibration GyroCalibration;
- GamepadMotionHelpers::AutoCalibration AutoCalibration;
- GamepadMotionHelpers::CalibrationMode CurrentCalibrationMode;
-
- bool IsCalibrating;
- void PushSensorSamples(float gyroX, float gyroY, float gyroZ, float accelMagnitude);
- void GetCalibratedSensor(float& gyroOffsetX, float& gyroOffsetY, float& gyroOffsetZ, float& accelMagnitude);
-};
-
-///////////// Everything below here are just implementation details /////////////
-
-namespace GamepadMotionHelpers
-{
- inline Quat::Quat()
- {
- w = 1.0f;
- x = 0.0f;
- y = 0.0f;
- z = 0.0f;
- }
-
- inline Quat::Quat(float inW, float inX, float inY, float inZ)
- {
- w = inW;
- x = inX;
- y = inY;
- z = inZ;
- }
-
- inline static Quat AngleAxis(float inAngle, float inX, float inY, float inZ)
- {
- const float sinHalfAngle = sinf(inAngle * 0.5f);
- Vec inAxis = Vec(inX, inY, inZ);
- inAxis.Normalize();
- inAxis *= sinHalfAngle;
- Quat result = Quat(cosf(inAngle * 0.5f), inAxis.x, inAxis.y, inAxis.z);
- return result;
- }
-
- inline void Quat::Set(float inW, float inX, float inY, float inZ)
- {
- w = inW;
- x = inX;
- y = inY;
- z = inZ;
- }
-
- inline Quat& Quat::operator*=(const Quat& rhs)
- {
- Set(w * rhs.w - x * rhs.x - y * rhs.y - z * rhs.z,
- w * rhs.x + x * rhs.w + y * rhs.z - z * rhs.y,
- w * rhs.y - x * rhs.z + y * rhs.w + z * rhs.x,
- w * rhs.z + x * rhs.y - y * rhs.x + z * rhs.w);
- return *this;
- }
-
- inline Quat operator*(Quat lhs, const Quat& rhs)
- {
- lhs *= rhs;
- return lhs;
- }
-
- inline void Quat::Normalize()
- {
- const float length = sqrtf(w * w + x * x + y * y + z * z);
- const float fixFactor = 1.0f / length;
-
- w *= fixFactor;
- x *= fixFactor;
- y *= fixFactor;
- z *= fixFactor;
-
- return;
- }
-
- inline Quat Quat::Normalized() const
- {
- Quat result = *this;
- result.Normalize();
- return result;
- }
-
- inline void Quat::Invert()
- {
- x = -x;
- y = -y;
- z = -z;
- return;
- }
-
- inline Quat Quat::Inverse() const
- {
- Quat result = *this;
- result.Invert();
- return result;
- }
-
- inline Vec::Vec()
- {
- x = 0.0f;
- y = 0.0f;
- z = 0.0f;
- }
-
- inline Vec::Vec(float inValue)
- {
- x = inValue;
- y = inValue;
- z = inValue;
- }
-
- inline Vec::Vec(float inX, float inY, float inZ)
- {
- x = inX;
- y = inY;
- z = inZ;
- }
-
- inline void Vec::Set(float inX, float inY, float inZ)
- {
- x = inX;
- y = inY;
- z = inZ;
- }
-
- inline float Vec::Length() const
- {
- return sqrtf(x * x + y * y + z * z);
- }
-
- inline float Vec::LengthSquared() const
- {
- return x * x + y * y + z * z;
- }
-
- inline void Vec::Normalize()
- {
- const float length = Length();
- if (length == 0.0)
- {
- return;
- }
- const float fixFactor = 1.0f / length;
-
- x *= fixFactor;
- y *= fixFactor;
- z *= fixFactor;
- return;
- }
-
- inline Vec Vec::Normalized() const
- {
- Vec result = *this;
- result.Normalize();
- return result;
- }
-
- inline Vec& Vec::operator+=(const Vec& rhs)
- {
- Set(x + rhs.x, y + rhs.y, z + rhs.z);
- return *this;
- }
-
- inline Vec operator+(Vec lhs, const Vec& rhs)
- {
- lhs += rhs;
- return lhs;
- }
-
- inline Vec& Vec::operator-=(const Vec& rhs)
- {
- Set(x - rhs.x, y - rhs.y, z - rhs.z);
- return *this;
- }
-
- inline Vec operator-(Vec lhs, const Vec& rhs)
- {
- lhs -= rhs;
- return lhs;
- }
-
- inline Vec& Vec::operator*=(const float rhs)
- {
- Set(x * rhs, y * rhs, z * rhs);
- return *this;
- }
-
- inline Vec operator*(Vec lhs, const float rhs)
- {
- lhs *= rhs;
- return lhs;
- }
-
- inline Vec& Vec::operator/=(const float rhs)
- {
- Set(x / rhs, y / rhs, z / rhs);
- return *this;
- }
-
- inline Vec operator/(Vec lhs, const float rhs)
- {
- lhs /= rhs;
- return lhs;
- }
-
- inline Vec& Vec::operator*=(const Quat& rhs)
- {
- Quat temp = rhs * Quat(0.0f, x, y, z) * rhs.Inverse();
- Set(temp.x, temp.y, temp.z);
- return *this;
- }
-
- inline Vec operator*(Vec lhs, const Quat& rhs)
- {
- lhs *= rhs;
- return lhs;
- }
-
- inline Vec Vec::operator-() const
- {
- Vec result = Vec(-x, -y, -z);
- return result;
- }
-
- inline float Vec::Dot(const Vec& other) const
- {
- return x * other.x + y * other.y + z * other.z;
- }
-
- inline Vec Vec::Cross(const Vec& other) const
- {
- return Vec(y * other.z - z * other.y,
- z * other.x - x * other.z,
- x * other.y - y * other.x);
- }
-
- inline Vec Vec::Min(const Vec& other) const
- {
- return Vec(x < other.x ? x : other.x,
- y < other.y ? y : other.y,
- z < other.z ? z : other.z);
- }
-
- inline Vec Vec::Max(const Vec& other) const
- {
- return Vec(x > other.x ? x : other.x,
- y > other.y ? y : other.y,
- z > other.z ? z : other.z);
- }
-
- inline Vec Vec::Abs() const
- {
- return Vec(x > 0 ? x : -x,
- y > 0 ? y : -y,
- z > 0 ? z : -z);
- }
-
- inline Vec Vec::Lerp(const Vec& other, float factor) const
- {
- return *this + (other - *this) * factor;
- }
-
- inline Vec Vec::Lerp(const Vec& other, const Vec& factor) const
- {
- return Vec(this->x + (other.x - this->x) * factor.x,
- this->y + (other.y - this->y) * factor.y,
- this->z + (other.z - this->z) * factor.z);
- }
-
- inline Motion::Motion()
- {
- Reset();
- }
-
- inline void Motion::Reset()
- {
- Quaternion.Set(1.f, 0.f, 0.f, 0.f);
- Accel.Set(0.f, 0.f, 0.f);
- Grav.Set(0.f, 0.f, 0.f);
- SmoothAccel.Set(0.f, 0.f, 0.f);
- Shakiness = 0.f;
- }
-
- ///
- /// The gyro inputs should be calibrated degrees per second but have no other processing. Acceleration is in G units (1 = approx. 9.8m/s^2)
- ///
- inline void Motion::Update(float inGyroX, float inGyroY, float inGyroZ, float inAccelX, float inAccelY, float inAccelZ, float gravityLength, float deltaTime)
- {
- if (!Settings)
- {
- return;
- }
-
- // get settings
- const float gravityCorrectionShakinessMinThreshold = Settings->GravityCorrectionShakinessMinThreshold;
- const float gravityCorrectionShakinessMaxThreshold = Settings->GravityCorrectionShakinessMaxThreshold;
- const float gravityCorrectionStillSpeed = Settings->GravityCorrectionStillSpeed;
- const float gravityCorrectionShakySpeed = Settings->GravityCorrectionShakySpeed;
- const float gravityCorrectionGyroFactor = Settings->GravityCorrectionGyroFactor;
- const float gravityCorrectionGyroMinThreshold = Settings->GravityCorrectionGyroMinThreshold;
- const float gravityCorrectionGyroMaxThreshold = Settings->GravityCorrectionGyroMaxThreshold;
- const float gravityCorrectionMinimumSpeed = Settings->GravityCorrectionMinimumSpeed;
-
- const Vec axis = Vec(inGyroX, inGyroY, inGyroZ);
- const Vec accel = Vec(inAccelX, inAccelY, inAccelZ);
- const float angleSpeed = axis.Length() * (float)M_PI / 180.0f;
- const float angle = angleSpeed * deltaTime;
-
- // rotate
- Quat rotation = AngleAxis(angle, axis.x, axis.y, axis.z);
- Quaternion *= rotation; // do it this way because it's a local rotation, not global
-
- //printf("Quat: %.4f %.4f %.4f %.4f\n",
- // Quaternion.w, Quaternion.x, Quaternion.y, Quaternion.z);
- float accelMagnitude = accel.Length();
- if (accelMagnitude > 0.0f)
- {
- const Vec accelNorm = accel / accelMagnitude;
- // account for rotation when tracking smoothed acceleration
- SmoothAccel *= rotation.Inverse();
- //printf("Absolute Accel: %.4f %.4f %.4f\n",
- // absoluteAccel.x, absoluteAccel.y, absoluteAccel.z);
- const float smoothFactor = ShortSteadinessHalfTime <= 0.f ? 0.f : exp2f(-deltaTime / ShortSteadinessHalfTime);
- Shakiness *= smoothFactor;
- Shakiness = std::max(Shakiness, (accel - SmoothAccel).Length());
- SmoothAccel = accel.Lerp(SmoothAccel, smoothFactor);
-
- //printf("Shakiness: %.4f\n", Shakiness);
-
- // update grav by rotation
- Grav *= rotation.Inverse();
- // we want to close the gap between grav and raw acceleration. What's the difference
- const Vec gravToAccel = (accelNorm * -gravityLength) - Grav;
- const Vec gravToAccelDir = gravToAccel.Normalized();
- // adjustment rate
- float gravCorrectionSpeed;
- if (gravityCorrectionShakinessMinThreshold < gravityCorrectionShakinessMaxThreshold)
- {
- gravCorrectionSpeed = gravityCorrectionStillSpeed + (gravityCorrectionShakySpeed - gravityCorrectionStillSpeed) * std::clamp((Shakiness - gravityCorrectionShakinessMinThreshold) / (gravityCorrectionShakinessMaxThreshold - gravityCorrectionShakinessMinThreshold), 0.f, 1.f);
- }
- else
- {
- gravCorrectionSpeed = Shakiness < gravityCorrectionShakinessMaxThreshold ? gravityCorrectionStillSpeed : gravityCorrectionShakySpeed;
- }
- // we also limit it to be no faster than a given proportion of the gyro rate, or the minimum gravity correction speed
- const float gyroGravCorrectionLimit = std::max(angleSpeed * gravityCorrectionGyroFactor, gravityCorrectionMinimumSpeed);
- if (gravCorrectionSpeed > gyroGravCorrectionLimit)
- {
- float closeEnoughFactor;
- if (gravityCorrectionGyroMinThreshold < gravityCorrectionGyroMaxThreshold)
- {
- closeEnoughFactor = std::clamp((gravToAccel.Length() - gravityCorrectionGyroMinThreshold) / (gravityCorrectionGyroMaxThreshold - gravityCorrectionGyroMinThreshold), 0.f, 1.f);
- }
- else
- {
- closeEnoughFactor = gravToAccel.Length() < gravityCorrectionGyroMaxThreshold ? 0.f : 1.f;
- }
- gravCorrectionSpeed = gyroGravCorrectionLimit + (gravCorrectionSpeed - gyroGravCorrectionLimit) * closeEnoughFactor;
- }
- const Vec gravToAccelDelta = gravToAccelDir * gravCorrectionSpeed * deltaTime;
- if (gravToAccelDelta.LengthSquared() < gravToAccel.LengthSquared())
- {
- Grav += gravToAccelDelta;
- }
- else
- {
- Grav = accelNorm * -gravityLength;
- }
-
- const Vec gravityDirection = Grav.Normalized() * Quaternion.Inverse(); // absolute gravity direction
- const float errorAngle = acosf(std::clamp(Vec(0.0f, -1.0f, 0.0f).Dot(gravityDirection), -1.f, 1.f));
- const Vec flattened = Vec(0.0f, -1.0f, 0.0f).Cross(gravityDirection);
- Quat correctionQuat = AngleAxis(errorAngle, flattened.x, flattened.y, flattened.z);
- Quaternion = Quaternion * correctionQuat;
-
- Accel = accel + Grav;
- }
- else
- {
- Grav *= rotation.Inverse();
- Accel = Grav;
- }
- Quaternion.Normalize();
- }
-
- inline void Motion::SetSettings(GamepadMotionSettings* settings)
- {
- Settings = settings;
- }
-
- inline SensorMinMaxWindow::SensorMinMaxWindow()
- {
- Reset(0.f);
- }
-
- inline void SensorMinMaxWindow::Reset(float remainder)
- {
- NumSamples = 0;
- TimeSampled = remainder;
- }
-
- inline void SensorMinMaxWindow::AddSample(const Vec& inGyro, const Vec& inAccel, float deltaTime)
- {
- if (NumSamples == 0)
- {
- MaxGyro = inGyro;
- MinGyro = inGyro;
- MeanGyro = inGyro;
- MaxAccel = inAccel;
- MinAccel = inAccel;
- MeanAccel = inAccel;
- StartAccel = inAccel;
- NumSamples = 1;
- TimeSampled += deltaTime;
- return;
- }
-
- MaxGyro = MaxGyro.Max(inGyro);
- MinGyro = MinGyro.Min(inGyro);
- MaxAccel = MaxAccel.Max(inAccel);
- MinAccel = MinAccel.Min(inAccel);
-
- NumSamples++;
- TimeSampled += deltaTime;
-
- Vec delta = inGyro - MeanGyro;
- MeanGyro += delta * (1.f / NumSamples);
- delta = inAccel - MeanAccel;
- MeanAccel += delta * (1.f / NumSamples);
- }
-
- inline Vec SensorMinMaxWindow::GetMidGyro()
- {
- return MeanGyro;
- }
-
- inline AutoCalibration::AutoCalibration()
- {
- CalibrationData = nullptr;
- Reset();
- }
-
- inline void AutoCalibration::Reset()
- {
- MinMaxWindow.Reset(0.f);
- Confidence = 0.f;
- bIsSteady = false;
- MinDeltaGyro = Vec(1.f);
- MinDeltaAccel = Vec(0.25f);
- RecalibrateThreshold = 1.f;
- SensorFusionSkippedTime = 0.f;
- TimeSteadySensorFusion = 0.f;
- TimeSteadyStillness = 0.f;
- }
-
- inline bool AutoCalibration::AddSampleStillness(const Vec& inGyro, const Vec& inAccel, float deltaTime, bool doSensorFusion)
- {
- if (inGyro.x == 0.f && inGyro.y == 0.f && inGyro.z == 0.f &&
- inAccel.x == 0.f && inAccel.y == 0.f && inAccel.z == 0.f)
- {
- // zeroes are almost certainly not valid inputs
- return false;
- }
-
- if (!Settings)
- {
- return false;
- }
-
- if (!CalibrationData)
- {
- return false;
- }
-
- // get settings
- const int minStillnessSamples = Settings->MinStillnessSamples;
- const float minStillnessCollectionTime = Settings->MinStillnessCollectionTime;
- const float minStillnessCorrectionTime = Settings->MinStillnessCorrectionTime;
- const float maxStillnessError = Settings->MaxStillnessError;
- const float stillnessSampleDeteriorationRate = Settings->StillnessSampleDeteriorationRate;
- const float stillnessErrorClimbRate = Settings->StillnessErrorClimbRate;
- const float stillnessErrorDropOnRecalibrate = Settings->StillnessErrorDropOnRecalibrate;
- const float stillnessCalibrationEaseInTime = Settings->StillnessCalibrationEaseInTime;
- const float stillnessCalibrationHalfTime = Settings->StillnessCalibrationHalfTime * Confidence;
- const float stillnessConfidenceRate = Settings->StillnessConfidenceRate;
- const float stillnessGyroDelta = Settings->StillnessGyroDelta;
- const float stillnessAccelDelta = Settings->StillnessAccelDelta;
-
- MinMaxWindow.AddSample(inGyro, inAccel, deltaTime);
- // get deltas
- const Vec gyroDelta = MinMaxWindow.MaxGyro - MinMaxWindow.MinGyro;
- const Vec accelDelta = MinMaxWindow.MaxAccel - MinMaxWindow.MinAccel;
-
- bool calibrated = false;
- bool isSteady = false;
- const Vec climbThisTick = Vec(stillnessSampleDeteriorationRate * deltaTime);
- if (stillnessGyroDelta < 0.f)
- {
- if (Confidence < 1.f)
- {
- MinDeltaGyro += climbThisTick;
- }
- }
- else
- {
- MinDeltaGyro = Vec(stillnessGyroDelta);
- }
- if (stillnessAccelDelta < 0.f)
- {
- if (Confidence < 1.f)
- {
- MinDeltaAccel += climbThisTick;
- }
- }
- else
- {
- MinDeltaAccel = Vec(stillnessAccelDelta);
- }
-
- //printf("Deltas: %.4f %.4f %.4f; %.4f %.4f %.4f\n",
- // gyroDelta.x, gyroDelta.y, gyroDelta.z,
- // accelDelta.x, accelDelta.y, accelDelta.z);
-
- if (MinMaxWindow.NumSamples >= minStillnessSamples && MinMaxWindow.TimeSampled >= minStillnessCollectionTime)
- {
- MinDeltaGyro = MinDeltaGyro.Min(gyroDelta);
- MinDeltaAccel = MinDeltaAccel.Min(accelDelta);
- }
- else
- {
- RecalibrateThreshold = std::min(RecalibrateThreshold + stillnessErrorClimbRate * deltaTime, maxStillnessError);
- return false;
- }
-
- // check that all inputs are below appropriate thresholds to be considered "still"
- if (gyroDelta.x <= MinDeltaGyro.x * RecalibrateThreshold &&
- gyroDelta.y <= MinDeltaGyro.y * RecalibrateThreshold &&
- gyroDelta.z <= MinDeltaGyro.z * RecalibrateThreshold &&
- accelDelta.x <= MinDeltaAccel.x * RecalibrateThreshold &&
- accelDelta.y <= MinDeltaAccel.y * RecalibrateThreshold &&
- accelDelta.z <= MinDeltaAccel.z * RecalibrateThreshold)
- {
- if (MinMaxWindow.NumSamples >= minStillnessSamples && MinMaxWindow.TimeSampled >= minStillnessCorrectionTime)
- {
- /*if (TimeSteadyStillness == 0.f)
- {
- printf("Still!\n");
- }/**/
-
- TimeSteadyStillness = std::min(TimeSteadyStillness + deltaTime, stillnessCalibrationEaseInTime);
- const float calibrationEaseIn = stillnessCalibrationEaseInTime <= 0.f ? 1.f : TimeSteadyStillness / stillnessCalibrationEaseInTime;
-
- const Vec calibratedGyro = MinMaxWindow.GetMidGyro();
-
- const Vec oldGyroBias = Vec(CalibrationData->X, CalibrationData->Y, CalibrationData->Z) / std::max((float)CalibrationData->NumSamples, 1.f);
- const float stillnessLerpFactor = stillnessCalibrationHalfTime <= 0.f ? 0.f : exp2f(-calibrationEaseIn * deltaTime / stillnessCalibrationHalfTime);
- Vec newGyroBias = calibratedGyro.Lerp(oldGyroBias, stillnessLerpFactor);
- Confidence = std::min(Confidence + deltaTime * stillnessConfidenceRate, 1.f);
- isSteady = true;
-
- if (doSensorFusion)
- {
- const Vec previousNormal = MinMaxWindow.StartAccel.Normalized();
- const Vec thisNormal = inAccel.Normalized();
- Vec angularVelocity = thisNormal.Cross(previousNormal);
- const float crossLength = angularVelocity.Length();
- if (crossLength > 0.f)
- {
- const float thisDotPrev = std::clamp(thisNormal.Dot(previousNormal), -1.f, 1.f);
- const float angleChange = acosf(thisDotPrev) * 180.0f / (float)M_PI;
- const float anglePerSecond = angleChange / MinMaxWindow.TimeSampled;
- angularVelocity *= anglePerSecond / crossLength;
- }
-
- Vec axisCalibrationStrength = thisNormal.Abs();
- Vec sensorFusionBias = (calibratedGyro - angularVelocity).Lerp(oldGyroBias, stillnessLerpFactor);
- if (axisCalibrationStrength.x <= 0.7f)
- {
- newGyroBias.x = sensorFusionBias.x;
- }
- if (axisCalibrationStrength.y <= 0.7f)
- {
- newGyroBias.y = sensorFusionBias.y;
- }
- if (axisCalibrationStrength.z <= 0.7f)
- {
- newGyroBias.z = sensorFusionBias.z;
- }
- }
-
- CalibrationData->X = newGyroBias.x;
- CalibrationData->Y = newGyroBias.y;
- CalibrationData->Z = newGyroBias.z;
-
- CalibrationData->AccelMagnitude = MinMaxWindow.MeanAccel.Length();
- CalibrationData->NumSamples = 1;
-
- calibrated = true;
- }
- else
- {
- RecalibrateThreshold = std::min(RecalibrateThreshold + stillnessErrorClimbRate * deltaTime, maxStillnessError);
- }
- }
- else if (TimeSteadyStillness > 0.f)
- {
- //printf("Moved!\n");
- RecalibrateThreshold -= stillnessErrorDropOnRecalibrate;
- if (RecalibrateThreshold < 1.f) RecalibrateThreshold = 1.f;
-
- TimeSteadyStillness = 0.f;
- MinMaxWindow.Reset(0.f);
- }
- else
- {
- RecalibrateThreshold = std::min(RecalibrateThreshold + stillnessErrorClimbRate * deltaTime, maxStillnessError);
- MinMaxWindow.Reset(0.f);
- }
-
- bIsSteady = isSteady;
- return calibrated;
- }
-
- inline void AutoCalibration::NoSampleStillness()
- {
- MinMaxWindow.Reset(0.f);
- }
-
- inline bool AutoCalibration::AddSampleSensorFusion(const Vec& inGyro, const Vec& inAccel, float deltaTime)
- {
- if (deltaTime <= 0.f)
- {
- return false;
- }
-
- if (inGyro.x == 0.f && inGyro.y == 0.f && inGyro.z == 0.f &&
- inAccel.x == 0.f && inAccel.y == 0.f && inAccel.z == 0.f)
- {
- // all zeroes are almost certainly not valid inputs
- TimeSteadySensorFusion = 0.f;
- SensorFusionSkippedTime = 0.f;
- PreviousAccel = inAccel;
- SmoothedPreviousAccel = inAccel;
- SmoothedAngularVelocityGyro = GamepadMotionHelpers::Vec();
- SmoothedAngularVelocityAccel = GamepadMotionHelpers::Vec();
- return false;
- }
-
- if (PreviousAccel.x == 0.f && PreviousAccel.y == 0.f && PreviousAccel.z == 0.f)
- {
- TimeSteadySensorFusion = 0.f;
- SensorFusionSkippedTime = 0.f;
- PreviousAccel = inAccel;
- SmoothedPreviousAccel = inAccel;
- SmoothedAngularVelocityGyro = GamepadMotionHelpers::Vec();
- SmoothedAngularVelocityAccel = GamepadMotionHelpers::Vec();
- return false;
- }
-
- // in case the controller state hasn't updated between samples
- if (inAccel.x == PreviousAccel.x && inAccel.y == PreviousAccel.y && inAccel.z == PreviousAccel.z)
- {
- SensorFusionSkippedTime += deltaTime;
- return false;
- }
-
- if (!Settings)
- {
- return false;
- }
-
- // get settings
- const float sensorFusionCalibrationSmoothingStrength = Settings->SensorFusionCalibrationSmoothingStrength;
- const float sensorFusionAngularAccelerationThreshold = Settings->SensorFusionAngularAccelerationThreshold;
- const float sensorFusionCalibrationEaseInTime = Settings->SensorFusionCalibrationEaseInTime;
- const float sensorFusionCalibrationHalfTime = Settings->SensorFusionCalibrationHalfTime * Confidence;
- const float sensorFusionConfidenceRate = Settings->SensorFusionConfidenceRate;
-
- deltaTime += SensorFusionSkippedTime;
- SensorFusionSkippedTime = 0.f;
- bool calibrated = false;
- bool isSteady = false;
-
- // framerate independent lerp smoothing: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
- const float smoothingLerpFactor = exp2f(-sensorFusionCalibrationSmoothingStrength * deltaTime);
- // velocity from smoothed accel matches better if we also smooth gyro
- const Vec previousGyro = SmoothedAngularVelocityGyro;
- SmoothedAngularVelocityGyro = inGyro.Lerp(SmoothedAngularVelocityGyro, smoothingLerpFactor); // smooth what remains
- const float gyroAccelerationMag = (SmoothedAngularVelocityGyro - previousGyro).Length() / deltaTime;
- // get angle between old and new accel
- const Vec previousNormal = SmoothedPreviousAccel.Normalized();
- const Vec thisAccel = inAccel.Lerp(SmoothedPreviousAccel, smoothingLerpFactor);
- const Vec thisNormal = thisAccel.Normalized();
- Vec angularVelocity = thisNormal.Cross(previousNormal);
- const float crossLength = angularVelocity.Length();
- if (crossLength > 0.f)
- {
- const float thisDotPrev = std::clamp(thisNormal.Dot(previousNormal), -1.f, 1.f);
- const float angleChange = acosf(thisDotPrev) * 180.0f / (float)M_PI;
- const float anglePerSecond = angleChange / deltaTime;
- angularVelocity *= anglePerSecond / crossLength;
- }
- SmoothedAngularVelocityAccel = angularVelocity;
-
- // apply corrections
- if (gyroAccelerationMag > sensorFusionAngularAccelerationThreshold || CalibrationData == nullptr)
- {
- /*if (TimeSteadySensorFusion > 0.f)
- {
- printf("Shaken!\n");
- }/**/
- TimeSteadySensorFusion = 0.f;
- //printf("No calibration due to acceleration of %.4f\n", gyroAccelerationMag);
- }
- else
- {
- /*if (TimeSteadySensorFusion == 0.f)
- {
- printf("Steady!\n");
- }/**/
-
- TimeSteadySensorFusion = std::min(TimeSteadySensorFusion + deltaTime, sensorFusionCalibrationEaseInTime);
- const float calibrationEaseIn = sensorFusionCalibrationEaseInTime <= 0.f ? 1.f : TimeSteadySensorFusion / sensorFusionCalibrationEaseInTime;
- const Vec oldGyroBias = Vec(CalibrationData->X, CalibrationData->Y, CalibrationData->Z) / std::max((float)CalibrationData->NumSamples, 1.f);
- // recalibrate over time proportional to the difference between the calculated bias and the current assumed bias
- const float sensorFusionLerpFactor = sensorFusionCalibrationHalfTime <= 0.f ? 0.f : exp2f(-calibrationEaseIn * deltaTime / sensorFusionCalibrationHalfTime);
- Vec newGyroBias = (SmoothedAngularVelocityGyro - SmoothedAngularVelocityAccel).Lerp(oldGyroBias, sensorFusionLerpFactor);
- Confidence = std::min(Confidence + deltaTime * sensorFusionConfidenceRate, 1.f);
- isSteady = true;
- // don't change bias in axes that can't be affected by the gravity direction
- Vec axisCalibrationStrength = thisNormal.Abs();
- if (axisCalibrationStrength.x > 0.7f)
- {
- axisCalibrationStrength.x = 1.f;
- }
- if (axisCalibrationStrength.y > 0.7f)
- {
- axisCalibrationStrength.y = 1.f;
- }
- if (axisCalibrationStrength.z > 0.7f)
- {
- axisCalibrationStrength.z = 1.f;
- }
- newGyroBias = newGyroBias.Lerp(oldGyroBias, axisCalibrationStrength.Min(Vec(1.f)));
-
- CalibrationData->X = newGyroBias.x;
- CalibrationData->Y = newGyroBias.y;
- CalibrationData->Z = newGyroBias.z;
-
- CalibrationData->AccelMagnitude = thisAccel.Length();
-
- CalibrationData->NumSamples = 1;
-
- calibrated = true;
-
- //printf("Recalibrating at a strength of %.4f\n", calibrationEaseIn);
- }
-
- SmoothedPreviousAccel = thisAccel;
- PreviousAccel = inAccel;
-
- //printf("Gyro: %.4f, %.4f, %.4f | Accel: %.4f, %.4f, %.4f\n",
- // SmoothedAngularVelocityGyro.x, SmoothedAngularVelocityGyro.y, SmoothedAngularVelocityGyro.z,
- // SmoothedAngularVelocityAccel.x, SmoothedAngularVelocityAccel.y, SmoothedAngularVelocityAccel.z);
-
- bIsSteady = isSteady;
-
- return calibrated;
- }
-
- inline void AutoCalibration::NoSampleSensorFusion()
- {
- TimeSteadySensorFusion = 0.f;
- SensorFusionSkippedTime = 0.f;
- PreviousAccel = GamepadMotionHelpers::Vec();
- SmoothedPreviousAccel = GamepadMotionHelpers::Vec();
- SmoothedAngularVelocityGyro = GamepadMotionHelpers::Vec();
- SmoothedAngularVelocityAccel = GamepadMotionHelpers::Vec();
- }
-
- inline void AutoCalibration::SetCalibrationData(GyroCalibration* calibrationData)
- {
- CalibrationData = calibrationData;
- }
-
- inline void AutoCalibration::SetSettings(GamepadMotionSettings* settings)
- {
- Settings = settings;
- }
-
-} // namespace GamepadMotionHelpers
-
-inline GamepadMotion::GamepadMotion()
-{
- IsCalibrating = false;
- CurrentCalibrationMode = GamepadMotionHelpers::CalibrationMode::Manual;
- Reset();
- AutoCalibration.SetCalibrationData(&GyroCalibration);
- AutoCalibration.SetSettings(&Settings);
- Motion.SetSettings(&Settings);
-}
-
-inline void GamepadMotion::Reset()
-{
- GyroCalibration = {};
- Gyro = {};
- RawAccel = {};
- Settings = GamepadMotionSettings();
- Motion.Reset();
-}
-
-inline void GamepadMotion::ProcessMotion(float gyroX, float gyroY, float gyroZ,
- float accelX, float accelY, float accelZ, float deltaTime)
-{
- if (gyroX == 0.f && gyroY == 0.f && gyroZ == 0.f &&
- accelX == 0.f && accelY == 0.f && accelZ == 0.f)
- {
- // all zeroes are almost certainly not valid inputs
- return;
- }
-
- float accelMagnitude = sqrtf(accelX * accelX + accelY * accelY + accelZ * accelZ);
-
- if (IsCalibrating)
- {
- // manual calibration
- PushSensorSamples(gyroX, gyroY, gyroZ, accelMagnitude);
- AutoCalibration.NoSampleSensorFusion();
- AutoCalibration.NoSampleStillness();
- }
- else if (CurrentCalibrationMode & GamepadMotionHelpers::CalibrationMode::Stillness)
- {
- AutoCalibration.AddSampleStillness(GamepadMotionHelpers::Vec(gyroX, gyroY, gyroZ), GamepadMotionHelpers::Vec(accelX, accelY, accelZ), deltaTime, CurrentCalibrationMode & GamepadMotionHelpers::CalibrationMode::SensorFusion);
- AutoCalibration.NoSampleSensorFusion();
- }
- else
- {
- AutoCalibration.NoSampleStillness();
- if (CurrentCalibrationMode & GamepadMotionHelpers::CalibrationMode::SensorFusion)
- {
- AutoCalibration.AddSampleSensorFusion(GamepadMotionHelpers::Vec(gyroX, gyroY, gyroZ), GamepadMotionHelpers::Vec(accelX, accelY, accelZ), deltaTime);
- }
- else
- {
- AutoCalibration.NoSampleSensorFusion();
- }
- }
-
- float gyroOffsetX, gyroOffsetY, gyroOffsetZ;
- GetCalibratedSensor(gyroOffsetX, gyroOffsetY, gyroOffsetZ, accelMagnitude);
-
- gyroX -= gyroOffsetX;
- gyroY -= gyroOffsetY;
- gyroZ -= gyroOffsetZ;
-
- Motion.Update(gyroX, gyroY, gyroZ, accelX, accelY, accelZ, accelMagnitude, deltaTime);
-
- Gyro.x = gyroX;
- Gyro.y = gyroY;
- Gyro.z = gyroZ;
- RawAccel.x = accelX;
- RawAccel.y = accelY;
- RawAccel.z = accelZ;
-}
-
-// reading the current state
-inline void GamepadMotion::GetCalibratedGyro(float& x, float& y, float& z)
-{
- x = Gyro.x;
- y = Gyro.y;
- z = Gyro.z;
-}
-
-inline void GamepadMotion::GetGravity(float& x, float& y, float& z)
-{
- x = Motion.Grav.x;
- y = Motion.Grav.y;
- z = Motion.Grav.z;
-}
-
-inline void GamepadMotion::GetProcessedAcceleration(float& x, float& y, float& z)
-{
- x = Motion.Accel.x;
- y = Motion.Accel.y;
- z = Motion.Accel.z;
-}
-
-inline void GamepadMotion::GetOrientation(float& w, float& x, float& y, float& z)
-{
- w = Motion.Quaternion.w;
- x = Motion.Quaternion.x;
- y = Motion.Quaternion.y;
- z = Motion.Quaternion.z;
-}
-
-inline void GamepadMotion::GetPlayerSpaceGyro(float& x, float& y, const float yawRelaxFactor)
-{
- CalculatePlayerSpaceGyro(x, y, Gyro.x, Gyro.y, Gyro.z, Motion.Grav.x, Motion.Grav.y, Motion.Grav.z, yawRelaxFactor);
-}
-
-inline void GamepadMotion::CalculatePlayerSpaceGyro(float& x, float& y, const float gyroX, const float gyroY, const float gyroZ, const float gravX, const float gravY, const float gravZ, const float yawRelaxFactor)
-{
- // take gravity into account without taking on any error from gravity. Explained in depth at http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc7
- const float worldYaw = -(gravY * gyroY + gravZ * gyroZ);
- const float worldYawSign = worldYaw < 0.f ? -1.f : 1.f;
- y = worldYawSign * std::min(std::abs(worldYaw) * yawRelaxFactor, sqrtf(gyroY * gyroY + gyroZ * gyroZ));
- x = gyroX;
-}
-
-inline void GamepadMotion::GetWorldSpaceGyro(float& x, float& y, const float sideReductionThreshold)
-{
- CalculateWorldSpaceGyro(x, y, Gyro.x, Gyro.y, Gyro.z, Motion.Grav.x, Motion.Grav.y, Motion.Grav.z, sideReductionThreshold);
-}
-
-inline void GamepadMotion::CalculateWorldSpaceGyro(float& x, float& y, const float gyroX, const float gyroY, const float gyroZ, const float gravX, const float gravY, const float gravZ, const float sideReductionThreshold)
-{
- // use the gravity direction as the yaw axis, and derive an appropriate pitch axis. Explained in depth at http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc6
- const float worldYaw = -gravX * gyroX - gravY * gyroY - gravZ * gyroZ;
- // project local pitch axis (X) onto gravity plane
- const float gravDotPitchAxis = gravX;
- GamepadMotionHelpers::Vec pitchAxis(1.f - gravX * gravDotPitchAxis,
- -gravY * gravDotPitchAxis,
- -gravZ * gravDotPitchAxis);
- // normalize
- const float pitchAxisLengthSquared = pitchAxis.LengthSquared();
- if (pitchAxisLengthSquared > 0.f)
- {
- const float pitchAxisLength = sqrtf(pitchAxisLengthSquared);
- const float lengthReciprocal = 1.f / pitchAxisLength;
- pitchAxis *= lengthReciprocal;
-
- const float flatness = std::abs(gravY);
- const float upness = std::abs(gravZ);
- const float sideReduction = sideReductionThreshold <= 0.f ? 1.f : std::clamp((std::max(flatness, upness) - sideReductionThreshold) / sideReductionThreshold, 0.f, 1.f);
-
- x = sideReduction * pitchAxis.Dot(GamepadMotionHelpers::Vec(gyroX, gyroY, gyroZ));
- }
- else
- {
- x = 0.f;
- }
-
- y = worldYaw;
-}
-
-// gyro calibration functions
-inline void GamepadMotion::StartContinuousCalibration()
-{
- IsCalibrating = true;
-}
-
-inline void GamepadMotion::PauseContinuousCalibration()
-{
- IsCalibrating = false;
-}
-
-inline void GamepadMotion::ResetContinuousCalibration()
-{
- GyroCalibration = {};
- AutoCalibration.Reset();
-}
-
-inline void GamepadMotion::GetCalibrationOffset(float& xOffset, float& yOffset, float& zOffset)
-{
- float accelMagnitude;
- GetCalibratedSensor(xOffset, yOffset, zOffset, accelMagnitude);
-}
-
-inline void GamepadMotion::SetCalibrationOffset(float xOffset, float yOffset, float zOffset, int weight)
-{
- if (GyroCalibration.NumSamples > 1)
- {
- GyroCalibration.AccelMagnitude *= ((float)weight) / GyroCalibration.NumSamples;
- }
- else
- {
- GyroCalibration.AccelMagnitude = (float)weight;
- }
-
- GyroCalibration.NumSamples = weight;
- GyroCalibration.X = xOffset * weight;
- GyroCalibration.Y = yOffset * weight;
- GyroCalibration.Z = zOffset * weight;
-}
-
-inline float GamepadMotion::GetAutoCalibrationConfidence()
-{
- return AutoCalibration.Confidence;
-}
-
-inline void GamepadMotion::SetAutoCalibrationConfidence(float newConfidence)
-{
- AutoCalibration.Confidence = newConfidence;
-}
-
-inline bool GamepadMotion::GetAutoCalibrationIsSteady()
-{
- return AutoCalibration.IsSteady();
-}
-
-inline GamepadMotionHelpers::CalibrationMode GamepadMotion::GetCalibrationMode()
-{
- return CurrentCalibrationMode;
-}
-
-inline void GamepadMotion::SetCalibrationMode(GamepadMotionHelpers::CalibrationMode calibrationMode)
-{
- CurrentCalibrationMode = calibrationMode;
-}
-
-inline void GamepadMotion::ResetMotion()
-{
- Motion.Reset();
-}
-
-// Private Methods
-
-inline void GamepadMotion::PushSensorSamples(float gyroX, float gyroY, float gyroZ, float accelMagnitude)
-{
- // accumulate
- GyroCalibration.NumSamples++;
- GyroCalibration.X += gyroX;
- GyroCalibration.Y += gyroY;
- GyroCalibration.Z += gyroZ;
- GyroCalibration.AccelMagnitude += accelMagnitude;
-}
-
-inline void GamepadMotion::GetCalibratedSensor(float& gyroOffsetX, float& gyroOffsetY, float& gyroOffsetZ, float& accelMagnitude)
-{
- if (GyroCalibration.NumSamples <= 0)
- {
- gyroOffsetX = 0.f;
- gyroOffsetY = 0.f;
- gyroOffsetZ = 0.f;
- accelMagnitude = 1.f;
- return;
- }
-
- const float inverseSamples = 1.f / GyroCalibration.NumSamples;
- gyroOffsetX = GyroCalibration.X * inverseSamples;
- gyroOffsetY = GyroCalibration.Y * inverseSamples;
- gyroOffsetZ = GyroCalibration.Z * inverseSamples;
- accelMagnitude = GyroCalibration.AccelMagnitude * inverseSamples;
-}
diff --git a/lib/GamepadMotionHelpers/LICENSE b/lib/GamepadMotionHelpers/LICENSE
deleted file mode 100644
index a46396a..0000000
--- a/lib/GamepadMotionHelpers/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2020-2023 Julian "Jibb" Smart
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/lib/GamepadMotionHelpers/README.md b/lib/GamepadMotionHelpers/README.md
deleted file mode 100644
index c5c1bc9..0000000
--- a/lib/GamepadMotionHelpers/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# GamepadMotionHelpers
-GamepadMotionHelpers is a lightweight header-only library for sensor fusion, gyro calibration, etc. BYO input library (eg [SDL2](https://github.com/libsdl-org/SDL)).
-
-## Units
-Convert your gyro units into **degrees per second** and accelerometer units to **g-force** (1 g = 9.8 m/s^2). You don't have to use these units in your application, but convert to these units when writing to GamepadMotionHelpers and convert back when reading from it. Your input reader might prefer radians per second and metres per second squared, but the datasheets for every IMU I've seen talk about degrees per second and g-force.
-
-## Coordinate Space
-This library uses a Y-up coordinate system. While Z-up is (only slightly) preferable for many games, PlayStation controllers use Y-up, and have set the standard for input libraries like [SDL2](https://github.com/libsdl-org/SDL) and [JSL](https://github.com/JibbSmart/JoyShockLibrary). These libraries convert inputs from other controller types to the same space used by PlayStation's DualShock 4 and DualSense, so that's what's used here.
-
-## Basic Use
-Include the GamepadMotion.hpp file in your C++ project. That's it! Everything you need is in that file, and its only dependency is ``````.
-
-For each controller with gyro (and optionally accelerometer), create a ```GamepadMotion``` object. At regular intervals, whether when a new report comes in from the controller or when polling the controller's state, you should call ```ProcessMotion(...)```. This is when you tell your GamepadMotion object the latest gyro (in degrees per second) and accelerometer (in g-force) inputs. You'll also give it the time since the last update for this controller (in seconds).
-
-ProcessMotion takes these inputs, updates some internal values, and then you can use any of the following to read its current state:
-- ```GetCalibratedGyro(float& x, float& y, float& z)``` - Get the controller's angular velocity in degrees per second. This is just the raw gyro you gave it minus the gyro's bias as determined by your calibration settings (more on that below).
-- ```GetGravity(float& x, float& y, float& z)``` - Get the gravity direction in the controller's local space. When the controller is still on a flat surface it'll be approximately (0, -1, 0). The controller can't detect the gravity direction when it's in freefall or being shaken around, but it can make a pretty good guess if its gyro is correctly calibrated and then make further corrections when the controller is still again.
-- ```GetProcessedAcceleration(float& x, float& y, float& z)``` - Get the controller's current acceleration in g-force with gravity removed. Raw accelerometer input includes gravity -- it is only (0, 0, 0) when the controller is in freefall. However, using the gravity direction as calculated for GetGravity, it can remove that component and detect how you're shaking the controller about. This function gives you that acceleration vector with the gravity removed.
-- ```GetOrientation(float& w, float& x, float& y, float& z)``` - Get the controller's orientation. Gyro and accelerometer input are combined to give a good estimate of the controller's orientation.
-
-Additional helper functions are available for taking gravity into account and returning a "world space" or "player space" rotation in two axes. Bear in mind that the **X** and **Y** set by these functions is still around the controller's axes. This means **Y** is the *horizontal* part of the rotation, and **X** is the vertical part. To convert to a mouse-like input, you'll treat the **Y** as the horizontal or yaw input and **X** as the vertical or pitch input. This might be unintuitive, but since it's also true of the "local space" angular velocities obtained from GetCalibratedGyro, this makes it simple to let the user choose between *local space*, *world space*, and *player space* in your game or application by just swapping GetCalibratedGyro for these functions depending on that selection:
-- ```GetWorldSpaceGyro(float& x, float& y, const float sideReductionThreshold = 0.125f)``` - Get the controller's angular velocity in *world space* as described on GyroWiki in the [player space article here](http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc6). Yaw input will be derived from motion around the gravity axis, and pitch input from an appropriate pitch axis calculated from the controller's orientation with respect to the gravity axis. Any errors in the calculated gravity axis (though likely very small) will be taken on by the calculated world space gyro rotation, making it slightly less robust than using calibrated gyro directly ("local space" gyro) or using *player space* gyro below. More info in the linked article.
-- ```GetPlayerSpaceGyro(float& x, float& y, const float yawRelaxFactor = 1.41f)``` - Get the controller's angular velocity in *player space* as described on GyroWiki in the [player space article here](http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained#toc7). Yaw input will be derived from motion approximately around the gravity axis, without any impact from errors in the gravity calculation. Pitch is just local pitch. It is robust, accommodates players who are used to both local space and world space gyro, while taking on most of the advantages of each. It is proven in popular games and is an ideal default for players using a standalone controller. For handheld (where the screen is part of the controller, such as mobile, Switch, or Steam Deck) local space (using the calibrated gyro input directly) may be preferable. More info in the linked article.
-
-If you want to plug in the gyro and gravity values yourself (perhaps you're using an externally calculated gravity), you can use ```CalculateWorldSpaceGyro``` and ```CalculatePlayerSpaceGyro``` instead. Make sure you use this GamepadMotionHelpers' coordinate space, units, and gravity is normalized, since those are all assumed for these functions.
-
-## Sensor Fusion
-Combining multiple types of sensor like this to get a better picture of the controller's state is called "sensor fusion". Moment-to-moment changes in orientation are detected using the gyro, but that only gives local angular velocity and needs to be correctly calibrated. Errors can accumulate over time. The gravity vector as detected by the accelerometer is used to make corrections to the relevant components of the controller's orientation.
-
-But this cannot be used to correct the controller's orientation around the gravity vector (the **yaw** axis). If you're using the controller's absolute orientation for some reason, this "yaw drift" may need to be accounted for somehow. Some devices also have a magnetometer (compass) to counter yaw drift, but since popular game controllers don't have a magnetometer, I haven't tried it myself. In future, if I get such a device, I'd like to add the option for GamepadMotionHelpers to accept magnetometer input and account for it when calculating values for the above functions.
-
-## Gyro Calibration
-Modern gyroscopes often need calibration. This is like how a [weighing scale](https://en.wikipedia.org/wiki/Weighing_scale) can need calibration to tell it what 'zero' is. Like a weighing scale, a correctly calibrated gyroscope will give an accurate reading. If you're using the gyro input as a mouse, which is the simplest application of a controller's gyro, you can find essential reading on [GyroWiki here](http://gyrowiki.jibbsmart.com/blog:good-gyro-controls-part-1:the-gyro-is-a-mouse).
-
-Calibration just means having the controller sit still and remembering the average reported angular velocity in each axis. This is the gyro's "bias". In GamepadMotionHelpers, I call our best guess at the controller's bias the "calibration offset". GamepadMotionHelpers has some options to help with calibrating:
-
-At any time, you can begin manually calibrating a controller by calling ```StartContinuousCalibration()```. This will start recording the average angular velocity and apply it immediately to any subsequent **GetGalibratedGyro(...)** call. At any time you can ```PauseContinuousCalibration()``` to no longer add current values to the average angular velocity being recorded. You can ```ResetContinousCalibration()``` to remove the recorded average before starting over with **StartContinuousCalibration** again.
-
-You can read the stored calibration values using ```GetCalibrationOffset(float& xOffset, float& yOffset, float& zOffset)```. You can manually set the calibration offset yourself with ```SetCalibrationOffset(float xOffset, float yOffset, float zOffset, int weight)```. This will override all stored values. The **weight** argument at the end determines how strongly these values should be considered over time if Continuous Calibration is still active (new values are still being added to the average). Each new sample has a weight of 1, so if you **SetCalibrationOffset** with a weight of 10, it'll have the weight of 10 samples when calculating the average. If you're not continuing to add samples (Continuous Calibration is not active), the weight will be meaningless. Setting this manually is unusual, so don't worry about it too much if that sounds complicated.
-
-Most games don't ask the user to calibrate the gyro themselves. They have built-in automatic calibration, which I like to call "auto-calibration". There's no such thing as a "good enough" auto-calibration solution -- at least not with only gyro and accelerometer. Every game that has an auto-calibration solution would be made better for more serious players with the option to manually calibrate their gyro, so I urge you to provide players the option to do the same in your game. Having said that, auto-calibration is a useful option for casual players, and you may choose to have it enabled in your game by default.
-
-So GamepadMotionHelpers provides some auto-calibration options. You can call ```SetCalibrationMode(CalibrationMode)``` on each GamepadMotion instance with the following options:
-- ```CalibrationMode::Manual``` - No auto-calibration. This is the default.
-- ```CalibrationMode::Stillness``` - Automatically try to detect when the controller is being held still and update the calibration offset accordingly.
-- ```CalibrationMode::SensorFusion``` - Calculate an angular velocity from changes in the gravity direction as detected by the accelerometer. If these are steady enough, use them to make corrections to the calibration offset. This will only apply to relevant axes.
-
-Many players are already aware of the shortcomings of trying to automatically detect stillness to automatically calibrate the gyro. Whether on Switch, PlayStation, or using PlayStation controllers on PC, players have tried to track a slow or distant target only to have the aimer suddenly stop moving! The game or the platform has **misinterpreted their slow and steady input as the controller being held still**, and they've incorrectly recalibrated accordingly. Players *hate it* when this happens.
-
-**This is why it's important to let players manually calibrate their gyro** if they want to.
-
-Auto-calibration is used so widely in console games that it's speculated that game developers may not have the option to disable it on these platforms. If this is the case, GamepadMotionHelpers offers a big advantage over those platforms: you can disable it and enable it at any time.
-
-You, the game developer, can have your game tell if the player is tracking a distant or slow-moving target. You can tell if the player's aimer is moving towards a visible target or roughly following the movement of one. When it is, maybe disabling the auto-calibration (```SetCalibrationMode(CalibrationMode::Manual)```) could be the difference between good and bad auto-calibration. I don't know if the GamepadMotionHelpers auto-calibration functions are better or worse than their Switch and PlayStation counterparts generally, but by letting you take the game's context into account, you may be able to offer players a way better experience without them having to manually calibrate.
-
-But still give them the option to calibrate manually, please :)
-
-The **SensorFusion** calibration mode has shortcomings of its own. It's much harder to accidentally trick the game into incorrectly calibrating, but the angular velocity calculated from the accelerometer moment-to-moment is generally much less precise. Leaving the controller still, you'll notice the calibrated gyro moving slightly up and down over time. So while the **Stillness** mode is characterised by good behaviour occasionally punctuated by frustrating errors, the **SensorFusion** mode will tend to be more consistently not-quite-right without being terrible.
-
-Secondly, this library currently only combines accelerometer and gyro, so the **SensorFusion** auto-calibration cannot correct the gyro in all axes at the same time. The **SensorFusion**-only mode will be more useful in future when magnetometer input is supported, which can account for the axes that the accelerometer can't.
-
-Both auto-calibration modes can be combined by passing ```CalibrationMode::Stillness | CalibrationMode::SensorFusion``` to **SetCalibrationMode**. In this case, it'll use **Stillness** auto-calibration, but it'll adjust the calibration offset based on any angular velocity implied by changes in the accelerometer input. This tends to give better results than just using **Stillness** or **SensorFusion** on their own.
-
-If you aren't sure what to choose, I'd suggest using the combined ```CalibrationMode::Stillness | CalibrationMode::SensorFusion``` when auto calibration is enabled, but also allowing the player to manually calibrate.
-
-**TODO** This is a clunky way to let the user set up what is obviously the best solution. Maybe I should just call it "hybrid" or something and be done with it?
-
-Auto-calibration can also be used to communicate manual calibration to the player. ```GetAutoCalibrationIsSteady()``` will tell you whether GamepadMotionHelpers thinks the controller is currently being held steady (if auto-calibration is enabled). ```GetAutoCalibrationConfidence()``` will tell you how confident GamepadMotionHelpers is that it has a good calibration value from auto-calibration, from 0-1. Higher confidence means that new calibration changes will be applied more gradually. You can use these functions to detect when a controller needs to be calibrated, prompt the player to put their controller down, detect when they have put their controller down, and show progress for calibration (default 1 second once it starts). You can also override the confidence yourself (```SetAutoCalibrationConfidence()```), and resetting calibration will reset confidence to 0. How quickly confidence grows as well as other calibration settings can be customised in **GamepadMotionSettings**.
-
-## In the Wild
-GamepadMotionHelpers is currently used in:
-- [JoyShockMapper](https://github.com/Electronicks/JoyShockMapper)
-- [JoyShockLibrary](https://github.com/JibbSmart/JoyShockLibrary)
-- JoyShockOverlay
-
-If you know of any other games or applications using GamepadMotionHelpers, please let me know!
\ No newline at end of file
diff --git a/lib/N64ModernRuntime b/lib/N64ModernRuntime
index e8d7aec..8441e22 160000
--- a/lib/N64ModernRuntime
+++ b/lib/N64ModernRuntime
@@ -1 +1 @@
-Subproject commit e8d7aec1bb7947fc15d8e521c0d5c4af8c0bcc3f
+Subproject commit 8441e2252a840bd65477d2f549b0ca37f024754f
diff --git a/lib/RecompFrontend b/lib/RecompFrontend
new file mode 160000
index 0000000..8a58012
--- /dev/null
+++ b/lib/RecompFrontend
@@ -0,0 +1 @@
+Subproject commit 8a58012d2083a40cb1ebb537a4c828dcf5724d74
diff --git a/lib/RmlUi b/lib/RmlUi
deleted file mode 160000
index 7a06f27..0000000
--- a/lib/RmlUi
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 7a06f27db04fe5d13a5dacc19b2b4544673a4eca
diff --git a/lib/freetype-windows-binaries b/lib/freetype-windows-binaries
deleted file mode 160000
index d6fb49d..0000000
--- a/lib/freetype-windows-binaries
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d6fb49d11a9d0011bf4ecfe7e570beaaa189838a
diff --git a/lib/lunasvg b/lib/lunasvg
deleted file mode 160000
index 4166d0c..0000000
--- a/lib/lunasvg
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 4166d0cccfc059b39d5ecfc372524375e59448f9
diff --git a/patches/recompui_event_structs.h b/patches/recompui_event_structs.h
index 914160d..5495081 100644
--- a/patches/recompui_event_structs.h
+++ b/patches/recompui_event_structs.h
@@ -1,7 +1,7 @@
#ifndef __UI_FUNCS_H__
#define __UI_FUNCS_H__
-// These two enums must be kept in sync with src/ui/elements/ui_types.h!
+// These three enums must be kept in sync with src/ui/elements/ui_types.h!
typedef enum {
UI_EVENT_NONE,
UI_EVENT_CLICK,
@@ -11,6 +11,9 @@ typedef enum {
UI_EVENT_DRAG,
UI_EVENT_RESERVED1, // Would be UI_EVENT_TEXT but text events aren't usable in mods currently
UI_EVENT_UPDATE,
+ UI_EVENT_NAVIGATE,
+ UI_EVENT_MOUSE_BUTTON,
+ UI_EVENT_MENU_ACTION,
UI_EVENT_COUNT
} RecompuiEventType;
@@ -21,6 +24,16 @@ typedef enum {
UI_DRAG_END
} RecompuiDragPhase;
+typedef enum {
+ UI_MENU_ACTION_NONE,
+ UI_MENU_ACTION_ACCEPT,
+ UI_MENU_ACTION_APPLY,
+ UI_MENU_ACTION_BACK,
+ UI_MENU_ACTION_TOGGLE,
+ UI_MENU_ACTION_TAB_LEFT,
+ UI_MENU_ACTION_TAB_RIGHT
+} RecompuiMenuAction;
+
typedef struct {
RecompuiEventType type;
union {
@@ -46,6 +59,10 @@ typedef struct {
float y;
RecompuiDragPhase phase;
} drag;
+
+ struct {
+ RecompuiMenuAction action;
+ } menu_action;
} data;
} RecompuiEventData;
diff --git a/src/game/config.cpp b/src/game/config.cpp
index 6e90bf8..098cdd8 100644
--- a/src/game/config.cpp
+++ b/src/game/config.cpp
@@ -1,10 +1,14 @@
#include "banjo_config.h"
-#include "recomp_input.h"
+#include "recompui/recompui.h"
+#include "recompui/config.h"
+#include "recompinput/recompinput.h"
#include "banjo_sound.h"
#include "banjo_render.h"
#include "banjo_support.h"
#include "ultramodern/config.hpp"
#include "librecomp/files.hpp"
+#include "librecomp/config.hpp"
+#include "util/file.h"
#include
#include
#include
@@ -18,511 +22,125 @@
#include "apple/rt64_apple.h"
#endif
-constexpr std::u8string_view general_filename = u8"general.json";
-constexpr std::u8string_view graphics_filename = u8"graphics.json";
-constexpr std::u8string_view controls_filename = u8"controls.json";
-constexpr std::u8string_view sound_filename = u8"sound.json";
+static void add_general_options(recomp::config::Config &config) {
+ using EnumOptionVector = const std::vector;
-constexpr auto res_default = ultramodern::renderer::Resolution::Auto;
-constexpr auto hr_default = ultramodern::renderer::HUDRatioMode::Clamp16x9;
-constexpr auto api_default = ultramodern::renderer::GraphicsApi::Auto;
-constexpr auto ar_default = ultramodern::renderer::AspectRatio::Expand;
-constexpr auto msaa_default = ultramodern::renderer::Antialiasing::MSAA2X;
-constexpr auto rr_default = ultramodern::renderer::RefreshRate::Display;
-constexpr auto hpfb_default = ultramodern::renderer::HighPrecisionFramebuffer::Off;
-constexpr int ds_default = 1;
-constexpr int rr_manual_default = 60;
-constexpr bool developer_mode_default = false;
+ static EnumOptionVector note_saving_mode_options = {
+ {banjo::NoteSavingMode::Off, "Off", "Off"},
+ {banjo::NoteSavingMode::On, "On", "On"},
+ };
+ config.add_enum_option(
+ banjo::configkeys::general::note_saving_mode,
+ "Note Saving",
+ "Saves collected notes so that you don't need to collect them again when revisiting a level. On is the default, while off matches the original game.",
+ note_saving_mode_options,
+ banjo::NoteSavingMode::On
+ );
-static bool is_steam_deck = false;
+ static EnumOptionVector camera_invert_mode_options = {
+ {banjo::CameraInvertMode::InvertNone, "InvertNone", "None"},
+ {banjo::CameraInvertMode::InvertX, "InvertX", "Invert X"},
+ {banjo::CameraInvertMode::InvertY, "InvertY", "Invert Y"},
+ {banjo::CameraInvertMode::InvertBoth, "InvertBoth", "Invert Both"}
+ };
+ config.add_enum_option(
+ banjo::configkeys::general::camera_invert_mode,
+ "Aiming Camera Inverting",
+ // TODO: Update for banjo
+ "Inverts the camera controls. Invert Y is the default and matches the original game.",
+ camera_invert_mode_options,
+ banjo::CameraInvertMode::InvertY
+ );
-ultramodern::renderer::WindowMode wm_default() {
- return is_steam_deck ? ultramodern::renderer::WindowMode::Fullscreen : ultramodern::renderer::WindowMode::Windowed;
-}
-
-#ifdef __gnu_linux__
-void detect_steam_deck() {
- // Check if the board vendor is Valve.
- std::ifstream board_vendor_file("/sys/devices/virtual/dmi/id/board_vendor");
- std::string line;
- if (std::getline(board_vendor_file, line).good() && line == "Valve") {
- is_steam_deck = true;
- return;
- }
-
- // Check if the SteamDeck variable is set to 1.
- const char* steam_deck_env = getenv("SteamDeck");
- if (steam_deck_env != nullptr && std::string{steam_deck_env} == "1") {
- is_steam_deck = true;
- return;
- }
-
- is_steam_deck = false;
- return;
-}
-#else
-void detect_steam_deck() { is_steam_deck = false; }
-#endif
-
-template
-T from_or_default(const json& j, const std::string& key, T default_value) {
- T ret;
- auto find_it = j.find(key);
- if (find_it != j.end()) {
- find_it->get_to(ret);
- }
- else {
- ret = default_value;
- }
-
- return ret;
-}
-
-template
-void call_if_key_exists(void (*func)(T), const json& j, const std::string& key) {
- auto find_it = j.find(key);
- if (find_it != j.end()) {
- T val;
- find_it->get_to(val);
- func(val);
- }
-}
-
-namespace ultramodern {
- void to_json(json& j, const renderer::GraphicsConfig& config) {
- j = json{
- {"res_option", config.res_option},
- {"wm_option", config.wm_option},
- {"hr_option", config.hr_option},
- {"api_option", config.api_option},
- {"ds_option", config.ds_option},
- {"ar_option", config.ar_option},
- {"msaa_option", config.msaa_option},
- {"rr_option", config.rr_option},
- {"hpfb_option", config.hpfb_option},
- {"rr_manual_value", config.rr_manual_value},
- {"developer_mode", config.developer_mode},
- };
- }
-
- void from_json(const json& j, renderer::GraphicsConfig& config) {
- config.res_option = from_or_default(j, "res_option", res_default);
- config.wm_option = from_or_default(j, "wm_option", wm_default());
- config.hr_option = from_or_default(j, "hr_option", hr_default);
- config.api_option = from_or_default(j, "api_option", api_default);
- config.ds_option = from_or_default(j, "ds_option", ds_default);
- config.ar_option = from_or_default(j, "ar_option", ar_default);
- config.msaa_option = from_or_default(j, "msaa_option", msaa_default);
- config.rr_option = from_or_default(j, "rr_option", rr_default);
- config.hpfb_option = from_or_default(j, "hpfb_option", hpfb_default);
- config.rr_manual_value = from_or_default(j, "rr_manual_value", rr_manual_default);
- config.developer_mode = from_or_default(j, "developer_mode", developer_mode_default);
- }
-}
-
-namespace recomp {
- void to_json(json& j, const InputField& field) {
- j = json{ {"input_type", field.input_type}, {"input_id", field.input_id} };
- }
-
- void from_json(const json& j, InputField& field) {
- j.at("input_type").get_to(field.input_type);
- j.at("input_id").get_to(field.input_id);
- }
-}
-
-std::filesystem::path banjo::get_app_folder_path() {
- // directly check for portable.txt (windows and native linux binary)
- if (std::filesystem::exists("portable.txt")) {
- return std::filesystem::current_path();
- }
-
-#if defined(__APPLE__)
- // Check for portable file in the directory containing the app bundle.
- const auto app_bundle_path = banjo::get_bundle_directory().parent_path();
- if (std::filesystem::exists(app_bundle_path / "portable.txt")) {
- return app_bundle_path;
- }
-#endif
-
- std::filesystem::path recomp_dir{};
-
-#if defined(_WIN32)
- // Deduce local app data path.
- PWSTR known_path = NULL;
- HRESULT result = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &known_path);
- if (result == S_OK) {
- recomp_dir = std::filesystem::path{known_path} / banjo::program_id;
- }
-
- CoTaskMemFree(known_path);
-#elif defined(__linux__) || defined(__APPLE__)
- // check for APP_FOLDER_PATH env var
- if (getenv("APP_FOLDER_PATH") != nullptr) {
- return std::filesystem::path{getenv("APP_FOLDER_PATH")};
- }
-
-#if defined(__APPLE__)
- const auto supportdir = banjo::get_application_support_directory();
- if (supportdir) {
- return *supportdir / banjo::program_id;
- }
-#endif
-
- const char *homedir;
-
- if ((homedir = getenv("HOME")) == nullptr) {
- #if defined(__linux__)
- homedir = getpwuid(getuid())->pw_dir;
- #elif defined(__APPLE__)
- homedir = GetHomeDirectory();
- #endif
- }
-
- if (homedir != nullptr) {
- recomp_dir = std::filesystem::path{homedir} / (std::u8string{u8".config/"} + std::u8string{banjo::program_id});
- }
-#endif
-
- return recomp_dir;
-}
-
-bool read_json(std::ifstream input_file, nlohmann::json& json_out) {
- if (!input_file.good()) {
- return false;
- }
-
- try {
- input_file >> json_out;
- }
- catch (nlohmann::json::parse_error&) {
- return false;
- }
- return true;
-}
-
-bool read_json_with_backups(const std::filesystem::path& path, nlohmann::json& json_out) {
- // Try reading and parsing the base file.
- if (read_json(std::ifstream{path}, json_out)) {
- return true;
- }
-
- // Try reading and parsing the backup file.
- if (read_json(recomp::open_input_backup_file(path), json_out)) {
- return true;
- }
-
- // Both reads failed.
- return false;
-}
-
-bool save_json_with_backups(const std::filesystem::path& path, const nlohmann::json& json_data) {
- {
- std::ofstream output_file = recomp::open_output_file_with_backup(path);
- if (!output_file.good()) {
- return false;
- }
-
- output_file << std::setw(4) << json_data;
- }
- return recomp::finalize_output_file_with_backup(path);
-}
-
-bool save_general_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
-
- recomp::to_json(config_json["background_input_mode"], recomp::get_background_input_mode());
- config_json["rumble_strength"] = recomp::get_rumble_strength();
- config_json["gyro_sensitivity"] = recomp::get_gyro_sensitivity();
- config_json["mouse_sensitivity"] = recomp::get_mouse_sensitivity();
- config_json["joystick_deadzone"] = recomp::get_joystick_deadzone();
- config_json["camera_invert_mode"] = banjo::get_camera_invert_mode();
- config_json["analog_cam_mode"] = banjo::get_analog_cam_mode();
- config_json["analog_camera_invert_mode"] = banjo::get_analog_camera_invert_mode();
- config_json["note_saving_mode"] = banjo::get_note_saving_mode();
- config_json["debug_mode"] = banjo::get_debug_mode_enabled();
-
- return save_json_with_backups(path, config_json);
-}
-
-void set_general_settings_from_json(const nlohmann::json& config_json) {
- recomp::set_background_input_mode(from_or_default(config_json, "background_input_mode", recomp::BackgroundInputMode::On));
- recomp::set_rumble_strength(from_or_default(config_json, "rumble_strength", 25));
- recomp::set_gyro_sensitivity(from_or_default(config_json, "gyro_sensitivity", 50));
- recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", is_steam_deck ? 50 : 0));
- recomp::set_joystick_deadzone(from_or_default(config_json, "joystick_deadzone", 5));
- banjo::set_camera_invert_mode(from_or_default(config_json, "camera_invert_mode", banjo::CameraInvertMode::InvertY));
- banjo::set_analog_cam_mode(from_or_default(config_json, "analog_cam_mode", banjo::AnalogCamMode::Off));
- banjo::set_analog_camera_invert_mode(from_or_default(config_json, "analog_camera_invert_mode", banjo::CameraInvertMode::InvertNone));
- banjo::set_note_saving_mode(from_or_default(config_json, "note_saving_mode", banjo::NoteSavingMode::On));
- banjo::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false));
-}
-
-bool load_general_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
- if (!read_json_with_backups(path, config_json)) {
- return false;
- }
-
- set_general_settings_from_json(config_json);
- return true;
-}
-
-void assign_mapping(recomp::InputDevice device, recomp::GameInput input, const std::vector& value) {
- for (size_t binding_index = 0; binding_index < std::min(value.size(), recomp::bindings_per_input); binding_index++) {
- recomp::set_input_binding(input, binding_index, device, value[binding_index]);
- }
-};
-
-// same as assign_mapping, except will clear unassigned bindings if not in value
-void assign_mapping_complete(recomp::InputDevice device, recomp::GameInput input, const std::vector& value) {
- for (size_t binding_index = 0; binding_index < recomp::bindings_per_input; binding_index++) {
- if (binding_index >= value.size()) {
- recomp::set_input_binding(input, binding_index, device, recomp::InputField{});
- } else {
- recomp::set_input_binding(input, binding_index, device, value[binding_index]);
- }
- }
-};
-
-void assign_all_mappings(recomp::InputDevice device, const recomp::DefaultN64Mappings& values) {
- assign_mapping_complete(device, recomp::GameInput::A, values.a);
- assign_mapping_complete(device, recomp::GameInput::B, values.b);
- assign_mapping_complete(device, recomp::GameInput::Z, values.z);
- assign_mapping_complete(device, recomp::GameInput::START, values.start);
- assign_mapping_complete(device, recomp::GameInput::DPAD_UP, values.dpad_up);
- assign_mapping_complete(device, recomp::GameInput::DPAD_DOWN, values.dpad_down);
- assign_mapping_complete(device, recomp::GameInput::DPAD_LEFT, values.dpad_left);
- assign_mapping_complete(device, recomp::GameInput::DPAD_RIGHT, values.dpad_right);
- assign_mapping_complete(device, recomp::GameInput::L, values.l);
- assign_mapping_complete(device, recomp::GameInput::R, values.r);
- assign_mapping_complete(device, recomp::GameInput::C_UP, values.c_up);
- assign_mapping_complete(device, recomp::GameInput::C_DOWN, values.c_down);
- assign_mapping_complete(device, recomp::GameInput::C_LEFT, values.c_left);
- assign_mapping_complete(device, recomp::GameInput::C_RIGHT, values.c_right);
-
- assign_mapping_complete(device, recomp::GameInput::X_AXIS_NEG, values.analog_left);
- assign_mapping_complete(device, recomp::GameInput::X_AXIS_POS, values.analog_right);
- assign_mapping_complete(device, recomp::GameInput::Y_AXIS_NEG, values.analog_down);
- assign_mapping_complete(device, recomp::GameInput::Y_AXIS_POS, values.analog_up);
-
- assign_mapping_complete(device, recomp::GameInput::TOGGLE_MENU, values.toggle_menu);
- assign_mapping_complete(device, recomp::GameInput::ACCEPT_MENU, values.accept_menu);
- assign_mapping_complete(device, recomp::GameInput::APPLY_MENU, values.apply_menu);
-};
-
-void banjo::reset_input_bindings() {
- assign_all_mappings(recomp::InputDevice::Keyboard, recomp::default_n64_keyboard_mappings);
- assign_all_mappings(recomp::InputDevice::Controller, recomp::default_n64_controller_mappings);
-}
-
-void banjo::reset_cont_input_bindings() {
- assign_all_mappings(recomp::InputDevice::Controller, recomp::default_n64_controller_mappings);
-}
-
-void banjo::reset_kb_input_bindings() {
- assign_all_mappings(recomp::InputDevice::Keyboard, recomp::default_n64_keyboard_mappings);
-}
-
-void banjo::reset_single_input_binding(recomp::InputDevice device, recomp::GameInput input) {
- assign_mapping_complete(
- device,
- input,
- recomp::get_default_mapping_for_input(
- device == recomp::InputDevice::Keyboard ?
- recomp::default_n64_keyboard_mappings :
- recomp::default_n64_controller_mappings,
- input
- )
+ static EnumOptionVector analog_cam_mode_options = {
+ {banjo::AnalogCamMode::Off, "Off", "Off"},
+ {banjo::AnalogCamMode::On, "On", "On"},
+ };
+ config.add_enum_option(
+ banjo::configkeys::general::analog_cam_mode,
+ "Analog Camera",
+ // TODO: Update for banjo
+ "Enables the analog camera.",
+ analog_cam_mode_options,
+ banjo::AnalogCamMode::Off
+ );
+ config.add_enum_option(
+ banjo::configkeys::general::analog_camera_invert_mode,
+ "Analog Camera Inverting",
+ // TODO: Update for banjo
+ "Inverts the camera controls for the analog camera if it's enabled. None is the default.",
+ camera_invert_mode_options,
+ banjo::CameraInvertMode::InvertNone
+ );
+ config.add_option_disable_dependency(
+ banjo::configkeys::general::analog_camera_invert_mode,
+ banjo::configkeys::general::analog_cam_mode,
+ banjo::AnalogCamMode::Off
);
}
-void reset_graphics_options() {
- ultramodern::renderer::GraphicsConfig new_config{};
- new_config.res_option = res_default;
- new_config.wm_option = wm_default();
- new_config.hr_option = hr_default;
- new_config.ds_option = ds_default;
- new_config.ar_option = ar_default;
- new_config.msaa_option = msaa_default;
- new_config.rr_option = rr_default;
- new_config.hpfb_option = hpfb_default;
- new_config.rr_manual_value = rr_manual_default;
- new_config.developer_mode = developer_mode_default;
- ultramodern::renderer::set_graphics_config(new_config);
+template
+T get_general_config_enum_value(const std::string& option_id) {
+ return static_cast(std::get(recompui::config::get_general_config().get_option_value(option_id)));
}
-bool save_graphics_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
- ultramodern::to_json(config_json, ultramodern::renderer::get_graphics_config());
- return save_json_with_backups(path, config_json);
+banjo::NoteSavingMode banjo::get_note_saving_mode() {
+ return get_general_config_enum_value(banjo::configkeys::general::note_saving_mode);
}
-bool load_graphics_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
- if (!read_json_with_backups(path, config_json)) {
- return false;
- }
-
- ultramodern::renderer::GraphicsConfig new_config{};
- ultramodern::from_json(config_json, new_config);
- ultramodern::renderer::set_graphics_config(new_config);
- return true;
+banjo::CameraInvertMode banjo::get_camera_invert_mode() {
+ return get_general_config_enum_value(banjo::configkeys::general::camera_invert_mode);
}
-void add_input_bindings(nlohmann::json& out, recomp::GameInput input, recomp::InputDevice device) {
- const std::string& input_name = recomp::get_input_enum_name(input);
- nlohmann::json& out_array = out[input_name];
- out_array = nlohmann::json::array();
- for (size_t binding_index = 0; binding_index < recomp::bindings_per_input; binding_index++) {
- out_array[binding_index] = recomp::get_input_binding(input, binding_index, device);
- }
-};
-
-bool save_controls_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
-
- config_json["keyboard"] = {};
- config_json["controller"] = {};
-
- for (size_t i = 0; i < recomp::get_num_inputs(); i++) {
- recomp::GameInput cur_input = static_cast(i);
-
- add_input_bindings(config_json["keyboard"], cur_input, recomp::InputDevice::Keyboard);
- add_input_bindings(config_json["controller"], cur_input, recomp::InputDevice::Controller);
- }
-
- return save_json_with_backups(path, config_json);
+banjo::CameraInvertMode banjo::get_analog_camera_invert_mode() {
+ return get_general_config_enum_value(banjo::configkeys::general::analog_camera_invert_mode);
}
-bool load_input_device_from_json(const nlohmann::json& config_json, recomp::InputDevice device, const std::string& key) {
- // Check if the json object for the given key exists.
- auto find_it = config_json.find(key);
- if (find_it == config_json.end()) {
- return false;
- }
-
- const nlohmann::json& mappings_json = *find_it;
-
- for (size_t i = 0; i < recomp::get_num_inputs(); i++) {
- recomp::GameInput cur_input = static_cast(i);
- const std::string& input_name = recomp::get_input_enum_name(cur_input);
-
- // Check if the json object for the given input exists and that it's an array.
- auto find_input_it = mappings_json.find(input_name);
- if (find_input_it == mappings_json.end() || !find_input_it->is_array()) {
- assign_mapping(
- device,
- cur_input,
- recomp::get_default_mapping_for_input(
- device == recomp::InputDevice::Keyboard ?
- recomp::default_n64_keyboard_mappings :
- recomp::default_n64_controller_mappings,
- cur_input
- )
- );
- continue;
- }
- const nlohmann::json& input_json = *find_input_it;
-
- // Deserialize all the bindings from the json array (up to the max number of bindings per input).
- for (size_t binding_index = 0; binding_index < std::min(recomp::bindings_per_input, input_json.size()); binding_index++) {
- recomp::InputField cur_field{};
- recomp::from_json(input_json[binding_index], cur_field);
- recomp::set_input_binding(cur_input, binding_index, device, cur_field);
- }
- }
-
- return true;
+banjo::AnalogCamMode banjo::get_analog_cam_mode() {
+ return get_general_config_enum_value(banjo::configkeys::general::analog_cam_mode);
}
-bool load_controls_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
- if (!read_json_with_backups(path, config_json)) {
- return false;
- }
-
- if (!load_input_device_from_json(config_json, recomp::InputDevice::Keyboard, "keyboard")) {
- assign_all_mappings(recomp::InputDevice::Keyboard, recomp::default_n64_keyboard_mappings);
- }
-
- if (!load_input_device_from_json(config_json, recomp::InputDevice::Controller, "controller")) {
- assign_all_mappings(recomp::InputDevice::Controller, recomp::default_n64_controller_mappings);
- }
- return true;
+static void add_sound_options(recomp::config::Config &config) {
+ config.add_percent_number_option(
+ banjo::configkeys::sound::bgm_volume,
+ "Background Music Volume",
+ "Controls the overall volume of background music.",
+ 100.0f
+ );
+}
+template
+T get_sound_config_number_value(const std::string& option_id) {
+ return static_cast(std::get(recompui::config::get_sound_config().get_option_value(option_id)));
}
-bool save_sound_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
-
- config_json["main_volume"] = banjo::get_main_volume();
- config_json["bgm_volume"] = banjo::get_bgm_volume();
-
- return save_json_with_backups(path, config_json);
+int banjo::get_bgm_volume() {
+ return get_sound_config_number_value(banjo::configkeys::sound::bgm_volume);
}
-bool load_sound_config(const std::filesystem::path& path) {
- nlohmann::json config_json{};
- if (!read_json_with_backups(path, config_json)) {
- return false;
- }
-
- banjo::reset_sound_settings();
- call_if_key_exists(banjo::set_main_volume, config_json, "main_volume");
- call_if_key_exists(banjo::set_bgm_volume, config_json, "bgm_volume");
- return true;
-}
-
-void banjo::load_config() {
- detect_steam_deck();
-
- std::filesystem::path recomp_dir = banjo::get_app_folder_path();
- std::filesystem::path general_path = recomp_dir / general_filename;
- std::filesystem::path graphics_path = recomp_dir / graphics_filename;
- std::filesystem::path controls_path = recomp_dir / controls_filename;
- std::filesystem::path sound_path = recomp_dir / sound_filename;
+void banjo::init_config() {
+ std::filesystem::path recomp_dir = recompui::file::get_app_folder_path();
if (!recomp_dir.empty()) {
std::filesystem::create_directories(recomp_dir);
}
- // TODO error handling for failing to save config files after resetting them.
+ recompui::config::GeneralTabOptions general_options{};
+ general_options.has_rumble_strength = true;
+ general_options.has_gyro_sensitivity = false;
+ general_options.has_mouse_sensitivity = false;
- if (!load_general_config(general_path)) {
- // Set the general settings from an empty json to use defaults.
- set_general_settings_from_json({});
- save_general_config(general_path);
- }
+ auto &general_config = recompui::config::create_general_tab(general_options);
+ add_general_options(general_config);
- if (!load_graphics_config(graphics_path)) {
- reset_graphics_options();
- save_graphics_config(graphics_path);
- }
+ auto &graphics_config = recompui::config::create_graphics_tab();
- if (!load_controls_config(controls_path)) {
- banjo::reset_input_bindings();
- save_controls_config(controls_path);
- }
+ recompui::config::create_controls_tab();
+
+ auto &sound_config = recompui::config::create_sound_tab();
+ add_sound_options(sound_config);
+
+ recompui::config::create_mods_tab();
+
+ recompui::config::finalize();
- if (!load_sound_config(sound_path)) {
- banjo::reset_sound_settings();
- save_sound_config(sound_path);
- }
-}
-
-void banjo::save_config() {
- std::filesystem::path recomp_dir = banjo::get_app_folder_path();
-
- if (recomp_dir.empty()) {
- return;
- }
-
- std::filesystem::create_directories(recomp_dir);
-
- // TODO error handling for failing to save config files.
-
- save_general_config(recomp_dir / general_filename);
- save_graphics_config(recomp_dir / graphics_filename);
- save_controls_config(recomp_dir / controls_filename);
- save_sound_config(recomp_dir / sound_filename);
}
diff --git a/src/game/controls.cpp b/src/game/controls.cpp
deleted file mode 100644
index 0bb3857..0000000
--- a/src/game/controls.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-#include
-
-#include "librecomp/helpers.hpp"
-#include "recomp_input.h"
-#include "ultramodern/ultramodern.hpp"
-
-// Arrays that hold the mappings for every input for keyboard and controller respectively.
-using input_mapping = std::array;
-using input_mapping_array = std::array(recomp::GameInput::COUNT)>;
-static input_mapping_array keyboard_input_mappings{};
-static input_mapping_array controller_input_mappings{};
-
-// Make the button value array, which maps a button index to its bit field.
-#define DEFINE_INPUT(name, value, readable) uint16_t(value##u),
-static const std::array n64_button_values = {
- DEFINE_N64_BUTTON_INPUTS()
-};
-#undef DEFINE_INPUT
-
-// Make the input name array.
-#define DEFINE_INPUT(name, value, readable) readable,
-static const std::vector input_names = {
- DEFINE_ALL_INPUTS()
-};
-#undef DEFINE_INPUT
-
-// Make the input enum name array.
-#define DEFINE_INPUT(name, value, readable) #name,
-static const std::vector input_enum_names = {
- DEFINE_ALL_INPUTS()
-};
-#undef DEFINE_INPUT
-
-size_t recomp::get_num_inputs() {
- return (size_t)GameInput::COUNT;
-}
-
-const std::string& recomp::get_input_name(GameInput input) {
- return input_names.at(static_cast(input));
-}
-
-const std::string& recomp::get_input_enum_name(GameInput input) {
- return input_enum_names.at(static_cast(input));
-}
-
-recomp::GameInput recomp::get_input_from_enum_name(const std::string_view enum_name) {
- auto find_it = std::find(input_enum_names.begin(), input_enum_names.end(), enum_name);
- if (find_it == input_enum_names.end()) {
- return recomp::GameInput::COUNT;
- }
-
- return static_cast(find_it - input_enum_names.begin());
-}
-
-// Due to an RmlUi limitation this can't be const. Ideally it would return a const reference or even just a straight up copy.
-recomp::InputField& recomp::get_input_binding(GameInput input, size_t binding_index, recomp::InputDevice device) {
- input_mapping_array& device_mappings = (device == recomp::InputDevice::Controller) ? controller_input_mappings : keyboard_input_mappings;
- input_mapping& cur_input_mapping = device_mappings.at(static_cast(input));
-
- if (binding_index < cur_input_mapping.size()) {
- return cur_input_mapping[binding_index];
- }
- else {
- static recomp::InputField dummy_field = {};
- return dummy_field;
- }
-}
-
-void recomp::set_input_binding(recomp::GameInput input, size_t binding_index, recomp::InputDevice device, recomp::InputField value) {
- input_mapping_array& device_mappings = (device == recomp::InputDevice::Controller) ? controller_input_mappings : keyboard_input_mappings;
- input_mapping& cur_input_mapping = device_mappings.at(static_cast(input));
-
- if (binding_index < cur_input_mapping.size()) {
- cur_input_mapping[binding_index] = value;
- }
-}
-
-bool recomp::get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out) {
- uint16_t cur_buttons = 0;
- float cur_x = 0.0f;
- float cur_y = 0.0f;
-
- if (controller_num != 0) {
- return false;
- }
-
- if (!recomp::game_input_disabled()) {
- for (size_t i = 0; i < n64_button_values.size(); i++) {
- size_t input_index = (size_t)GameInput::N64_BUTTON_START + i;
- cur_buttons |= recomp::get_input_digital(keyboard_input_mappings[input_index]) ? n64_button_values[i] : 0;
- cur_buttons |= recomp::get_input_digital(controller_input_mappings[input_index]) ? n64_button_values[i] : 0;
- }
-
- float joystick_deadzone = recomp::get_joystick_deadzone() / 100.0f;
-
- float joystick_x = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_POS])
- - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::X_AXIS_NEG]);
-
- float joystick_y = recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_POS])
- - recomp::get_input_analog(controller_input_mappings[(size_t)GameInput::Y_AXIS_NEG]);
-
- recomp::apply_joystick_deadzone(joystick_x, joystick_y, &joystick_x, &joystick_y);
-
- cur_x = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_POS])
- - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::X_AXIS_NEG]) + joystick_x;
-
- cur_y = recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_POS])
- - recomp::get_input_analog(keyboard_input_mappings[(size_t)GameInput::Y_AXIS_NEG]) + joystick_y;
- }
-
- *buttons_out = cur_buttons;
- *x_out = std::clamp(cur_x, -1.0f, 1.0f);
- *y_out = std::clamp(cur_y, -1.0f, 1.0f);
-
- return true;
-}
diff --git a/src/game/input.cpp b/src/game/input.cpp
deleted file mode 100644
index 6e4bccc..0000000
--- a/src/game/input.cpp
+++ /dev/null
@@ -1,897 +0,0 @@
-#include
-#include
-
-#include "ultramodern/ultramodern.hpp"
-#include "recomp.h"
-#include "recomp_input.h"
-#include "banjo_config.h"
-#include "recomp_ui.h"
-#include "SDL.h"
-#include "promptfont.h"
-#include "GamepadMotion.hpp"
-
-constexpr float axis_threshold = 0.5f;
-
-struct ControllerState {
- SDL_GameController* controller;
- std::array latest_accelerometer;
- GamepadMotion motion;
- uint32_t prev_gyro_timestamp;
- ControllerState() : controller{}, latest_accelerometer{}, motion{}, prev_gyro_timestamp{} {
- motion.Reset();
- motion.SetCalibrationMode(GamepadMotionHelpers::CalibrationMode::Stillness | GamepadMotionHelpers::CalibrationMode::SensorFusion);
- };
-};
-
-static struct {
- const Uint8* keys = nullptr;
- SDL_Keymod keymod = SDL_Keymod::KMOD_NONE;
- int numkeys = 0;
- std::atomic_int32_t mouse_wheel_pos = 0;
- std::mutex cur_controllers_mutex;
- std::vector cur_controllers{};
- std::unordered_map controller_states;
-
- std::array rotation_delta{};
- std::array mouse_delta{};
- std::mutex pending_input_mutex;
- std::array pending_rotation_delta{};
- std::array pending_mouse_delta{};
-
- float cur_rumble;
- bool rumble_active;
-} InputState;
-
-static struct {
- std::list files_dropped;
-} DropState;
-
-std::atomic scanning_device = recomp::InputDevice::COUNT;
-std::atomic scanned_input;
-
-enum class InputType {
- None = 0, // Using zero for None ensures that default initialized InputFields are unbound.
- Keyboard,
- Mouse,
- ControllerDigital,
- ControllerAnalog // Axis input_id values are the SDL value + 1
-};
-
-void set_scanned_input(recomp::InputField value) {
- scanning_device.store(recomp::InputDevice::COUNT);
- scanned_input.store(value);
-}
-
-recomp::InputField recomp::get_scanned_input() {
- recomp::InputField ret = scanned_input.load();
- scanned_input.store({});
- return ret;
-}
-
-void recomp::start_scanning_input(recomp::InputDevice device) {
- scanned_input.store({});
- scanning_device.store(device);
-}
-
-void recomp::stop_scanning_input() {
- scanning_device.store(recomp::InputDevice::COUNT);
-}
-
-void queue_if_enabled(SDL_Event* event) {
- if (!recomp::all_input_disabled()) {
- recompui::queue_event(*event);
- }
-}
-
-static std::atomic_bool cursor_enabled = true;
-
-void recompui::set_cursor_visible(bool visible) {
- cursor_enabled.store(visible);
-}
-
-bool should_override_keystate(SDL_Scancode key, SDL_Keymod mod) {
- // Override Enter when Alt is held.
- if (key == SDL_Scancode::SDL_SCANCODE_RETURN) {
- if (mod & SDL_Keymod::KMOD_ALT) {
- return true;
- }
- }
-
- return false;
-}
-
-bool sdl_event_filter(void* userdata, SDL_Event* event) {
- switch (event->type) {
- case SDL_EventType::SDL_KEYDOWN:
- {
- SDL_KeyboardEvent* keyevent = &event->key;
-
- // Skip repeated events when not in the menu
- if (!recompui::is_context_capturing_input() &&
- event->key.repeat) {
- break;
- }
-
- if ((keyevent->keysym.scancode == SDL_Scancode::SDL_SCANCODE_RETURN && (keyevent->keysym.mod & SDL_Keymod::KMOD_ALT)) ||
- keyevent->keysym.scancode == SDL_Scancode::SDL_SCANCODE_F11
- ) {
- recompui::toggle_fullscreen();
- }
- if (scanning_device != recomp::InputDevice::COUNT) {
- if (keyevent->keysym.scancode == SDL_Scancode::SDL_SCANCODE_ESCAPE) {
- recomp::cancel_scanning_input();
- }
- else if (scanning_device == recomp::InputDevice::Keyboard) {
- set_scanned_input({ (uint32_t)InputType::Keyboard, keyevent->keysym.scancode });
- }
- }
- else {
- if (!should_override_keystate(keyevent->keysym.scancode, static_cast(keyevent->keysym.mod))) {
- queue_if_enabled(event);
- }
- }
- }
- break;
- case SDL_EventType::SDL_CONTROLLERDEVICEADDED:
- {
- SDL_ControllerDeviceEvent* controller_event = &event->cdevice;
- SDL_GameController* controller = SDL_GameControllerOpen(controller_event->which);
- printf("Controller added: %d\n", controller_event->which);
- if (controller != nullptr) {
- printf(" Instance ID: %d\n", SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller)));
- ControllerState& state = InputState.controller_states[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller))];
- state.controller = controller;
-
- if (SDL_GameControllerHasSensor(controller, SDL_SensorType::SDL_SENSOR_GYRO) && SDL_GameControllerHasSensor(controller, SDL_SensorType::SDL_SENSOR_ACCEL)) {
- SDL_GameControllerSetSensorEnabled(controller, SDL_SensorType::SDL_SENSOR_GYRO, SDL_TRUE);
- SDL_GameControllerSetSensorEnabled(controller, SDL_SensorType::SDL_SENSOR_ACCEL, SDL_TRUE);
- }
- }
- }
- break;
- case SDL_EventType::SDL_CONTROLLERDEVICEREMOVED:
- {
- SDL_ControllerDeviceEvent* controller_event = &event->cdevice;
- printf("Controller removed: %d\n", controller_event->which);
- InputState.controller_states.erase(controller_event->which);
- }
- break;
- case SDL_EventType::SDL_QUIT: {
- if (!ultramodern::is_game_started()) {
- ultramodern::quit();
- return true;
- }
-
- banjo::open_quit_game_prompt();
- recompui::activate_mouse();
- break;
- }
- case SDL_EventType::SDL_MOUSEWHEEL:
- {
- SDL_MouseWheelEvent* wheel_event = &event->wheel;
- InputState.mouse_wheel_pos.fetch_add(wheel_event->y * (wheel_event->direction == SDL_MOUSEWHEEL_FLIPPED ? -1 : 1));
- }
- queue_if_enabled(event);
- break;
- case SDL_EventType::SDL_CONTROLLERBUTTONDOWN:
- if (scanning_device != recomp::InputDevice::COUNT) {
- auto menuToggleBinding0 = recomp::get_input_binding(recomp::GameInput::TOGGLE_MENU, 0, recomp::InputDevice::Controller);
- auto menuToggleBinding1 = recomp::get_input_binding(recomp::GameInput::TOGGLE_MENU, 1, recomp::InputDevice::Controller);
- // note - magic number: 0 is InputType::None
- if ((menuToggleBinding0.input_type != 0 && event->cbutton.button == menuToggleBinding0.input_id) ||
- (menuToggleBinding1.input_type != 0 && event->cbutton.button == menuToggleBinding1.input_id)) {
- recomp::cancel_scanning_input();
- }
- else if (scanning_device == recomp::InputDevice::Controller) {
- SDL_ControllerButtonEvent* button_event = &event->cbutton;
- auto scanned_input_index = recomp::get_scanned_input_index();
- if ((scanned_input_index == static_cast(recomp::GameInput::TOGGLE_MENU) ||
- scanned_input_index == static_cast(recomp::GameInput::ACCEPT_MENU) ||
- scanned_input_index == static_cast(recomp::GameInput::APPLY_MENU)) && (
- button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP ||
- button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN ||
- button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
- button_event->button == SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) {
- break;
- }
-
- set_scanned_input({ (uint32_t)InputType::ControllerDigital, button_event->button });
- }
- }
- else {
- queue_if_enabled(event);
- }
- break;
- case SDL_EventType::SDL_CONTROLLERAXISMOTION:
- if (scanning_device == recomp::InputDevice::Controller) {
- auto scanned_input_index = recomp::get_scanned_input_index();
- if (scanned_input_index == static_cast(recomp::GameInput::TOGGLE_MENU) ||
- scanned_input_index == static_cast(recomp::GameInput::ACCEPT_MENU) ||
- scanned_input_index == static_cast(recomp::GameInput::APPLY_MENU)) {
- break;
- }
-
- SDL_ControllerAxisEvent* axis_event = &event->caxis;
- float axis_value = axis_event->value * (1/32768.0f);
- if (axis_value > axis_threshold) {
- SDL_Event set_stick_return_event;
- set_stick_return_event.type = SDL_USEREVENT;
- set_stick_return_event.user.code = axis_event->axis;
- set_stick_return_event.user.data1 = nullptr;
- set_stick_return_event.user.data2 = nullptr;
- recompui::queue_event(set_stick_return_event);
-
- set_scanned_input({ (uint32_t)InputType::ControllerAnalog, axis_event->axis + 1 });
- }
- else if (axis_value < -axis_threshold) {
- SDL_Event set_stick_return_event;
- set_stick_return_event.type = SDL_USEREVENT;
- set_stick_return_event.user.code = axis_event->axis;
- set_stick_return_event.user.data1 = nullptr;
- set_stick_return_event.user.data2 = nullptr;
- recompui::queue_event(set_stick_return_event);
-
- set_scanned_input({ (uint32_t)InputType::ControllerAnalog, -axis_event->axis - 1 });
- }
- }
- else {
- queue_if_enabled(event);
- }
- break;
- case SDL_EventType::SDL_CONTROLLERSENSORUPDATE:
- if (event->csensor.sensor == SDL_SensorType::SDL_SENSOR_ACCEL) {
- // Convert acceleration to g's.
- float x = event->csensor.data[0] / SDL_STANDARD_GRAVITY;
- float y = event->csensor.data[1] / SDL_STANDARD_GRAVITY;
- float z = event->csensor.data[2] / SDL_STANDARD_GRAVITY;
- ControllerState& state = InputState.controller_states[event->csensor.which];
- state.latest_accelerometer[0] = x;
- state.latest_accelerometer[1] = y;
- state.latest_accelerometer[2] = z;
- }
- else if (event->csensor.sensor == SDL_SensorType::SDL_SENSOR_GYRO) {
- // constexpr float gyro_threshold = 0.05f;
- // Convert rotational velocity to degrees per second.
- constexpr float rad_to_deg = 180.0f / M_PI;
- float x = event->csensor.data[0] * rad_to_deg;
- float y = event->csensor.data[1] * rad_to_deg;
- float z = event->csensor.data[2] * rad_to_deg;
- ControllerState& state = InputState.controller_states[event->csensor.which];
- uint64_t cur_timestamp = event->csensor.timestamp;
- uint32_t delta_ms = cur_timestamp - state.prev_gyro_timestamp;
- state.motion.ProcessMotion(x, y, z, state.latest_accelerometer[0], state.latest_accelerometer[1], state.latest_accelerometer[2], delta_ms * 0.001f);
- state.prev_gyro_timestamp = cur_timestamp;
-
- float rot_x = 0.0f;
- float rot_y = 0.0f;
- state.motion.GetPlayerSpaceGyro(rot_x, rot_y);
-
- {
- std::lock_guard lock{ InputState.pending_input_mutex };
- InputState.pending_rotation_delta[0] += rot_x;
- InputState.pending_rotation_delta[1] += rot_y;
- }
- }
- break;
- case SDL_EventType::SDL_MOUSEMOTION:
- if (!recomp::game_input_disabled()) {
- SDL_MouseMotionEvent* motion_event = &event->motion;
- std::lock_guard lock{ InputState.pending_input_mutex };
- InputState.pending_mouse_delta[0] += motion_event->xrel;
- InputState.pending_mouse_delta[1] += motion_event->yrel;
- }
- queue_if_enabled(event);
- break;
- case SDL_EventType::SDL_DROPBEGIN:
- DropState.files_dropped.clear();
- break;
- case SDL_EventType::SDL_DROPFILE:
- DropState.files_dropped.emplace_back(std::filesystem::path(std::u8string_view((const char8_t*)(event->drop.file))));
- SDL_free(event->drop.file);
- break;
- case SDL_EventType::SDL_DROPCOMPLETE:
- recompui::drop_files(DropState.files_dropped);
- break;
- case SDL_EventType::SDL_CONTROLLERBUTTONUP:
- // Always queue button up events to avoid missing them during binding.
- recompui::queue_event(*event);
- break;
- default:
- queue_if_enabled(event);
- break;
- }
- return false;
-}
-
-void recomp::handle_events() {
- SDL_Event cur_event;
- static bool started = false;
- static bool exited = false;
- while (SDL_PollEvent(&cur_event) && !exited) {
- exited = sdl_event_filter(nullptr, &cur_event);
-
- // Lock the cursor if all three conditions are true: mouse aiming is enabled, game input is not disabled, and the game has been started.
- bool cursor_locked = (recomp::get_mouse_sensitivity() != 0) && !recomp::game_input_disabled() && ultramodern::is_game_started();
-
- // Hide the cursor based on its enable state, but override visibility to false if the cursor is locked.
- bool cursor_visible = cursor_enabled;
- if (cursor_locked) {
- cursor_visible = false;
- }
-
- SDL_ShowCursor(cursor_visible ? SDL_ENABLE : SDL_DISABLE);
- SDL_SetRelativeMouseMode(cursor_locked ? SDL_TRUE : SDL_FALSE);
- }
-
- if (!started && ultramodern::is_game_started()) {
- started = true;
- recompui::process_game_started();
- }
-}
-
-constexpr SDL_GameControllerButton SDL_CONTROLLER_BUTTON_SOUTH = SDL_CONTROLLER_BUTTON_A;
-constexpr SDL_GameControllerButton SDL_CONTROLLER_BUTTON_EAST = SDL_CONTROLLER_BUTTON_B;
-constexpr SDL_GameControllerButton SDL_CONTROLLER_BUTTON_WEST = SDL_CONTROLLER_BUTTON_X;
-constexpr SDL_GameControllerButton SDL_CONTROLLER_BUTTON_NORTH = SDL_CONTROLLER_BUTTON_Y;
-
-const recomp::DefaultN64Mappings recomp::default_n64_keyboard_mappings = {
- .a = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_SPACE}
- },
- .b = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_LSHIFT}
- },
- .l = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_E}
- },
- .r = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_R}
- },
- .z = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_Q}
- },
- .start = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_RETURN}
- },
- .c_left = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_LEFT}
- },
- .c_right = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_RIGHT}
- },
- .c_up = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_UP}
- },
- .c_down = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_DOWN}
- },
- .dpad_left = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_J}
- },
- .dpad_right = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_L}
- },
- .dpad_up = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_I}
- },
- .dpad_down = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_K}
- },
- .analog_left = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_A}
- },
- .analog_right = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_D}
- },
- .analog_up = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_W}
- },
- .analog_down = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_S}
- },
- .toggle_menu = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_ESCAPE}
- },
- .accept_menu = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_RETURN}
- },
- .apply_menu = {
- {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_F}
- }
-};
-
-const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = {
- .a = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_SOUTH},
- },
- .b = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_WEST},
- },
- .l = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
- },
- .r = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_TRIGGERRIGHT + 1},
- },
- .z = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_TRIGGERLEFT + 1},
- },
- .start = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_START},
- },
- .c_left = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = -(SDL_CONTROLLER_AXIS_RIGHTX + 1)},
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_NORTH},
- },
- .c_right = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_RIGHTX + 1},
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_EAST},
- },
- .c_up = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = -(SDL_CONTROLLER_AXIS_RIGHTY + 1)},
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_RIGHTSTICK},
- },
- .c_down = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_RIGHTY + 1},
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
- },
- .dpad_left = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_DPAD_LEFT},
- },
- .dpad_right = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
- },
- .dpad_up = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_DPAD_UP},
- },
- .dpad_down = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_DPAD_DOWN},
- },
- .analog_left = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = -(SDL_CONTROLLER_AXIS_LEFTX + 1)},
- },
- .analog_right = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_LEFTX + 1},
- },
- .analog_up = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = -(SDL_CONTROLLER_AXIS_LEFTY + 1)},
- },
- .analog_down = {
- {.input_type = (uint32_t)InputType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_LEFTY + 1},
- },
- .toggle_menu = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_BACK},
- },
- .accept_menu = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_SOUTH},
- },
- .apply_menu = {
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_WEST},
- {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_START}
- }
-};
-
-void recomp::poll_inputs() {
- InputState.keys = SDL_GetKeyboardState(&InputState.numkeys);
- InputState.keymod = SDL_GetModState();
-
- {
- std::lock_guard lock{ InputState.cur_controllers_mutex };
- InputState.cur_controllers.clear();
-
- for (const auto& [id, state] : InputState.controller_states) {
- (void)id; // Avoid unused variable warning.
- SDL_GameController* controller = state.controller;
- if (controller != nullptr) {
- InputState.cur_controllers.push_back(controller);
- }
- }
- }
-
- // Read the deltas while resetting them to zero.
- {
- std::lock_guard lock{ InputState.pending_input_mutex };
-
- InputState.rotation_delta = InputState.pending_rotation_delta;
- InputState.pending_rotation_delta = { 0.0f, 0.0f };
-
- InputState.mouse_delta = InputState.pending_mouse_delta;
- InputState.pending_mouse_delta = { 0.0f, 0.0f };
- }
-}
-
-void recomp::set_rumble(int controller_num, bool on) {
- if (controller_num == 0) {
- InputState.rumble_active = on;
- }
-}
-
-ultramodern::input::connected_device_info_t recomp::get_connected_device_info(int controller_num) {
- switch (controller_num) {
- case 0:
- return ultramodern::input::connected_device_info_t{
- .connected_device = ultramodern::input::Device::Controller,
- .connected_pak = ultramodern::input::Pak::RumblePak,
- };
- }
-
- return ultramodern::input::connected_device_info_t{
- .connected_device = ultramodern::input::Device::None,
- .connected_pak = ultramodern::input::Pak::None,
- };
-}
-
-static float smoothstep(float from, float to, float amount) {
- amount = (amount * amount) * (3.0f - 2.0f * amount);
- return std::lerp(from, to, amount);
-}
-
-// Update rumble to attempt to mimic the way n64 rumble ramps up and falls off
-void recomp::update_rumble() {
- // Note: values are not accurate! just approximations based on feel
- if (InputState.rumble_active) {
- InputState.cur_rumble += 0.17f;
- if (InputState.cur_rumble > 1) InputState.cur_rumble = 1;
- }
- else {
- InputState.cur_rumble *= 0.92f;
- InputState.cur_rumble -= 0.01f;
- if (InputState.cur_rumble < 0) InputState.cur_rumble = 0;
- }
- float smooth_rumble = smoothstep(0, 1, InputState.cur_rumble);
-
- uint16_t rumble_strength = smooth_rumble * (recomp::get_rumble_strength() * 0xFFFF / 100);
- uint32_t duration = 1000000; // Dummy duration value that lasts long enough to matter as the game will reset rumble on its own.
- {
- std::lock_guard lock{ InputState.cur_controllers_mutex };
- for (const auto& controller : InputState.cur_controllers) {
- SDL_GameControllerRumble(controller, 0, rumble_strength, duration);
- }
- }
-}
-
-bool controller_button_state(int32_t input_id) {
- if (input_id >= 0 && input_id < SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_MAX) {
- SDL_GameControllerButton button = (SDL_GameControllerButton)input_id;
- bool ret = false;
- {
- std::lock_guard lock{ InputState.cur_controllers_mutex };
- for (const auto& controller : InputState.cur_controllers) {
- ret |= SDL_GameControllerGetButton(controller, button);
- }
- }
-
- return ret;
- }
- return false;
-}
-
-static std::atomic_bool right_analog_suppressed = false;
-
-float controller_axis_state(int32_t input_id, bool allow_suppression) {
- if (abs(input_id) - 1 < SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_MAX) {
- SDL_GameControllerAxis axis = (SDL_GameControllerAxis)(abs(input_id) - 1);
- bool negative_range = input_id < 0;
- float ret = 0.0f;
-
- {
- std::lock_guard lock{ InputState.cur_controllers_mutex };
- for (const auto& controller : InputState.cur_controllers) {
- float cur_val = SDL_GameControllerGetAxis(controller, axis) * (1/32768.0f);
- if (negative_range) {
- cur_val = -cur_val;
- }
-
- // Check if this input is a right analog axis and suppress it accordingly.
- if (allow_suppression && right_analog_suppressed.load() &&
- (axis == SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTX || axis == SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTY)) {
- cur_val = 0;
- }
- ret += std::clamp(cur_val, 0.0f, 1.0f);
- }
- }
-
- return std::clamp(ret, 0.0f, 1.0f);
- }
- return false;
-}
-
-float recomp::get_input_analog(const recomp::InputField& field) {
- switch ((InputType)field.input_type) {
- case InputType::Keyboard:
- if (InputState.keys && field.input_id >= 0 && field.input_id < InputState.numkeys) {
- if (should_override_keystate(static_cast(field.input_id), InputState.keymod)) {
- return 0.0f;
- }
- return InputState.keys[field.input_id] ? 1.0f : 0.0f;
- }
- return 0.0f;
- case InputType::ControllerDigital:
- return controller_button_state(field.input_id) ? 1.0f : 0.0f;
- case InputType::ControllerAnalog:
- return controller_axis_state(field.input_id, true);
- case InputType::Mouse:
- // TODO mouse support
- return 0.0f;
- case InputType::None:
- return false;
- }
-}
-
-float recomp::get_input_analog(const std::span fields) {
- float ret = 0.0f;
- for (const auto& field : fields) {
- ret += get_input_analog(field);
- }
- return std::clamp(ret, 0.0f, 1.0f);
-}
-
-bool recomp::get_input_digital(const recomp::InputField& field) {
- switch ((InputType)field.input_type) {
- case InputType::Keyboard:
- if (InputState.keys && field.input_id >= 0 && field.input_id < InputState.numkeys) {
- if (should_override_keystate(static_cast(field.input_id), InputState.keymod)) {
- return false;
- }
- return InputState.keys[field.input_id] != 0;
- }
- return false;
- case InputType::ControllerDigital:
- return controller_button_state(field.input_id);
- case InputType::ControllerAnalog:
- // TODO adjustable threshold
- return controller_axis_state(field.input_id, true) >= axis_threshold;
- case InputType::Mouse:
- // TODO mouse support
- return false;
- case InputType::None:
- return false;
- }
-}
-
-bool recomp::get_input_digital(const std::span fields) {
- bool ret = 0;
- for (const auto& field : fields) {
- ret |= get_input_digital(field);
- }
- return ret;
-}
-
-void recomp::get_gyro_deltas(float* x, float* y) {
- std::array cur_rotation_delta = InputState.rotation_delta;
- float sensitivity = (float)recomp::get_gyro_sensitivity() / 100.0f;
- *x = cur_rotation_delta[0] * sensitivity;
- *y = cur_rotation_delta[1] * sensitivity;
-}
-
-void recomp::get_mouse_deltas(float* x, float* y) {
- std::array cur_mouse_delta = InputState.mouse_delta;
- float sensitivity = (float)recomp::get_mouse_sensitivity() / 100.0f;
- *x = cur_mouse_delta[0] * sensitivity;
- *y = cur_mouse_delta[1] * sensitivity;
-}
-
-void recomp::apply_joystick_deadzone(float x_in, float y_in, float* x_out, float* y_out) {
- float joystick_deadzone = (float)recomp::get_joystick_deadzone() / 100.0f;
-
- if (fabsf(x_in) < joystick_deadzone) {
- x_in = 0.0f;
- }
- else {
- if (x_in > 0.0f) {
- x_in -= joystick_deadzone;
- }
- else {
- x_in += joystick_deadzone;
- }
-
- x_in /= (1.0f - joystick_deadzone);
- }
-
- if (fabsf(y_in) < joystick_deadzone) {
- y_in = 0.0f;
- }
- else {
- if (y_in > 0.0f) {
- y_in -= joystick_deadzone;
- }
- else {
- y_in += joystick_deadzone;
- }
-
- y_in /= (1.0f - joystick_deadzone);
- }
-
- *x_out = x_in;
- *y_out = y_in;
-}
-
-void recomp::get_right_analog(float* x, float* y) {
- float x_val =
- controller_axis_state((SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTX + 1), false) -
- controller_axis_state(-(SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTX + 1), false);
- float y_val =
- controller_axis_state((SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTY + 1), false) -
- controller_axis_state(-(SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTY + 1), false);
- recomp::apply_joystick_deadzone(x_val, y_val, x, y);
-}
-
-void recomp::set_right_analog_suppressed(bool suppressed) {
- right_analog_suppressed.store(suppressed);
-}
-
-bool recomp::game_input_disabled() {
- // Disable input if any menu that blocks input is open.
- return recompui::is_context_capturing_input();
-}
-
-bool recomp::all_input_disabled() {
- // Disable all input if an input is being polled.
- return scanning_device != recomp::InputDevice::COUNT;
-}
-
-std::string controller_button_to_string(SDL_GameControllerButton button) {
- switch (button) {
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A:
- return PF_GAMEPAD_A;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_B:
- return PF_GAMEPAD_B;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_X:
- return PF_GAMEPAD_X;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_Y:
- return PF_GAMEPAD_Y;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_BACK:
- return PF_XBOX_VIEW;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_GUIDE:
- return PF_GAMEPAD_HOME;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_START:
- return PF_XBOX_MENU;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSTICK:
- return PF_ANALOG_L_CLICK;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSTICK:
- return PF_ANALOG_R_CLICK;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
- return PF_XBOX_LEFT_SHOULDER;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
- return PF_XBOX_RIGHT_SHOULDER;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP:
- return PF_DPAD_UP;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN:
- return PF_DPAD_DOWN;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT:
- return PF_DPAD_LEFT;
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
- return PF_DPAD_RIGHT;
- // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_MISC1:
- // return "";
- // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE1:
- // return "";
- // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE2:
- // return "";
- // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE3:
- // return "";
- // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE4:
- // return "";
- case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_TOUCHPAD:
- return PF_SONY_TOUCHPAD;
- default:
- return "Button " + std::to_string(button);
- }
-}
-
-std::unordered_map scancode_codepoints{
- {SDL_SCANCODE_LEFT, PF_KEYBOARD_LEFT},
- // NOTE: UP and RIGHT are swapped with promptfont.
- {SDL_SCANCODE_UP, PF_KEYBOARD_RIGHT},
- {SDL_SCANCODE_RIGHT, PF_KEYBOARD_UP},
- {SDL_SCANCODE_DOWN, PF_KEYBOARD_DOWN},
- {SDL_SCANCODE_A, PF_KEYBOARD_A},
- {SDL_SCANCODE_B, PF_KEYBOARD_B},
- {SDL_SCANCODE_C, PF_KEYBOARD_C},
- {SDL_SCANCODE_D, PF_KEYBOARD_D},
- {SDL_SCANCODE_E, PF_KEYBOARD_E},
- {SDL_SCANCODE_F, PF_KEYBOARD_F},
- {SDL_SCANCODE_G, PF_KEYBOARD_G},
- {SDL_SCANCODE_H, PF_KEYBOARD_H},
- {SDL_SCANCODE_I, PF_KEYBOARD_I},
- {SDL_SCANCODE_J, PF_KEYBOARD_J},
- {SDL_SCANCODE_K, PF_KEYBOARD_K},
- {SDL_SCANCODE_L, PF_KEYBOARD_L},
- {SDL_SCANCODE_M, PF_KEYBOARD_M},
- {SDL_SCANCODE_N, PF_KEYBOARD_N},
- {SDL_SCANCODE_O, PF_KEYBOARD_O},
- {SDL_SCANCODE_P, PF_KEYBOARD_P},
- {SDL_SCANCODE_Q, PF_KEYBOARD_Q},
- {SDL_SCANCODE_R, PF_KEYBOARD_R},
- {SDL_SCANCODE_S, PF_KEYBOARD_S},
- {SDL_SCANCODE_T, PF_KEYBOARD_T},
- {SDL_SCANCODE_U, PF_KEYBOARD_U},
- {SDL_SCANCODE_V, PF_KEYBOARD_V},
- {SDL_SCANCODE_W, PF_KEYBOARD_W},
- {SDL_SCANCODE_X, PF_KEYBOARD_X},
- {SDL_SCANCODE_Y, PF_KEYBOARD_Y},
- {SDL_SCANCODE_Z, PF_KEYBOARD_Z},
- {SDL_SCANCODE_0, PF_KEYBOARD_0},
- {SDL_SCANCODE_1, PF_KEYBOARD_1},
- {SDL_SCANCODE_2, PF_KEYBOARD_2},
- {SDL_SCANCODE_3, PF_KEYBOARD_3},
- {SDL_SCANCODE_4, PF_KEYBOARD_4},
- {SDL_SCANCODE_5, PF_KEYBOARD_5},
- {SDL_SCANCODE_6, PF_KEYBOARD_6},
- {SDL_SCANCODE_7, PF_KEYBOARD_7},
- {SDL_SCANCODE_8, PF_KEYBOARD_8},
- {SDL_SCANCODE_9, PF_KEYBOARD_9},
- {SDL_SCANCODE_ESCAPE, PF_KEYBOARD_ESCAPE},
- {SDL_SCANCODE_F1, PF_KEYBOARD_F1},
- {SDL_SCANCODE_F2, PF_KEYBOARD_F2},
- {SDL_SCANCODE_F3, PF_KEYBOARD_F3},
- {SDL_SCANCODE_F4, PF_KEYBOARD_F4},
- {SDL_SCANCODE_F5, PF_KEYBOARD_F5},
- {SDL_SCANCODE_F6, PF_KEYBOARD_F6},
- {SDL_SCANCODE_F7, PF_KEYBOARD_F7},
- {SDL_SCANCODE_F8, PF_KEYBOARD_F8},
- {SDL_SCANCODE_F9, PF_KEYBOARD_F9},
- {SDL_SCANCODE_F10, PF_KEYBOARD_F10},
- {SDL_SCANCODE_F11, PF_KEYBOARD_F11},
- {SDL_SCANCODE_F12, PF_KEYBOARD_F12},
- {SDL_SCANCODE_PRINTSCREEN, PF_KEYBOARD_PRINT_SCREEN},
- {SDL_SCANCODE_SCROLLLOCK, PF_KEYBOARD_SCROLL_LOCK},
- {SDL_SCANCODE_PAUSE, PF_KEYBOARD_PAUSE},
- {SDL_SCANCODE_INSERT, PF_KEYBOARD_INSERT},
- {SDL_SCANCODE_HOME, PF_KEYBOARD_HOME},
- {SDL_SCANCODE_PAGEUP, PF_KEYBOARD_PAGE_UP},
- {SDL_SCANCODE_DELETE, PF_KEYBOARD_DELETE},
- {SDL_SCANCODE_END, PF_KEYBOARD_END},
- {SDL_SCANCODE_PAGEDOWN, PF_KEYBOARD_PAGE_DOWN},
- {SDL_SCANCODE_SPACE, PF_KEYBOARD_SPACE},
- {SDL_SCANCODE_BACKSPACE, PF_KEYBOARD_BACKSPACE},
- {SDL_SCANCODE_TAB, PF_KEYBOARD_TAB},
- {SDL_SCANCODE_RETURN, PF_KEYBOARD_ENTER},
- {SDL_SCANCODE_CAPSLOCK, PF_KEYBOARD_CAPS},
- {SDL_SCANCODE_NUMLOCKCLEAR, PF_KEYBOARD_NUM_LOCK},
- {SDL_SCANCODE_LSHIFT, "L" PF_KEYBOARD_SHIFT},
- {SDL_SCANCODE_RSHIFT, "R" PF_KEYBOARD_SHIFT},
-};
-
-std::string keyboard_input_to_string(SDL_Scancode key) {
- if (scancode_codepoints.find(key) != scancode_codepoints.end()) {
- return scancode_codepoints[key];
- }
- return std::to_string(key);
-}
-
-std::string controller_axis_to_string(int axis) {
- bool positive = axis > 0;
- SDL_GameControllerAxis actual_axis = SDL_GameControllerAxis(abs(axis) - 1);
- switch (actual_axis) {
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_LEFTX:
- return positive ? "\u21C0" : "\u21BC";
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_LEFTY:
- return positive ? "\u21C2" : "\u21BE";
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTX:
- return positive ? "\u21C1" : "\u21BD";
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_RIGHTY:
- return positive ? "\u21C3" : "\u21BF";
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_TRIGGERLEFT:
- return positive ? "\u2196" : "\u21DC";
- case SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
- return positive ? "\u2197" : "\u21DD";
- default:
- return "Axis " + std::to_string(actual_axis) + (positive ? '+' : '-');
- }
-}
-
-std::string recomp::InputField::to_string() const {
- switch ((InputType)input_type) {
- case InputType::None:
- return "";
- case InputType::ControllerDigital:
- return controller_button_to_string((SDL_GameControllerButton)input_id);
- case InputType::ControllerAnalog:
- return controller_axis_to_string(input_id);
- case InputType::Keyboard:
- return keyboard_input_to_string((SDL_Scancode)input_id);
- default:
- return std::to_string(input_type) + "," + std::to_string(input_id);
- }
-}
diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp
index cc1b89e..7e1bf43 100644
--- a/src/game/recomp_api.cpp
+++ b/src/game/recomp_api.cpp
@@ -4,8 +4,9 @@
#include "librecomp/overlays.hpp"
#include "librecomp/addresses.hpp"
#include "banjo_config.h"
-#include "recomp_input.h"
-#include "recomp_ui.h"
+#include "recompinput/recompinput.h"
+#include "recompui/recompui.h"
+#include "recompui/renderer.h"
#include "banjo_render.h"
#include "banjo_sound.h"
#include "librecomp/helpers.hpp"
@@ -17,7 +18,7 @@
#include "../lib/N64ModernRuntime/thirdparty/xxHash/xxh3.h"
extern "C" void recomp_update_inputs(uint8_t* rdram, recomp_context* ctx) {
- recomp::poll_inputs();
+ recompinput::poll_inputs();
}
extern "C" void recomp_puts(uint8_t* rdram, recomp_context* ctx) {
@@ -50,14 +51,15 @@ extern "C" void recomp_get_gyro_deltas(uint8_t* rdram, recomp_context* ctx) {
float* x_out = _arg<0, float*>(rdram, ctx);
float* y_out = _arg<1, float*>(rdram, ctx);
- recomp::get_gyro_deltas(x_out, y_out);
+ // TODO: use controller number
+ recompinput::get_gyro_deltas(0, x_out, y_out);
}
extern "C" void recomp_get_mouse_deltas(uint8_t* rdram, recomp_context* ctx) {
float* x_out = _arg<0, float*>(rdram, ctx);
float* y_out = _arg<1, float*>(rdram, ctx);
- recomp::get_mouse_deltas(x_out, y_out);
+ recompinput::get_mouse_deltas(x_out, y_out);
}
extern "C" void recomp_powf(uint8_t* rdram, recomp_context* ctx) {
@@ -123,7 +125,7 @@ extern "C" void recomp_load_overlays(uint8_t * rdram, recomp_context * ctx) {
}
extern "C" void recomp_high_precision_fb_enabled(uint8_t * rdram, recomp_context * ctx) {
- _return(ctx, static_cast(banjo::renderer::RT64HighPrecisionFBEnabled()));
+ _return(ctx, static_cast(recompui::renderer::RT64HighPrecisionFBEnabled()));
}
extern "C" void recomp_get_resolution_scale(uint8_t* rdram, recomp_context* ctx) {
@@ -167,7 +169,8 @@ extern "C" void recomp_get_camera_inputs(uint8_t* rdram, recomp_context* ctx) {
float x, y;
- recomp::get_right_analog(&x, &y);
+ // TODO: use controller number
+ recompinput::get_right_analog(0, &x, &y);
float magnitude = sqrtf(x * x + y * y);
@@ -187,7 +190,7 @@ extern "C" void recomp_get_camera_inputs(uint8_t* rdram, recomp_context* ctx) {
extern "C" void recomp_set_right_analog_suppressed(uint8_t* rdram, recomp_context* ctx) {
s32 suppressed = _arg<0, s32>(rdram, ctx);
- recomp::set_right_analog_suppressed(suppressed);
+ recompinput::set_right_analog_suppressed(suppressed);
}
constexpr uint32_t k1_to_phys(uint32_t addr) {
diff --git a/src/game/recomp_data_api.cpp b/src/game/recomp_data_api.cpp
index 2557abf..6aa5621 100644
--- a/src/game/recomp_data_api.cpp
+++ b/src/game/recomp_data_api.cpp
@@ -5,7 +5,7 @@
#include "slot_map.h"
#include "recomp_data.h"
-#include "recomp_ui.h"
+#include "recompui/recompui.h"
#include "librecomp/helpers.hpp"
#include "librecomp/overlays.hpp"
#include "librecomp/addresses.hpp"
diff --git a/src/game/recomp_extension_api.cpp b/src/game/recomp_extension_api.cpp
index 1ba0e92..56d4182 100644
--- a/src/game/recomp_extension_api.cpp
+++ b/src/game/recomp_extension_api.cpp
@@ -7,7 +7,7 @@
#include "librecomp/helpers.hpp"
#include "librecomp/addresses.hpp"
#include "ultramodern/error_handling.hpp"
-#include "recomp_ui.h"
+#include "recompui/recompui.h"
#include "recomp_data.h"
#include "../patches/object_extension_funcs.h"
diff --git a/src/main/main.cpp b/src/main/main.cpp
index 94d253b..585b210 100644
--- a/src/main/main.cpp
+++ b/src/main/main.cpp
@@ -27,8 +27,14 @@
#undef Always
#endif
-#include "recomp_ui.h"
-#include "recomp_input.h"
+#include "recompui/recompui.h"
+#include "recompui/program_config.h"
+#include "recompui/renderer.h"
+#include "recompui/config.h"
+#include "util/file.h"
+#include "recompinput/input_events.h"
+#include "recompinput/recompinput.h"
+#include "recompinput/profiles.h"
#include "banjo_config.h"
#include "banjo_sound.h"
#include "banjo_render.h"
@@ -174,7 +180,7 @@ ultramodern::renderer::WindowHandle create_window(ultramodern::gfx_callbacks_t::
}
void update_gfx(void*) {
- recomp::handle_events();
+ recompinput::handle_events();
}
static SDL_AudioCVT audio_convert;
@@ -216,7 +222,7 @@ void queue_samples(int16_t* audio_data, size_t sample_count) {
// Convert the audio from 16-bit values to floats and swap the audio channels into the
// swap buffer to correct for the address xor caused by endianness handling.
- float cur_main_volume = banjo::get_main_volume() / 100.0f; // Get the current main volume, normalized to 0.0-1.0.
+ float cur_main_volume = static_cast(recompui::config::sound::get_main_volume()) / 100.0f; // Get the current main volume, normalized to 0.0-1.0.
for (size_t i = 0; i < sample_count; i += input_channels) {
swap_buffer[i + 0 + duplicated_input_frames * input_channels] = audio_data[i + 1] * (0.5f / 32768.0f) * cur_main_volume;
swap_buffer[i + 1 + duplicated_input_frames * input_channels] = audio_data[i + 0] * (0.5f / 32768.0f) * cur_main_volume;
@@ -520,15 +526,34 @@ void release_preload(PreloadContext& context) {
#endif
void enable_texture_pack(recomp::mods::ModContext& context, const recomp::mods::ModHandle& mod) {
- banjo::renderer::enable_texture_pack(context, mod);
+ recompui::renderer::enable_texture_pack(context, mod);
}
void disable_texture_pack(recomp::mods::ModContext&, const recomp::mods::ModHandle& mod) {
- banjo::renderer::disable_texture_pack(mod);
+ recompui::renderer::disable_texture_pack(mod);
}
void reorder_texture_pack(recomp::mods::ModContext&) {
- banjo::renderer::trigger_texture_pack_update();
+ recompui::renderer::trigger_texture_pack_update();
+}
+
+void on_launcher_init(recompui::LauncherMenu *menu) {
+ auto game_options_menu = menu->init_game_options_menu(
+ supported_games[0].game_id,
+ supported_games[0].mod_game_id,
+ recompui::GameOptionsMenuLayout::Center
+ );
+ game_options_menu->add_default_options();
+
+ // TODO: Style launcher and get better background.
+ auto bg_element = menu->set_launcher_background_svg("banjkazoobg.svg");
+ bg_element->set_top(0.0f);
+ bg_element->set_bottom(0.0f);
+ bg_element->set_left(50.0f, recompui::Unit::Percent);
+ bg_element->set_height(1080.0f, recompui::Unit::Dp);
+ bg_element->set_width(1920.0f, recompui::Unit::Dp);
+ bg_element->set_translate_2D(-50.0f, 0.0f, recompui::Unit::Percent);
+ bg_element->set_opacity(0.25f);
}
#define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name)
@@ -608,12 +633,15 @@ int main(int argc, char** argv) {
reset_audio(48000);
// Source controller mappings file
- std::u8string controller_db_path = (banjo::get_program_path() / "recompcontrollerdb.txt").u8string();
+ std::u8string controller_db_path = (recompui::file::get_program_path() / "recompcontrollerdb.txt").u8string();
if (SDL_GameControllerAddMappingsFromFile(reinterpret_cast(controller_db_path.c_str())) < 0) {
fprintf(stderr, "Failed to load controller mappings: %s\n", SDL_GetError());
}
- recomp::register_config_path(banjo::get_app_folder_path());
+ recompui::programconfig::set_program_name(banjo::program_name);
+ recompui::programconfig::set_program_id(banjo::program_id);
+ recompui::register_primary_font("Suplexmentary Comic NC.ttf", "Suplexmentary Comic NC");
+ recomp::register_config_path(recompui::file::get_app_folder_path());
// Register supported games and patches
for (const auto& game : supported_games) {
@@ -627,8 +655,8 @@ int main(int argc, char** argv) {
REGISTER_FUNC(recomp_get_analog_cam_enabled);
REGISTER_FUNC(recomp_get_camera_inputs);
REGISTER_FUNC(recomp_get_bgm_volume);
- REGISTER_FUNC(recomp_get_gyro_deltas);
- REGISTER_FUNC(recomp_get_mouse_deltas);
+ // REGISTER_FUNC(recomp_get_gyro_deltas);
+ // REGISTER_FUNC(recomp_get_mouse_deltas);
REGISTER_FUNC(recomp_get_inverted_axes);
REGISTER_FUNC(recomp_get_analog_inverted_axes);
recompui::register_ui_exports();
@@ -637,16 +665,22 @@ int main(int argc, char** argv) {
banjo::register_bk_overlays();
banjo::register_bk_patches();
+
// Register extensions for two types: Props and ActorMarkers.
recomputil::init_extended_object_data(2);
- banjo::load_config();
+
+ recompinput::players::set_single_player_mode(true);
+
+ banjo::init_config();
+
+ recompui::register_launcher_init_callback(on_launcher_init);
recomp::rsp::callbacks_t rsp_callbacks{
.get_rsp_microcode = get_rsp_microcode,
};
ultramodern::renderer::callbacks_t renderer_callbacks{
- .create_render_context = banjo::renderer::create_render_context,
+ .create_render_context = recompui::renderer::create_render_context,
};
ultramodern::gfx_callbacks_t gfx_callbacks{
@@ -662,15 +696,15 @@ int main(int argc, char** argv) {
};
ultramodern::input::callbacks_t input_callbacks{
- .poll_input = recomp::poll_inputs,
- .get_input = recomp::get_n64_input,
- .set_rumble = recomp::set_rumble,
- .get_connected_device_info = recomp::get_connected_device_info,
+ .poll_input = recompinput::poll_inputs,
+ .get_input = recompinput::profiles::get_n64_input,
+ .set_rumble = recompinput::set_rumble,
+ .get_connected_device_info = recompinput::get_connected_device_info,
};
ultramodern::events::callbacks_t thread_callbacks{
- .vi_callback = recomp::update_rumble,
- .gfx_init_callback = recompui::update_supported_options,
+ .vi_callback = recompinput::update_rumble,
+ .gfx_init_callback = nullptr,
};
ultramodern::error_handling::callbacks_t error_handling_callbacks{
diff --git a/src/main/rt64_render_context.cpp b/src/main/rt64_render_context.cpp
deleted file mode 100644
index 665a6c6..0000000
--- a/src/main/rt64_render_context.cpp
+++ /dev/null
@@ -1,535 +0,0 @@
-#include
-#include
-#include
-#include
-
-#define HLSL_CPU
-#include "hle/rt64_application.h"
-#include "rt64_render_hooks.h"
-#include "overloaded.h"
-
-#include "ultramodern/ultramodern.hpp"
-#include "ultramodern/config.hpp"
-
-#include "banjo_render.h"
-#include "recomp_ui.h"
-#include "concurrentqueue.h"
-
-static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
-static bool sample_positions_supported = false;
-static bool high_precision_fb_enabled = false;
-
-static uint8_t DMEM[0x1000];
-static uint8_t IMEM[0x1000];
-
-struct TexturePackEnableAction {
- std::string mod_id;
-};
-
-struct TexturePackDisableAction {
- std::string mod_id;
-};
-
-struct TexturePackSecondaryEnableAction {
- std::string mod_id;
-};
-
-struct TexturePackSecondaryDisableAction {
- std::string mod_id;
-};
-
-struct TexturePackUpdateAction {
-};
-
-using TexturePackAction = std::variant;
-
-static moodycamel::ConcurrentQueue texture_pack_action_queue;
-
-unsigned int MI_INTR_REG = 0;
-
-unsigned int DPC_START_REG = 0;
-unsigned int DPC_END_REG = 0;
-unsigned int DPC_CURRENT_REG = 0;
-unsigned int DPC_STATUS_REG = 0;
-unsigned int DPC_CLOCK_REG = 0;
-unsigned int DPC_BUFBUSY_REG = 0;
-unsigned int DPC_PIPEBUSY_REG = 0;
-unsigned int DPC_TMEM_REG = 0;
-
-void dummy_check_interrupts() {}
-
-RT64::UserConfiguration::Antialiasing compute_max_supported_aa(plume::RenderSampleCounts bits) {
- if (bits & plume::RenderSampleCount::Bits::COUNT_2) {
- if (bits & plume::RenderSampleCount::Bits::COUNT_4) {
- if (bits & plume::RenderSampleCount::Bits::COUNT_8) {
- return RT64::UserConfiguration::Antialiasing::MSAA8X;
- }
- return RT64::UserConfiguration::Antialiasing::MSAA4X;
- }
- return RT64::UserConfiguration::Antialiasing::MSAA2X;
- };
- return RT64::UserConfiguration::Antialiasing::None;
-}
-
-RT64::UserConfiguration::AspectRatio to_rt64(ultramodern::renderer::AspectRatio option) {
- switch (option) {
- case ultramodern::renderer::AspectRatio::Original:
- return RT64::UserConfiguration::AspectRatio::Original;
- case ultramodern::renderer::AspectRatio::Expand:
- return RT64::UserConfiguration::AspectRatio::Expand;
- case ultramodern::renderer::AspectRatio::Manual:
- return RT64::UserConfiguration::AspectRatio::Manual;
- case ultramodern::renderer::AspectRatio::OptionCount:
- return RT64::UserConfiguration::AspectRatio::OptionCount;
- }
-}
-
-RT64::UserConfiguration::Antialiasing to_rt64(ultramodern::renderer::Antialiasing option) {
- switch (option) {
- case ultramodern::renderer::Antialiasing::None:
- return RT64::UserConfiguration::Antialiasing::None;
- case ultramodern::renderer::Antialiasing::MSAA2X:
- return RT64::UserConfiguration::Antialiasing::MSAA2X;
- case ultramodern::renderer::Antialiasing::MSAA4X:
- return RT64::UserConfiguration::Antialiasing::MSAA4X;
- case ultramodern::renderer::Antialiasing::MSAA8X:
- return RT64::UserConfiguration::Antialiasing::MSAA8X;
- case ultramodern::renderer::Antialiasing::OptionCount:
- return RT64::UserConfiguration::Antialiasing::OptionCount;
- }
-}
-
-RT64::UserConfiguration::RefreshRate to_rt64(ultramodern::renderer::RefreshRate option) {
- switch (option) {
- case ultramodern::renderer::RefreshRate::Original:
- return RT64::UserConfiguration::RefreshRate::Original;
- case ultramodern::renderer::RefreshRate::Display:
- return RT64::UserConfiguration::RefreshRate::Display;
- case ultramodern::renderer::RefreshRate::Manual:
- return RT64::UserConfiguration::RefreshRate::Manual;
- case ultramodern::renderer::RefreshRate::OptionCount:
- return RT64::UserConfiguration::RefreshRate::OptionCount;
- }
-}
-
-RT64::UserConfiguration::InternalColorFormat to_rt64(ultramodern::renderer::HighPrecisionFramebuffer option) {
- switch (option) {
- case ultramodern::renderer::HighPrecisionFramebuffer::Off:
- return RT64::UserConfiguration::InternalColorFormat::Standard;
- case ultramodern::renderer::HighPrecisionFramebuffer::On:
- return RT64::UserConfiguration::InternalColorFormat::High;
- case ultramodern::renderer::HighPrecisionFramebuffer::Auto:
- return RT64::UserConfiguration::InternalColorFormat::Automatic;
- case ultramodern::renderer::HighPrecisionFramebuffer::OptionCount:
- return RT64::UserConfiguration::InternalColorFormat::OptionCount;
- }
-}
-
-void set_application_user_config(RT64::Application* application, const ultramodern::renderer::GraphicsConfig& config) {
- switch (config.res_option) {
- default:
- case ultramodern::renderer::Resolution::Auto:
- application->userConfig.resolution = RT64::UserConfiguration::Resolution::WindowIntegerScale;
- application->userConfig.downsampleMultiplier = 1;
- break;
- case ultramodern::renderer::Resolution::Original:
- application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual;
- application->userConfig.resolutionMultiplier = std::max(config.ds_option, 1);
- application->userConfig.downsampleMultiplier = std::max(config.ds_option, 1);
- break;
- case ultramodern::renderer::Resolution::Original2x:
- application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual;
- application->userConfig.resolutionMultiplier = 2.0 * std::max(config.ds_option, 1);
- application->userConfig.downsampleMultiplier = std::max(config.ds_option, 1);
- break;
- }
-
- switch (config.hr_option) {
- default:
- case ultramodern::renderer::HUDRatioMode::Original:
- application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Original;
- break;
- case ultramodern::renderer::HUDRatioMode::Clamp16x9:
- application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Manual;
- application->userConfig.extAspectTarget = 16.0/9.0;
- break;
- case ultramodern::renderer::HUDRatioMode::Full:
- application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Expand;
- break;
- }
-
- application->userConfig.aspectRatio = to_rt64(config.ar_option);
- application->userConfig.antialiasing = to_rt64(config.msaa_option);
- application->userConfig.refreshRate = to_rt64(config.rr_option);
- application->userConfig.refreshRateTarget = config.rr_manual_value;
- application->userConfig.internalColorFormat = to_rt64(config.hpfb_option);
- application->userConfig.displayBuffering = RT64::UserConfiguration::DisplayBuffering::Triple;
-}
-
-ultramodern::renderer::SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) {
- switch (rt64_result) {
- case RT64::Application::SetupResult::Success:
- return ultramodern::renderer::SetupResult::Success;
- case RT64::Application::SetupResult::DynamicLibrariesNotFound:
- return ultramodern::renderer::SetupResult::DynamicLibrariesNotFound;
- case RT64::Application::SetupResult::InvalidGraphicsAPI:
- return ultramodern::renderer::SetupResult::InvalidGraphicsAPI;
- case RT64::Application::SetupResult::GraphicsAPINotFound:
- return ultramodern::renderer::SetupResult::GraphicsAPINotFound;
- case RT64::Application::SetupResult::GraphicsDeviceNotFound:
- return ultramodern::renderer::SetupResult::GraphicsDeviceNotFound;
- }
-
- fprintf(stderr, "Unhandled `RT64::Application::SetupResult` ?\n");
- assert(false);
- std::exit(EXIT_FAILURE);
-}
-
-ultramodern::renderer::GraphicsApi map_graphics_api(RT64::UserConfiguration::GraphicsAPI api) {
- switch (api) {
- case RT64::UserConfiguration::GraphicsAPI::D3D12:
- return ultramodern::renderer::GraphicsApi::D3D12;
- case RT64::UserConfiguration::GraphicsAPI::Vulkan:
- return ultramodern::renderer::GraphicsApi::Vulkan;
- case RT64::UserConfiguration::GraphicsAPI::Metal:
- return ultramodern::renderer::GraphicsApi::Metal;
- case RT64::UserConfiguration::GraphicsAPI::Automatic:
- return ultramodern::renderer::GraphicsApi::Auto;
- }
-
- fprintf(stderr, "Unhandled `RT64::UserConfiguration::GraphicsAPI` ?\n");
- assert(false);
- std::exit(EXIT_FAILURE);
-}
-
-banjo::renderer::RT64Context::RT64Context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool debug) {
- static unsigned char dummy_rom_header[0x40];
- recompui::set_render_hooks();
-
- // Set up the RT64 application core fields.
- RT64::Application::Core appCore{};
-#if defined(_WIN32)
- appCore.window = window_handle.window;
-#elif defined(__linux__) || defined(__ANDROID__)
- appCore.window = window_handle;
-#elif defined(__APPLE__)
- appCore.window.window = window_handle.window;
- appCore.window.view = window_handle.view;
-#endif
-
- appCore.checkInterrupts = dummy_check_interrupts;
-
- appCore.HEADER = dummy_rom_header;
- appCore.RDRAM = rdram;
- appCore.DMEM = DMEM;
- appCore.IMEM = IMEM;
-
- appCore.MI_INTR_REG = &MI_INTR_REG;
-
- appCore.DPC_START_REG = &DPC_START_REG;
- appCore.DPC_END_REG = &DPC_END_REG;
- appCore.DPC_CURRENT_REG = &DPC_CURRENT_REG;
- appCore.DPC_STATUS_REG = &DPC_STATUS_REG;
- appCore.DPC_CLOCK_REG = &DPC_CLOCK_REG;
- appCore.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG;
- appCore.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG;
- appCore.DPC_TMEM_REG = &DPC_TMEM_REG;
-
- ultramodern::renderer::ViRegs* vi_regs = ultramodern::renderer::get_vi_regs();
-
- appCore.VI_STATUS_REG = &vi_regs->VI_STATUS_REG;
- appCore.VI_ORIGIN_REG = &vi_regs->VI_ORIGIN_REG;
- appCore.VI_WIDTH_REG = &vi_regs->VI_WIDTH_REG;
- appCore.VI_INTR_REG = &vi_regs->VI_INTR_REG;
- appCore.VI_V_CURRENT_LINE_REG = &vi_regs->VI_V_CURRENT_LINE_REG;
- appCore.VI_TIMING_REG = &vi_regs->VI_TIMING_REG;
- appCore.VI_V_SYNC_REG = &vi_regs->VI_V_SYNC_REG;
- appCore.VI_H_SYNC_REG = &vi_regs->VI_H_SYNC_REG;
- appCore.VI_LEAP_REG = &vi_regs->VI_LEAP_REG;
- appCore.VI_H_START_REG = &vi_regs->VI_H_START_REG;
- appCore.VI_V_START_REG = &vi_regs->VI_V_START_REG;
- appCore.VI_V_BURST_REG = &vi_regs->VI_V_BURST_REG;
- appCore.VI_X_SCALE_REG = &vi_regs->VI_X_SCALE_REG;
- appCore.VI_Y_SCALE_REG = &vi_regs->VI_Y_SCALE_REG;
-
- // Set up the RT64 application configuration fields.
- RT64::ApplicationConfiguration appConfig;
- appConfig.useConfigurationFile = false;
-
- // Create the RT64 application.
- app = std::make_unique(appCore, appConfig);
-
- // Set initial user config settings based on the current settings.
- auto& cur_config = ultramodern::renderer::get_graphics_config();
- set_application_user_config(app.get(), cur_config);
- app->userConfig.developerMode = debug;
- // Force gbi depth branches to prevent LODs from kicking in.
- app->enhancementConfig.f3dex.forceBranch = true;
- // Scale LODs based on the output resolution.
- app->enhancementConfig.textureLOD.scale = true;
- // Pick an API if the user has set an override.
- switch (cur_config.api_option) {
- case ultramodern::renderer::GraphicsApi::D3D12:
- app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::D3D12;
- break;
- case ultramodern::renderer::GraphicsApi::Vulkan:
- app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::Vulkan;
- break;
- case ultramodern::renderer::GraphicsApi::Metal:
- app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::Metal;
- break;
- case ultramodern::renderer::GraphicsApi::Auto:
- app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::Automatic;
- break;
- }
-
- // Set up the RT64 application.
- uint32_t thread_id = 0;
-#ifdef _WIN32
- thread_id = window_handle.thread_id;
-#endif
- setup_result = map_setup_result(app->setup(thread_id));
- // Get the API that RT64 chose.
- chosen_api = map_graphics_api(app->chosenGraphicsAPI);
- if (setup_result != ultramodern::renderer::SetupResult::Success) {
- app = nullptr;
- return;
- }
-
- // Set the application's fullscreen state.
- app->setFullScreen(cur_config.wm_option == ultramodern::renderer::WindowMode::Fullscreen);
-
- // Check if the selected device actually supports MSAA sample positions and MSAA for for the formats that will be used
- // and downgrade the configuration accordingly.
- if (app->device->getCapabilities().sampleLocations) {
- plume::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(plume::RenderFormat::R8G8B8A8_UNORM);
- plume::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(plume::RenderFormat::D32_FLOAT);
- plume::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts;
- device_max_msaa = compute_max_supported_aa(common_sample_counts);
- sample_positions_supported = true;
- }
- else {
- device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
- sample_positions_supported = false;
- }
-
- high_precision_fb_enabled = app->shaderLibrary->usesHDR;
-}
-
-banjo::renderer::RT64Context::~RT64Context() = default;
-
-void banjo::renderer::RT64Context::send_dl(const OSTask* task) {
- check_texture_pack_actions();
- app->state->rsp->reset();
- app->interpreter->loadUCodeGBI(task->t.ucode & 0x3FFFFFF, task->t.ucode_data & 0x3FFFFFF, true);
- app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true);
-}
-
-void banjo::renderer::RT64Context::update_screen() {
- app->updateScreen();
-}
-
-void banjo::renderer::RT64Context::shutdown() {
- if (app != nullptr) {
- app->end();
- }
-}
-
-bool banjo::renderer::RT64Context::update_config(const ultramodern::renderer::GraphicsConfig& old_config, const ultramodern::renderer::GraphicsConfig& new_config) {
- if (old_config == new_config) {
- return false;
- }
-
- if (new_config.wm_option != old_config.wm_option) {
- app->setFullScreen(new_config.wm_option == ultramodern::renderer::WindowMode::Fullscreen);
- }
-
- set_application_user_config(app.get(), new_config);
-
- // When updating the user configuration, only discard framebuffers if an option was changed that affects the resolution.
- bool resolution_changed = new_config.res_option != old_config.res_option;
- bool aspect_ratio_changed = new_config.ar_option != old_config.ar_option;
- bool downsampling_changed = new_config.ds_option != old_config.ds_option;
- bool msaa_changed = new_config.msaa_option != old_config.msaa_option;
- app->updateUserConfig(resolution_changed || aspect_ratio_changed || downsampling_changed || msaa_changed);
-
- if (msaa_changed) {
- app->updateMultisampling();
- }
- return true;
-}
-
-void banjo::renderer::RT64Context::enable_instant_present() {
- // Enable the present early presentation mode for minimal latency.
- app->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly;
-
- app->updateEnhancementConfig();
-}
-
-uint32_t banjo::renderer::RT64Context::get_display_framerate() const {
- return app->presentQueue->ext.sharedResources->swapChainRate;
-}
-
-float banjo::renderer::RT64Context::get_resolution_scale() const {
- constexpr int ReferenceHeight = 240;
- switch (app->userConfig.resolution) {
- case RT64::UserConfiguration::Resolution::WindowIntegerScale:
- if (app->sharedQueueResources->swapChainHeight > 0) {
- return std::max(float((app->sharedQueueResources->swapChainHeight + ReferenceHeight - 1) / ReferenceHeight), 1.0f);
- }
- else {
- return 1.0f;
- }
- case RT64::UserConfiguration::Resolution::Manual:
- return float(app->userConfig.resolutionMultiplier);
- case RT64::UserConfiguration::Resolution::Original:
- default:
- return 1.0f;
- }
-}
-
-void banjo::renderer::RT64Context::check_texture_pack_actions() {
- bool packs_changed = false;
- TexturePackAction cur_action;
- while (texture_pack_action_queue.try_dequeue(cur_action)) {
- std::visit(overloaded{
- [&](TexturePackDisableAction &to_disable) {
- enabled_texture_packs.erase(to_disable.mod_id);
- packs_changed = true;
- },
- [&](TexturePackEnableAction &to_enable) {
- enabled_texture_packs.insert(to_enable.mod_id);
- packs_changed = true;
- },
- [&](TexturePackSecondaryDisableAction &to_override_disable) {
- secondary_disabled_texture_packs.insert(to_override_disable.mod_id);
- packs_changed = true;
- },
- [&](TexturePackSecondaryEnableAction &to_override_enable) {
- secondary_disabled_texture_packs.erase(to_override_enable.mod_id);
- packs_changed = true;
- },
- [&](TexturePackUpdateAction &) {
- packs_changed = true;
- }
- }, cur_action);
- }
-
- // If any packs were disabled, unload all packs and load all the active ones.
- if (packs_changed) {
- // Sort the enabled texture packs in reverse order so that earlier ones override later ones.
- std::vector sorted_texture_packs{};
- sorted_texture_packs.reserve(enabled_texture_packs.size());
- for (const std::string& mod : enabled_texture_packs) {
- if (!secondary_disabled_texture_packs.contains(mod)) {
- sorted_texture_packs.emplace_back(mod);
- }
- }
-
- std::sort(sorted_texture_packs.begin(), sorted_texture_packs.end(),
- [](const std::string& lhs, const std::string& rhs) {
- return recomp::mods::get_mod_order_index(lhs) > recomp::mods::get_mod_order_index(rhs);
- }
- );
-
- // Build the path list from the sorted mod list.
- std::vector replacement_directories;
- replacement_directories.reserve(enabled_texture_packs.size());
- for (const std::string &mod_id : sorted_texture_packs) {
- replacement_directories.emplace_back(RT64::ReplacementDirectory(recomp::mods::get_mod_filename(mod_id)));
- }
-
- if (!replacement_directories.empty()) {
- app->textureCache->loadReplacementDirectories(replacement_directories);
- }
- else {
- app->textureCache->clearReplacementDirectories();
- }
- }
-}
-
-RT64::UserConfiguration::Antialiasing banjo::renderer::RT64MaxMSAA() {
- return device_max_msaa;
-}
-
-std::unique_ptr banjo::renderer::create_render_context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode) {
- return std::make_unique(rdram, window_handle, developer_mode);
-}
-
-bool banjo::renderer::RT64SamplePositionsSupported() {
- return sample_positions_supported;
-}
-
-bool banjo::renderer::RT64HighPrecisionFBEnabled() {
- return high_precision_fb_enabled;
-}
-
-void banjo::renderer::trigger_texture_pack_update() {
- texture_pack_action_queue.enqueue(TexturePackUpdateAction{});
-}
-
-void banjo::renderer::enable_texture_pack(const recomp::mods::ModContext& context, const recomp::mods::ModHandle& mod) {
- texture_pack_action_queue.enqueue(TexturePackEnableAction{mod.manifest.mod_id});
-
- // Check for the texture pack enabled config option.
- const recomp::mods::ConfigSchema& config_schema = context.get_mod_config_schema(mod.manifest.mod_id);
- auto find_it = config_schema.options_by_id.find(banjo::renderer::special_option_texture_pack_enabled);
- if (find_it != config_schema.options_by_id.end()) {
- const recomp::mods::ConfigOption& config_option = config_schema.options[find_it->second];
-
- if (is_texture_pack_enable_config_option(config_option, false)) {
- recomp::mods::ConfigValueVariant value_variant = context.get_mod_config_value(mod.manifest.mod_id, config_option.id);
- uint32_t value;
- if (uint32_t* value_ptr = std::get_if(&value_variant)) {
- value = *value_ptr;
- }
- else {
- value = 0;
- }
-
- if (value) {
- banjo::renderer::secondary_enable_texture_pack(mod.manifest.mod_id);
- }
- else {
- banjo::renderer::secondary_disable_texture_pack(mod.manifest.mod_id);
- }
- }
- }
-}
-
-void banjo::renderer::disable_texture_pack(const recomp::mods::ModHandle& mod) {
- texture_pack_action_queue.enqueue(TexturePackDisableAction{mod.manifest.mod_id});
-}
-
-void banjo::renderer::secondary_enable_texture_pack(const std::string& mod_id) {
- texture_pack_action_queue.enqueue(TexturePackSecondaryEnableAction{mod_id});
-}
-
-void banjo::renderer::secondary_disable_texture_pack(const std::string& mod_id) {
- texture_pack_action_queue.enqueue(TexturePackSecondaryDisableAction{mod_id});
-}
-
-
-// HD texture enable option. Must be an enum with two options.
-// The first option is treated as disabled and the second option is treated as enabled.
-bool banjo::renderer::is_texture_pack_enable_config_option(const recomp::mods::ConfigOption& option, bool show_errors) {
- if (option.id == banjo::renderer::special_option_texture_pack_enabled) {
- if (option.type != recomp::mods::ConfigOptionType::Enum) {
- if (show_errors) {
- recompui::message_box(("Mod has the special config option id for enabling an HD texture pack (\"" + banjo::renderer::special_option_texture_pack_enabled + "\"), but the config option is not an enum.").c_str());
- }
- return false;
- }
-
- const recomp::mods::ConfigOptionEnum &option_enum = std::get(option.variant);
- if (option_enum.options.size() != 2) {
- if (show_errors) {
- recompui::message_box(("Mod has the special config option id for enabling an HD texture pack (\"" + banjo::renderer::special_option_texture_pack_enabled + "\"), but the config option doesn't have exactly 2 values.").c_str());
- }
- return false;
- }
-
- return true;
- }
- return false;
-}
diff --git a/src/main/support.cpp b/src/main/support.cpp
deleted file mode 100644
index fb4649a..0000000
--- a/src/main/support.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "banjo_support.h"
-#include
-#include "nfd.h"
-#include "RmlUi/Core.h"
-
-namespace banjo {
- // MARK: - Internal Helpers
- void perform_file_dialog_operation(const std::function& callback) {
- nfdnchar_t* native_path = nullptr;
- nfdresult_t result = NFD_OpenDialogN(&native_path, nullptr, 0, nullptr);
-
- bool success = (result == NFD_OKAY);
- std::filesystem::path path;
-
- if (success) {
- path = std::filesystem::path{native_path};
- NFD_FreePathN(native_path);
- }
-
- callback(success, path);
- }
-
- void perform_file_dialog_operation_multiple(const std::function&)>& callback) {
- const nfdpathset_t* native_paths = nullptr;
- nfdresult_t result = NFD_OpenDialogMultipleN(&native_paths, nullptr, 0, nullptr);
-
- bool success = (result == NFD_OKAY);
- std::list paths;
- nfdpathsetsize_t count = 0;
-
- if (success) {
- NFD_PathSet_GetCount(native_paths, &count);
- for (nfdpathsetsize_t i = 0; i < count; i++) {
- nfdnchar_t* cur_path = nullptr;
- nfdresult_t cur_result = NFD_PathSet_GetPathN(native_paths, i, &cur_path);
- if (cur_result == NFD_OKAY) {
- paths.emplace_back(std::filesystem::path{cur_path});
- }
- }
- NFD_PathSet_Free(native_paths);
- }
-
- callback(success, paths);
- }
-
- // MARK: - Public API
-
- std::filesystem::path get_program_path() {
-#if defined(__APPLE__)
- return get_bundle_resource_directory();
-#elif defined(__linux__) && defined(RECOMP_FLATPAK)
- return "/app/bin";
-#else
- return "";
-#endif
- }
-
- std::filesystem::path get_asset_path(const char* asset) {
- return get_program_path() / "assets" / asset;
- }
-
- void open_file_dialog(std::function callback) {
-#ifdef __APPLE__
- dispatch_on_ui_thread([callback]() {
- perform_file_dialog_operation(callback);
- });
-#else
- perform_file_dialog_operation(callback);
-#endif
- }
-
- void open_file_dialog_multiple(std::function& paths)> callback) {
-#ifdef __APPLE__
- dispatch_on_ui_thread([callback]() {
- perform_file_dialog_operation_multiple(callback);
- });
-#else
- perform_file_dialog_operation_multiple(callback);
-#endif
- }
-
- void show_error_message_box(const char *title, const char *message) {
-#ifdef __APPLE__
- std::string title_copy(title);
- std::string message_copy(message);
-
- dispatch_on_ui_thread([title_copy, message_copy] {
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title_copy.c_str(), message_copy.c_str(), nullptr);
- });
-#else
- SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, nullptr);
-#endif
- }
-}
diff --git a/src/main/theme.cpp b/src/main/theme.cpp
index 228f7e4..513b6bd 100644
--- a/src/main/theme.cpp
+++ b/src/main/theme.cpp
@@ -1,88 +1,92 @@
-#include "recomp_ui.h"
+#include "elements/ui_theme.h"
#include "theme.h"
void recomptheme::set_custom_theme() {
- recompui::set_theme_color(recompui::ThemeColor::Background1, recompui::Color{2, 7, 18, 255});
- recompui::set_theme_color(recompui::ThemeColor::Background2, recompui::Color{7, 15, 34, 255});
- recompui::set_theme_color(recompui::ThemeColor::Background3, recompui::Color{18, 24, 38, 255});
- recompui::set_theme_color(recompui::ThemeColor::BGOverlay, recompui::Color{182, 194, 221, 26});
- recompui::set_theme_color(recompui::ThemeColor::ModalOverlay, recompui::Color{2, 7, 18, 229});
- recompui::set_theme_color(recompui::ThemeColor::BGShadow, recompui::Color{0, 0, 0, 89});
- recompui::set_theme_color(recompui::ThemeColor::BGShadow2, recompui::Color{2, 7, 18, 184});
- recompui::set_theme_color(recompui::ThemeColor::Text, recompui::Color{242, 242, 242, 255});
- recompui::set_theme_color(recompui::ThemeColor::TextActive, recompui::Color{245, 245, 245, 255});
- recompui::set_theme_color(recompui::ThemeColor::TextDim, recompui::Color{204, 204, 204, 255});
- recompui::set_theme_color(recompui::ThemeColor::TextInactive, recompui::Color{255, 255, 255, 153});
- recompui::set_theme_color(recompui::ThemeColor::TextA5, recompui::Color{242, 242, 242, 13});
- recompui::set_theme_color(recompui::ThemeColor::TextA20, recompui::Color{242, 242, 242, 51});
- recompui::set_theme_color(recompui::ThemeColor::TextA30, recompui::Color{242, 242, 242, 77});
- recompui::set_theme_color(recompui::ThemeColor::TextA50, recompui::Color{242, 242, 242, 128});
- recompui::set_theme_color(recompui::ThemeColor::TextA80, recompui::Color{242, 242, 242, 204});
- recompui::set_theme_color(recompui::ThemeColor::Primary, recompui::Color{29, 93, 226, 255});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryL, recompui::Color{167, 191, 241, 255});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryD, recompui::Color{0, 38, 117, 255});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryA5, recompui::Color{29, 93, 226, 13});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryA20, recompui::Color{29, 93, 226, 51});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryA30, recompui::Color{29, 93, 226, 77});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryA50, recompui::Color{29, 93, 226, 128});
- recompui::set_theme_color(recompui::ThemeColor::PrimaryA80, recompui::Color{29, 93, 226, 204});
- recompui::set_theme_color(recompui::ThemeColor::Secondary, recompui::Color{247, 158, 8, 255});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryL, recompui::Color{255, 215, 148, 255});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryD, recompui::Color{224, 141, 0, 255});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryA5, recompui::Color{247, 158, 8, 13});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryA20, recompui::Color{247, 158, 8, 51});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryA30, recompui::Color{247, 158, 8, 77});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryA50, recompui::Color{247, 158, 8, 128});
- recompui::set_theme_color(recompui::ThemeColor::SecondaryA80, recompui::Color{247, 158, 8, 204});
- recompui::set_theme_color(recompui::ThemeColor::Warning, recompui::Color{255, 254, 0, 255});
- recompui::set_theme_color(recompui::ThemeColor::WarningL, recompui::Color{255, 254, 143, 255});
- recompui::set_theme_color(recompui::ThemeColor::WarningD, recompui::Color{197, 163, 2, 255});
- recompui::set_theme_color(recompui::ThemeColor::WarningA5, recompui::Color{255, 254, 0, 13});
- recompui::set_theme_color(recompui::ThemeColor::WarningA20, recompui::Color{255, 254, 0, 51});
- recompui::set_theme_color(recompui::ThemeColor::WarningA30, recompui::Color{255, 254, 0, 77});
- recompui::set_theme_color(recompui::ThemeColor::WarningA50, recompui::Color{255, 254, 0, 128});
- recompui::set_theme_color(recompui::ThemeColor::WarningA80, recompui::Color{255, 254, 0, 204});
- recompui::set_theme_color(recompui::ThemeColor::Danger, recompui::Color{255, 53, 31, 255});
- recompui::set_theme_color(recompui::ThemeColor::DangerL, recompui::Color{255, 149, 138, 255});
- recompui::set_theme_color(recompui::ThemeColor::DangerD, recompui::Color{163, 16, 0, 255});
- recompui::set_theme_color(recompui::ThemeColor::DangerA5, recompui::Color{255, 53, 31, 13});
- recompui::set_theme_color(recompui::ThemeColor::DangerA20, recompui::Color{255, 53, 31, 51});
- recompui::set_theme_color(recompui::ThemeColor::DangerA30, recompui::Color{255, 53, 31, 77});
- recompui::set_theme_color(recompui::ThemeColor::DangerA50, recompui::Color{255, 53, 31, 128});
- recompui::set_theme_color(recompui::ThemeColor::DangerA80, recompui::Color{255, 53, 31, 204});
- recompui::set_theme_color(recompui::ThemeColor::Success, recompui::Color{40, 238, 32, 255});
- recompui::set_theme_color(recompui::ThemeColor::SuccessL, recompui::Color{155, 247, 151, 255});
- recompui::set_theme_color(recompui::ThemeColor::SuccessD, recompui::Color{18, 157, 12, 255});
- recompui::set_theme_color(recompui::ThemeColor::SuccessA5, recompui::Color{40, 238, 32, 13});
- recompui::set_theme_color(recompui::ThemeColor::SuccessA20, recompui::Color{40, 238, 32, 51});
- recompui::set_theme_color(recompui::ThemeColor::SuccessA30, recompui::Color{40, 238, 32, 77});
- recompui::set_theme_color(recompui::ThemeColor::SuccessA50, recompui::Color{40, 238, 32, 128});
- recompui::set_theme_color(recompui::ThemeColor::SuccessA80, recompui::Color{40, 238, 32, 204});
- recompui::set_theme_color(recompui::ThemeColor::Border, recompui::Color{255, 255, 255, 51});
- recompui::set_theme_color(recompui::ThemeColor::BorderSoft, recompui::Color{255, 255, 255, 26});
- recompui::set_theme_color(recompui::ThemeColor::BorderHard, recompui::Color{255, 255, 255, 77});
- recompui::set_theme_color(recompui::ThemeColor::BorderSolid, recompui::Color{255, 255, 255, 153});
- recompui::set_theme_color(recompui::ThemeColor::Transparent, recompui::Color{0, 0, 0, 0});
- recompui::set_theme_color(recompui::ThemeColor::A, recompui::Color{51, 51, 255, 255});
- recompui::set_theme_color(recompui::ThemeColor::AL, recompui::Color{178, 178, 255, 255});
- recompui::set_theme_color(recompui::ThemeColor::AD, recompui::Color{32, 32, 172, 255});
- recompui::set_theme_color(recompui::ThemeColor::AA5, recompui::Color{51, 51, 255, 13});
- recompui::set_theme_color(recompui::ThemeColor::AA20, recompui::Color{51, 51, 255, 51});
- recompui::set_theme_color(recompui::ThemeColor::AA30, recompui::Color{51, 51, 255, 77});
- recompui::set_theme_color(recompui::ThemeColor::AA50, recompui::Color{51, 51, 255, 128});
- recompui::set_theme_color(recompui::ThemeColor::AA80, recompui::Color{51, 51, 255, 204});
- recompui::set_theme_color(recompui::ThemeColor::White, recompui::Color{255, 255, 255, 255});
- recompui::set_theme_color(recompui::ThemeColor::WhiteA5, recompui::Color{255, 255, 255, 13});
- recompui::set_theme_color(recompui::ThemeColor::WhiteA20, recompui::Color{255, 255, 255, 51});
- recompui::set_theme_color(recompui::ThemeColor::WhiteA30, recompui::Color{255, 255, 255, 77});
- recompui::set_theme_color(recompui::ThemeColor::WhiteA50, recompui::Color{255, 255, 255, 128});
- recompui::set_theme_color(recompui::ThemeColor::WhiteA80, recompui::Color{255, 255, 255, 204});
- recompui::set_theme_color(recompui::ThemeColor::BW05, recompui::Color{13, 13, 13, 255});
- recompui::set_theme_color(recompui::ThemeColor::BW10, recompui::Color{26, 26, 26, 255});
- recompui::set_theme_color(recompui::ThemeColor::BW25, recompui::Color{64, 64, 64, 255});
- recompui::set_theme_color(recompui::ThemeColor::BW50, recompui::Color{128, 128, 128, 255});
- recompui::set_theme_color(recompui::ThemeColor::BW75, recompui::Color{191, 191, 191, 255});
- recompui::set_theme_color(recompui::ThemeColor::BW90, recompui::Color{229, 229, 229, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::Background1, recompui::Color{10, 10, 11, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::Background2, recompui::Color{19, 20, 21, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::Background3, recompui::Color{27, 27, 29, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BGOverlay, recompui::Color{199, 200, 204, 26}); // actually the overlay for the modal
+ recompui::theme::set_theme_color(recompui::theme::color::ModalOverlay, recompui::Color{10, 10, 11, 242}); // actually the background color of the modal itself
+ recompui::theme::set_theme_color(recompui::theme::color::BGShadow, recompui::Color{0, 0, 0, 89});
+ recompui::theme::set_theme_color(recompui::theme::color::BGShadow2, recompui::Color{10, 10, 11, 184});
+ recompui::theme::set_theme_color(recompui::theme::color::Text, recompui::Color{242, 242, 242, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::TextActive, recompui::Color{245, 245, 245, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::TextDim, recompui::Color{204, 204, 204, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::TextInactive, recompui::Color{255, 255, 255, 153});
+ recompui::theme::set_theme_color(recompui::theme::color::TextA5, recompui::Color{242, 242, 242, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::TextA20, recompui::Color{242, 242, 242, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::TextA30, recompui::Color{242, 242, 242, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::TextA50, recompui::Color{242, 242, 242, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::TextA80, recompui::Color{242, 242, 242, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Primary, recompui::Color{29, 93, 226, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryL, recompui::Color{167, 191, 241, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryD, recompui::Color{0, 38, 117, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryA5, recompui::Color{29, 93, 226, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryA20, recompui::Color{29, 93, 226, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryA30, recompui::Color{29, 93, 226, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryA50, recompui::Color{29, 93, 226, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::PrimaryA80, recompui::Color{29, 93, 226, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Secondary, recompui::Color{247, 158, 8, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryL, recompui::Color{255, 215, 148, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryD, recompui::Color{224, 141, 0, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryA5, recompui::Color{247, 158, 8, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryA20, recompui::Color{247, 158, 8, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryA30, recompui::Color{247, 158, 8, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryA50, recompui::Color{247, 158, 8, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::SecondaryA80, recompui::Color{247, 158, 8, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Warning, recompui::Color{255, 254, 0, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningL, recompui::Color{255, 254, 143, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningD, recompui::Color{197, 163, 2, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningA5, recompui::Color{255, 254, 0, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningA20, recompui::Color{255, 254, 0, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningA30, recompui::Color{255, 254, 0, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningA50, recompui::Color{255, 254, 0, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::WarningA80, recompui::Color{255, 254, 0, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Danger, recompui::Color{255, 53, 31, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerL, recompui::Color{255, 149, 138, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerD, recompui::Color{163, 16, 0, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerA5, recompui::Color{255, 53, 31, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerA20, recompui::Color{255, 53, 31, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerA30, recompui::Color{255, 53, 31, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerA50, recompui::Color{255, 53, 31, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::DangerA80, recompui::Color{255, 53, 31, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Success, recompui::Color{40, 238, 32, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessL, recompui::Color{155, 247, 151, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessD, recompui::Color{18, 157, 12, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessA5, recompui::Color{40, 238, 32, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessA20, recompui::Color{40, 238, 32, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessA30, recompui::Color{40, 238, 32, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessA50, recompui::Color{40, 238, 32, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::SuccessA80, recompui::Color{40, 238, 32, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::Border, recompui::Color{255, 255, 255, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::BorderSoft, recompui::Color{255, 255, 255, 26});
+ recompui::theme::set_theme_color(recompui::theme::color::BorderHard, recompui::Color{255, 255, 255, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::BorderSolid, recompui::Color{255, 255, 255, 153});
+ recompui::theme::set_theme_color(recompui::theme::color::Transparent, recompui::Color{0, 0, 0, 0});
+ recompui::theme::set_theme_color(recompui::theme::color::A, recompui::Color{51, 51, 255, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::AL, recompui::Color{178, 178, 255, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::AD, recompui::Color{32, 32, 172, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::AA5, recompui::Color{51, 51, 255, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::AA20, recompui::Color{51, 51, 255, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::AA30, recompui::Color{51, 51, 255, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::AA50, recompui::Color{51, 51, 255, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::AA80, recompui::Color{51, 51, 255, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::White, recompui::Color{255, 255, 255, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::WhiteA5, recompui::Color{255, 255, 255, 13});
+ recompui::theme::set_theme_color(recompui::theme::color::WhiteA20, recompui::Color{255, 255, 255, 51});
+ recompui::theme::set_theme_color(recompui::theme::color::WhiteA30, recompui::Color{255, 255, 255, 77});
+ recompui::theme::set_theme_color(recompui::theme::color::WhiteA50, recompui::Color{255, 255, 255, 128});
+ recompui::theme::set_theme_color(recompui::theme::color::WhiteA80, recompui::Color{255, 255, 255, 204});
+ recompui::theme::set_theme_color(recompui::theme::color::BW05, recompui::Color{13, 13, 13, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BW10, recompui::Color{26, 26, 26, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BW25, recompui::Color{64, 64, 64, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BW50, recompui::Color{128, 128, 128, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BW75, recompui::Color{191, 191, 191, 255});
+ recompui::theme::set_theme_color(recompui::theme::color::BW90, recompui::Color{229, 229, 229, 255});
+
+ recompui::theme::border::radius_sm = 12.0f;
+ recompui::theme::border::radius_md = 18.0f;
+ recompui::theme::border::radius_lg = 24.0f;
};
diff --git a/src/ui/core/ui_context.cpp b/src/ui/core/ui_context.cpp
deleted file mode 100644
index cff69fc..0000000
--- a/src/ui/core/ui_context.cpp
+++ /dev/null
@@ -1,725 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "slot_map.h"
-#include "RmlUi/Core/StreamMemory.h"
-
-#include "ultramodern/error_handling.hpp"
-#include "recomp_ui.h"
-#include "ui_context.h"
-#include "../elements/ui_element.h"
-
-// Hash implementations for ContextId and ResourceId.
-template <>
-struct std::hash {
- std::size_t operator()(const recompui::ContextId& id) const {
- return std::hash()(id.slot_id);
- }
-};
-
-template <>
-struct std::hash {
- std::size_t operator()(const recompui::ResourceId& id) const {
- return std::hash()(id.slot_id);
- }
-};
-
-using resource_slotmap = dod::slot_map32>;
-
-namespace recompui {
- struct Context {
- std::mutex context_lock;
- resource_slotmap resources;
- Rml::ElementDocument* document;
- Element root_element;
- Element* autofocus_element = nullptr;
- std::vector loose_elements;
- std::unordered_set to_update;
- std::vector> to_set_text;
- bool captures_input = true;
- bool captures_mouse = true;
- Context(Rml::ElementDocument* document) : document(document), root_element(document) {}
- };
-} // namespace recompui
-
-using context_slotmap = dod::slot_map32;
-
-static struct {
- std::recursive_mutex all_contexts_lock;
- context_slotmap all_contexts;
- std::unordered_set opened_contexts;
- std::unordered_map documents_to_contexts;
- Rml::SharedPtr style_sheet;
-} context_state;
-
-thread_local recompui::Context* opened_context = nullptr;
-thread_local recompui::ContextId opened_context_id = recompui::ContextId::null();
-
-enum class ContextErrorType {
- OpenWithoutClose,
- OpenInvalidContext,
- CloseWithoutOpen,
- CloseWrongContext,
- DestroyInvalidContext,
- GetContextWithoutOpen,
- AddResourceWithoutOpen,
- AddResourceToWrongContext,
- UpdateElementWithoutContext,
- UpdateElementInWrongContext,
- SetTextElementWithoutContext,
- SetTextElementInWrongContext,
- GetResourceWithoutOpen,
- GetResourceFailed,
- DestroyResourceWithoutOpen,
- DestroyResourceInWrongContext,
- DestroyResourceNotFound,
- GetDocumentInvalidContext,
- GetAutofocusInvalidContext,
- SetAutofocusInvalidContext,
- InternalError,
-};
-
-enum class SlotTag : uint8_t {
- Style = 0,
- Element = 1,
-};
-
-void context_error(recompui::ContextId id, ContextErrorType type) {
- (void)id;
-
- const char* error_message = "";
-
- switch (type) {
- case ContextErrorType::OpenWithoutClose:
- error_message = "Attempted to open a UI context without closing another UI context";
- break;
- case ContextErrorType::OpenInvalidContext:
- error_message = "Attempted to open an invalid UI context";
- break;
- case ContextErrorType::CloseWithoutOpen:
- error_message = "Attempted to close a UI context without one being open";
- break;
- case ContextErrorType::CloseWrongContext:
- error_message = "Attempted to close a different UI context than the one that's open";
- break;
- case ContextErrorType::DestroyInvalidContext:
- error_message = "Attempted to destroy an invalid UI element";
- break;
- case ContextErrorType::GetContextWithoutOpen:
- error_message = "Attempted to get the current UI context with no UI context open";
- break;
- case ContextErrorType::AddResourceWithoutOpen:
- error_message = "Attempted to create a UI resource with no open UI context";
- break;
- case ContextErrorType::AddResourceToWrongContext:
- error_message = "Attempted to create a UI resource in a different UI context than the one that's open";
- break;
- case ContextErrorType::UpdateElementWithoutContext:
- error_message = "Attempted to update a UI element with no open UI context";
- break;
- case ContextErrorType::UpdateElementInWrongContext:
- error_message = "Attempted to update a UI element in a different UI context than the one that's open";
- break;
- case ContextErrorType::SetTextElementWithoutContext:
- error_message = "Attempted to set the text of a UI element with no open UI context";
- break;
- case ContextErrorType::SetTextElementInWrongContext:
- error_message = "Attempted to set the text of a UI element in a different UI context than the one that's open";
- break;
- case ContextErrorType::GetResourceWithoutOpen:
- error_message = "Attempted to get a UI resource with no open UI context";
- break;
- case ContextErrorType::GetResourceFailed:
- error_message = "Failed to get a UI resource from the current open UI context";
- break;
- case ContextErrorType::DestroyResourceWithoutOpen:
- error_message = "Attempted to destroy a UI resource with no open UI context";
- break;
- case ContextErrorType::DestroyResourceInWrongContext:
- error_message = "Attempted to destroy a UI resource in a different UI context than the one that's open";
- break;
- case ContextErrorType::DestroyResourceNotFound:
- error_message = "Attempted to destroy a UI resource that doesn't exist in the current context";
- break;
- case ContextErrorType::GetDocumentInvalidContext:
- error_message = "Attempted to get the document of an invalid UI context";
- break;
- case ContextErrorType::GetAutofocusInvalidContext:
- error_message = "Attempted to get the autofocus element of an invalid UI context";
- break;
- case ContextErrorType::SetAutofocusInvalidContext:
- error_message = "Attempted to set the autofocus element of an invalid UI context";
- break;
- case ContextErrorType::InternalError:
- error_message = "Internal error in UI context";
- break;
- default:
- error_message = "Unknown UI context error";
- break;
- }
-
- // This assumes the error is coming from a mod, as it's unlikely that an end user will see a UI context error
- // in the base recomp.
- recompui::message_box((std::string{"Fatal error in mod - "} + error_message + ".").c_str());
- assert(false);
- ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
-}
-
-recompui::ContextId create_context_impl(Rml::ElementDocument* document) {
- static Rml::ElementDocument dummy_document{""};
- bool add_to_dict = true;
-
- if (document == nullptr) {
- document = &dummy_document;
- add_to_dict = false;
- }
-
- recompui::ContextId ret;
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- ret = { context_state.all_contexts.emplace(document).raw };
-
- if (add_to_dict) {
- context_state.documents_to_contexts.emplace(document, ret);
- }
- }
-
- return ret;
-}
-
-void recompui::init_styling(const std::filesystem::path& rcss_file) {
- std::string style{};
- {
- std::ifstream style_stream{rcss_file};
- style_stream.seekg(0, std::ios::end);
- style.resize(style_stream.tellg());
- style_stream.seekg(0, std::ios::beg);
-
- style_stream.read(style.data(), style.size());
- }
- std::unique_ptr rml_stream = std::make_unique(reinterpret_cast(style.data()), style.size());
- rml_stream->SetSourceURL(rcss_file.filename().string());
- context_state.style_sheet = Rml::Factory::InstanceStyleSheetStream(rml_stream.get());
-}
-
-recompui::ContextId recompui::create_context(const std::filesystem::path& path) {
- ContextId new_context = create_context_impl(nullptr);
-
- auto workingdir = std::filesystem::current_path();
-
- new_context.open();
- Rml::ElementDocument* doc = recompui::load_document(path.string());
- opened_context->document = doc;
- opened_context->root_element.base = doc;
- new_context.close();
-
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- context_state.documents_to_contexts.emplace(doc, new_context);
- }
-
- return new_context;
-}
-
-recompui::ContextId recompui::create_context(Rml::ElementDocument* document) {
- assert(document != nullptr);
-
- return create_context_impl(document);
-}
-
-recompui::ContextId recompui::create_context() {
- Rml::ElementDocument* doc = create_empty_document();
- doc->SetStyleSheetContainer(context_state.style_sheet);
- ContextId ret = create_context_impl(doc);
- Element* root = ret.get_root_element();
- // Mark the root element as not being a shim, as that's only needed for elements that were parented to Rml ones manually.
- root->shim = false;
-
- ret.open();
- root->set_width(100.0f, Unit::Percent);
- root->set_height(100.0f, Unit::Percent);
- root->set_display(Display::Flex);
- ret.close();
-
- doc->Hide();
-
- return ret;
-}
-
-void recompui::destroy_context(ContextId id) {
- bool existed = false;
-
- // TODO prevent deletion of a context while its mutex is in use. Second lock on the context's mutex before popping
- // from the slotmap?
-
- // Check if the provided id exists.
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- // Check if the target context is currently open.
- existed = context_state.all_contexts.has_key(context_slotmap::key{ id.slot_id });
- }
-
-
- // Raise an error if the context didn't exist.
- if (!existed) {
- context_error(id, ContextErrorType::DestroyInvalidContext);
- }
-
- id.open();
- id.clear_children();
- id.close();
-
- // Delete the provided id.
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- context_state.all_contexts.erase(context_slotmap::key{ id.slot_id });
- }
-}
-
-void recompui::destroy_all_contexts() {
- recompui::hide_all_contexts();
-
- std::lock_guard lock{ context_state.all_contexts_lock };
-
- // TODO prevent deletion of a context while its mutex is in use. Second lock on the context's mutex before popping
- // from the slotmap
-
- std::vector keys{};
- for (const auto& [key, item] : context_state.all_contexts.items()) {
- keys.push_back(key);
- }
-
- for (auto key : keys) {
- Context* ctx = context_state.all_contexts.get(key);
-
- std::lock_guard context_lock{ ctx->context_lock };
- opened_context = ctx;
- opened_context_id = ContextId{ key };
-
- opened_context_id.clear_children();
-
- opened_context = nullptr;
- opened_context_id = ContextId::null();
- }
-
- context_state.all_contexts.reset();
- context_state.documents_to_contexts.clear();
-}
-
-void recompui::ContextId::open() {
- // Ensure no other context is opened by this thread already.
- if (opened_context_id != ContextId::null()) {
- context_error(*this, ContextErrorType::OpenWithoutClose);
- }
-
- // Get the context with this id.
- Context* ctx;
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- ctx = context_state.all_contexts.get(context_slotmap::key{ slot_id });
- // If the context was found, add it to the opened contexts.
- if (ctx != nullptr) {
- context_state.opened_contexts.emplace(*this);
- }
- }
-
- // Check if the context exists.
- if (ctx == nullptr) {
- context_error(*this, ContextErrorType::OpenInvalidContext);
- }
-
- // Take ownership of the target context.
- ctx->context_lock.lock();
- opened_context = ctx;
- opened_context_id = *this;
-}
-
-bool recompui::ContextId::open_if_not_already() {
- if (opened_context_id == *this) {
- return false;
- }
-
- open();
- return true;
-}
-
-void recompui::ContextId::close() {
- // Ensure a context is currently opened by this thread.
- if (opened_context_id == ContextId::null()) {
- context_error(*this, ContextErrorType::CloseWithoutOpen);
- }
-
- // Check that the context that was specified is the same one that's currently open.
- if (*this != opened_context_id) {
- context_error(*this, ContextErrorType::CloseWrongContext);
- }
-
- // Release ownership of the target context.
- opened_context->context_lock.unlock();
- opened_context = nullptr;
- opened_context_id = ContextId::null();
-
- // Remove this context from the opened contexts.
- {
- std::lock_guard lock{ context_state.all_contexts_lock };
- context_state.opened_contexts.erase(*this);
- }
-}
-
-recompui::ContextId recompui::try_close_current_context() {
- if (opened_context_id != ContextId::null()) {
- ContextId prev_context = opened_context_id;
- opened_context_id.close();
- return prev_context;
- }
- return ContextId::null();
-}
-
-void recompui::ContextId::process_updates() {
- // Ensure a context is currently opened by this thread.
- if (opened_context_id == ContextId::null()) {
- context_error(*this, ContextErrorType::InternalError);
- }
-
- // Check that the context that was specified is the same one that's currently open.
- if (*this != opened_context_id) {
- context_error(*this, ContextErrorType::InternalError);
- }
-
- // Move the current update set into a local variable. This clears the update set
- // and allows it to be used to queue updates from any element callbacks.
- std::unordered_set to_update = std::move(opened_context->to_update);
-
- Event update_event = Event::update_event();
-
- for (auto cur_resource_id : to_update) {
- resource_slotmap::key cur_key{ cur_resource_id.slot_id };
-
- // Ignore any resources that aren't elements.
- if (cur_key.get_tag() != static_cast(SlotTag::Element)) {
- // Assert to catch errors of queueing other resource types for update.
- // This isn't an actual error, so there's no issue with continuing in release builds.
- assert(false);
- continue;
- }
-
- // Get the resource being updaten from the context.
- std::unique_ptr