Merge pull request #2418 from encounter/mod-browser

In-Game Mod Browser
This commit is contained in:
TakaRikka
2026-09-10 16:51:08 -07:00
committed by GitHub
118 changed files with 9591 additions and 2236 deletions
+18 -3
View File
@@ -180,8 +180,15 @@ FetchContent_Declare(miniz
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
EXCLUDE_FROM_ALL
)
message(STATUS "dusklight: Fetching PicoSHA2")
FetchContent_Declare(picosha2
URL https://github.com/okdshin/PicoSHA2/archive/refs/tags/v1.0.1.tar.gz
URL_HASH SHA256=9983136544234e573fe07cc1a22fdf978ad7979043e7be2e9082f6d4991ff8a8
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
EXCLUDE_FROM_ALL
)
set(_fetch_content_deps miniz)
set(_fetch_content_deps miniz picosha2)
if (DUSK_HAS_FUNCHOOK)
message(STATUS "dusklight: Fetching funchook")
# cmake/PatchFunchook.cmake patches funchook's cmake/capstone.cmake.in to inject a
@@ -216,6 +223,14 @@ if (DUSK_HAS_FUNCHOOK)
endif ()
FetchContent_MakeAvailable(${_fetch_content_deps})
if (DUSK_HAS_FUNCHOOK AND APPLE)
target_sources(funchook-static PRIVATE src/dusk/mods/loader/code_patch_macos.cpp)
target_include_directories(funchook-static PRIVATE src/dusk/mods/loader)
set_source_files_properties(src/dusk/mods/loader/code_patch_macos.cpp
TARGET_DIRECTORY funchook-static PROPERTIES
COMPILE_OPTIONS "-O2;-fno-sanitize=all;-fno-stack-protector")
endif ()
# Use signed char on ARM to match the original game (and x86)
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _arch)
if(_arch MATCHES "^(arm|aarch64)" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
@@ -241,8 +256,8 @@ include(cmake/GameABIConfig.cmake)
find_package(Threads REQUIRED)
set(GAME_COMPILE_DEFS DUSK_BUILDING_GAME=1)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd aurora::thp
aurora::card borealis::cli borealis::crash borealis::data borealis::disc borealis::discord borealis::file_select borealis::io borealis::log borealis::net borealis::presentation borealis::sentry borealis::update borealis::ws freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads zstd::libzstd dusklight_game_headers)
aurora::card borealis::http borealis::cli borealis::crash borealis::data borealis::disc borealis::discord borealis::file_select borealis::io borealis::log borealis::net borealis::presentation borealis::sentry borealis::update borealis::ws freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads zstd::libzstd dusklight_game_headers picosha2 PNG::PNG)
if (DUSK_HAS_FUNCHOOK)
list(APPEND GAME_LIBS funchook-static)
endif ()
+49 -53
View File
@@ -2,59 +2,55 @@ file(READ "${SOURCE_DIR}/cmake/capstone.cmake.in" _content)
# Insert PATCH_COMMAND before CONFIGURE_COMMAND in the ExternalProject_Add.
# Bracket args prevent cmake from substituting ${...} while writing this file.
string(REPLACE
" CONFIGURE_COMMAND \"\""
[=[ PATCH_COMMAND "${CMAKE_COMMAND}" -DDIR=${CMAKE_CURRENT_BINARY_DIR}/capstone-src -P "${CAPSTONE_FIX_SCRIPT}"
if (NOT _content MATCHES "CAPSTONE_FIX_SCRIPT")
string(REPLACE
" CONFIGURE_COMMAND \"\""
[=[ PATCH_COMMAND "${CMAKE_COMMAND}" -DDIR=${CMAKE_CURRENT_BINARY_DIR}/capstone-src -P "${CAPSTONE_FIX_SCRIPT}"
CONFIGURE_COMMAND ""]=]
_content "${_content}")
file(WRITE "${SOURCE_DIR}/cmake/capstone.cmake.in" "${_content}")
file(READ "${SOURCE_DIR}/src/funchook_unix.c" _unix_content)
# macOS rejects the POSIX mprotect RWX/RW transition for executable image pages on arm64.
# Use Mach VM_PROT_COPY for the short patch window, then restore RX permissions.
if (NOT _unix_content MATCHES "VM_PROT_READ \\| VM_PROT_WRITE \\| VM_PROT_COPY")
string(REPLACE
[=[ rv = mprotect(mstate->addr, mstate->size, prot);]=]
[=[#ifdef __APPLE__
kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)mstate->addr,
(vm_size_t)mstate->size, FALSE,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
if (kr == KERN_SUCCESS) {
funchook_log(funchook, " unprotect memory %p (size=%"PRIuPTR", prot=read,write,copy) <- %p (size=%"PRIuPTR")\n",
mstate->addr, mstate->size, start, len);
return 0;
}
funchook_set_error_message(funchook, "Failed to unprotect memory %p (size=%"PRIuPTR", prot=read,write,copy) <- %p (size=%"PRIuPTR", error=%s)",
mstate->addr, mstate->size, start, len,
mach_error_string(kr));
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
#endif
rv = mprotect(mstate->addr, mstate->size, prot);]=]
_unix_content "${_unix_content}")
string(REPLACE
[=[ char errbuf[128];
int rv = mprotect(mstate->addr, mstate->size, PROT_READ | PROT_EXEC);]=]
[=[ char errbuf[128];
#ifdef __APPLE__
kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)mstate->addr,
(vm_size_t)mstate->size, FALSE,
VM_PROT_READ | VM_PROT_EXECUTE);
if (kr == KERN_SUCCESS) {
funchook_log(funchook, " protect memory %p (size=%"PRIuPTR", prot=read,exec)\n",
mstate->addr, mstate->size);
return 0;
}
funchook_set_error_message(funchook, "Failed to protect memory %p (size=%"PRIuPTR", prot=read,exec, error=%s)",
mstate->addr, mstate->size,
mach_error_string(kr));
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
#endif
int rv = mprotect(mstate->addr, mstate->size, PROT_READ | PROT_EXEC);]=]
_unix_content "${_unix_content}")
_content "${_content}")
file(WRITE "${SOURCE_DIR}/cmake/capstone.cmake.in" "${_content}")
endif ()
file(WRITE "${SOURCE_DIR}/src/funchook_unix.c" "${_unix_content}")
file(READ "${SOURCE_DIR}/src/funchook.c" _content)
if (NOT _content MATCHES "commit_code_patch")
string(REPLACE "#include \"funchook_internal.h\""
"#include \"funchook_internal.h\"\n#ifdef __APPLE__\n#include \"code_patch_macos.hpp\"\n#endif"
_content "${_content}")
foreach(_operation install uninstall)
if (_operation STREQUAL "install")
set(_expected old_code)
set(_replacement new_code)
else ()
set(_expected new_code)
set(_replacement old_code)
endif ()
set(_original " mem_state_t mstate;
int rv = funchook_unprotect_begin(funchook, &mstate, entry->target_func, JUMP32_BYTE_SIZE);
if (rv != 0) {
return rv;
}
memcpy(entry->target_func, entry->${_replacement}, JUMP32_BYTE_SIZE);
rv = funchook_unprotect_end(funchook, &mstate);
if (rv != 0) {
return rv;
}
flush_instruction_cache(entry->target_func, JUMP32_BYTE_SIZE);")
string(FIND "${_content}" "${_original}" _position)
if (_position EQUAL -1)
message(FATAL_ERROR "Funchook ${_operation} patch site changed")
endif ()
string(REPLACE "${_original}" "#ifdef __APPLE__
int rv = commit_code_patch(entry->target_func, entry->${_expected},
entry->${_replacement}, JUMP32_BYTE_SIZE);
if (rv != 0) {
funchook_set_error_message(funchook, \"Code patch commit failed (Mach error %d)\", rv);
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
}
#else
${_original}
#endif" _content "${_content}")
endforeach ()
file(WRITE "${SOURCE_DIR}/src/funchook.c" "${_content}")
endif ()
+31
View File
@@ -1422,6 +1422,8 @@ set(DUSK_FILES
src/dusk/achievements.cpp
src/dusk/action_bindings.cpp
src/dusk/action_bindings.h
src/dusk/archive.cpp
src/dusk/archive.hpp
src/dusk/asserts.cpp
src/dusk/autosave.cpp
src/dusk/config.cpp
@@ -1435,6 +1437,7 @@ set(DUSK_FILES
src/dusk/commands.cpp
src/dusk/commands.hpp
src/dusk/game_clock.cpp
src/dusk/hash.hpp
src/dusk/game_mode.cpp
src/dusk/gamepad_color.cpp
src/dusk/globals.cpp
@@ -1481,10 +1484,20 @@ set(DUSK_FILES
src/dusk/mods/loader/depgraph.hpp
src/dusk/mods/loader/loader.cpp
src/dusk/mods/loader/loader.hpp
src/dusk/mods/loader/manifest.cpp
src/dusk/mods/loader/manifest.hpp
src/dusk/mods/loader/natives.cpp
src/dusk/mods/loader/natives.hpp
src/dusk/mods/loader/packages.cpp
src/dusk/mods/loader/packages.hpp
src/dusk/mods/loader/native_module.cpp
src/dusk/mods/loader/native_module.hpp
src/dusk/mods/loader/prepatch.cpp
src/dusk/mods/loader/prepatch.hpp
src/dusk/mods/catalog.cpp
src/dusk/mods/catalog.hpp
src/dusk/mods/queue.cpp
src/dusk/mods/queue.hpp
src/dusk/mods/item.hpp
src/dusk/mods/item_actor.cpp
src/dusk/mods/item_checks.cpp
@@ -1551,6 +1564,8 @@ set(DUSK_FILES
src/dusk/ui/controls.hpp
src/dusk/ui/document.cpp
src/dusk/ui/document.hpp
src/dusk/ui/drop_install_modal.cpp
src/dusk/ui/drop_install_modal.hpp
src/dusk/ui/editor.cpp
src/dusk/ui/editor.hpp
src/dusk/ui/event.cpp
@@ -1571,8 +1586,18 @@ set(DUSK_FILES
src/dusk/ui/list.hpp
src/dusk/ui/menu_bar.cpp
src/dusk/ui/menu_bar.hpp
src/dusk/ui/mod_browser.cpp
src/dusk/ui/mod_browser.hpp
src/dusk/ui/queue_window.cpp
src/dusk/ui/queue_window.hpp
src/dusk/ui/package_row.cpp
src/dusk/ui/package_row.hpp
src/dusk/ui/mod_texture_provider.cpp
src/dusk/ui/mod_texture_provider.hpp
src/dusk/ui/remote_texture_provider.cpp
src/dusk/ui/remote_texture_provider.hpp
src/dusk/ui/runtime_image.cpp
src/dusk/ui/runtime_image.hpp
src/dusk/ui/mod_window.cpp
src/dusk/ui/mod_window.hpp
src/dusk/ui/modal.cpp
@@ -1582,6 +1607,12 @@ set(DUSK_FILES
src/dusk/ui/nav_types.hpp
src/dusk/ui/nav_group.cpp
src/dusk/ui/nav_group.hpp
src/dusk/ui/context_menu.cpp
src/dusk/ui/context_menu.hpp
src/dusk/ui/icon_button.cpp
src/dusk/ui/icon_button.hpp
src/dusk/ui/tooltip.cpp
src/dusk/ui/tooltip.hpp
src/dusk/ui/number_button.cpp
src/dusk/ui/number_button.hpp
src/dusk/ui/overlay.cpp
+16 -18
View File
@@ -1,8 +1,6 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
--console-command-color: #FFD966;
display: block;
width: 100%;
height: 100%;
@@ -19,11 +17,11 @@ console {
width: 50%;
display: flex;
flex-direction: column;
background-color: rgba(0, 0, 0, 60%);
background-color: rgba(var(--color-black-rgb), 60%);
pointer-events: auto;
font-family: "Noto Mono";
font-size: 14dp;
color: #FFFFFF;
font-family: var(--font-family-monospace);
font-size: var(--font-size-sm);
color: var(--color-white);
transition: background-color 0.8s linear-in-out;
}
@@ -31,7 +29,7 @@ output {
display: block;
overflow: hidden;
max-height: 480dp;
padding: 4dp 8dp;
padding: var(--space-xs) var(--space-sm);
line-height: 1.4em;
}
@@ -46,11 +44,11 @@ console:not([open]) {
}
console:not([open])[fading] {
background-color: rgba(0, 0, 0, 0%);
background-color: rgba(var(--color-black-rgb), 0%);
}
console[open] {
background-color: rgba(0, 0, 0, 60%);
background-color: rgba(var(--color-black-rgb), 60%);
transition: none;
}
@@ -75,19 +73,19 @@ output[open] line {
}
line.cmd {
color: #FFD966;
color: var(--console-command-color);
}
console input {
display: none;
width: 100%;
background-color: rgba(0, 0, 0, 40%);
background-color: rgba(var(--color-black-rgb), 40%);
border: 0dp;
border-top: 1dp rgba(255, 255, 255, 20%);
color: #FFFFFF;
font-family: "Noto Mono";
font-size: 14dp;
padding: 4dp 8dp;
border-top: 1dp rgba(var(--color-white-rgb), 20%);
color: var(--color-white);
font-family: var(--font-family-monospace);
font-size: var(--font-size-sm);
padding: var(--space-xs) var(--space-sm);
}
console[open] input {
+38 -36
View File
@@ -2,19 +2,20 @@ window.logs content {
flex-flow: column;
}
window.logs .log-toolbar {
window.logs log-toolbar {
display: flex;
flex-flow: row;
flex: 0 0 64dp;
height: 64dp;
flex: 0 0 var(--toolbar-height);
height: var(--toolbar-height);
align-items: center;
gap: 8dp;
gap: var(--space-sm);
padding-right: 72dp;
background-color: rgba(217, 217, 217, 10%);
border-bottom: 2dp #92875B;
font-family: "Fira Sans Condensed";
background-color: rgba(var(--color-neutral-rgb), 10%);
border-bottom-width: 2dp;
border-bottom-color: var(--color-border);
font-family: var(--font-family-heading);
font-weight: bold;
font-size: 18dp;
font-size: var(--font-size-xl);
}
window.logs > close {
@@ -22,76 +23,77 @@ window.logs > close {
right: 8dp;
}
window.logs .log-title {
window.logs log-title {
align-self: stretch;
flex: 0 0 auto;
padding: 0 24dp;
line-height: 64dp;
padding: 0 var(--space-xl);
line-height: var(--toolbar-height);
text-transform: uppercase;
border-bottom: 4dp #C2A42D;
border-bottom-width: 4dp;
border-bottom-color: var(--color-accent);
font-effect: glow(0dp 4dp 0dp 4dp black);
}
window.logs .log-title-mod {
window.logs log-title-mod {
flex: 0 1 auto;
min-width: 0;
white-space: nowrap;
overflow: hidden;
font-family: "Fira Sans";
font-family: var(--font-family-body);
font-weight: normal;
font-size: 15dp;
color: rgba(224, 219, 200, 55%);
font-size: var(--font-size-base);
color: rgba(var(--color-text-rgb), 55%);
}
.log-toolbar-spacer {
log-toolbar-spacer {
flex: 1 1 0;
}
.log-toolbar button {
log-toolbar button {
flex: 0 0 auto;
font-family: "Fira Sans";
font-family: var(--font-family-body);
font-weight: normal;
font-size: 15dp;
padding: 5dp 12dp;
font-size: var(--font-size-base);
padding: 5dp var(--space-md);
}
window.logs content pane.log-view {
flex: 1 1 0;
padding: 12dp 16dp;
padding: var(--space-md) var(--space-lg);
padding-bottom: 0dp;
gap: 0dp;
}
.log-lines {
log-lines {
display: block;
}
.log-line {
log-line {
display: block;
font-family: "Noto Mono";
font-size: 13dp;
font-family: var(--font-family-monospace);
font-size: var(--font-size-xs);
line-height: 1.5;
word-break: break-word;
white-space: pre-wrap;
}
.log-line .log-time {
color: rgba(224, 219, 200, 45%);
log-line log-time {
color: rgba(var(--color-text-rgb), 45%);
}
.log-line .log-mod {
color: rgba(194, 164, 45, 80%);
log-line log-mod {
color: rgba(var(--color-accent-rgb), 80%);
}
.log-line.lvl-trace,
.log-line.lvl-debug {
log-line.lvl-trace,
log-line.lvl-debug {
opacity: 0.55;
}
.log-line.lvl-warn .log-msg {
color: #ffa826;
log-line.lvl-warn log-msg {
color: var(--color-warning);
}
.log-line.lvl-error .log-msg {
color: #cc4444;
log-line.lvl-error log-msg {
color: var(--color-error);
}
File diff suppressed because it is too large Load Diff
+137 -77
View File
@@ -1,8 +1,8 @@
window.mods content pane.mod-list {
flex: 0 0 360dp;
padding: 16dp;
padding: var(--space-lg);
padding-bottom: 0dp;
gap: 4dp;
gap: var(--space-xs);
}
@media (max-height: 640dp) {
@@ -12,29 +12,66 @@ window.mods content pane.mod-list {
}
window.mods content pane.mod-detail {
gap: 12dp;
gap: var(--space-md);
}
.mod-info-row {
mod-entry.browser,
mod-entry.installs {
min-height: 76dp;
}
mod-entry.browser mod-icon {
color: var(--color-accent);
decorator: text("&#xe2c0;" center center);
}
mod-entry.installs mod-icon {
color: var(--color-accent);
decorator: text("&#xe2c4;" center center);
}
mod-entry.installs {
background-color: rgba(var(--color-control-rgb), 20%);
box-shadow: rgba(var(--color-border-rgb), 25%) 0 0 0 1dp;
}
mod-entry.installs:hover,
mod-entry.installs:focus-visible {
background-color: rgba(var(--color-interactive-rgb), 12%);
box-shadow: var(--color-accent) 0 0 0 2dp;
}
mod-entry.installs progress {
height: 6dp;
margin: var(--space-xs) 0 0 0;
}
mod-list-separator {
display: block;
height: 1dp;
margin: var(--space-sm) 10dp;
background-color: rgba(var(--color-border-rgb), 30%);
}
mod-info-row {
display: flex;
align-items: center;
gap: 12dp;
padding: 4dp 0;
gap: var(--space-md);
padding: var(--space-xs) 0;
}
.mod-info-label {
font-family: "Fira Sans Condensed";
font-weight: bold;
mod-info-row > b {
font-family: var(--font-family-heading);
opacity: 0.55;
flex: 0 0 auto;
}
.mod-info-value {
mod-info-row > span {
flex: 1 1 0;
}
.mod-path {
font-size: 14dp;
font-size: var(--font-size-sm);
word-break: break-all;
opacity: 0.7;
}
@@ -42,106 +79,113 @@ window.mods content pane.mod-detail {
mod-entry {
display: flex;
flex-flow: row;
gap: 12dp;
gap: var(--space-md);
padding: 10dp;
border-radius: 10dp;
decorator: vertical-gradient(#c2a42d00 #c2a42d00);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 0%) rgba(var(--color-accent-rgb), 0%));
transition: decorator 0.1s linear-in-out;
cursor: pointer;
focus: auto;
}
mod-entry.current {
box-shadow: rgba(146, 135, 91, 40%) 0 0 0 1dp;
box-shadow: rgba(var(--color-border-rgb), 40%) 0 0 0 1dp;
}
mod-entry:hover,
mod-entry:focus-visible {
decorator: vertical-gradient(#c2a42d00 #c2a42d26);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 0) rgba(var(--color-accent-rgb), 38));
}
mod-entry:selected {
decorator: vertical-gradient(#c2a42d10 #c2a42d40);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 16) rgba(var(--color-accent-rgb), 64));
}
mod-entry .mod-icon {
mod-icon {
display: block;
flex: 0 0 auto;
width: 56dp;
height: 56dp;
border-radius: 8dp;
}
mod-entry icon.mod-icon {
border-radius: var(--radius-panel);
font-family: var(--font-family-icons);
font-size: 36dp;
background-color: rgba(17, 16, 10, 20%);
color: rgba(224, 219, 200, 45%);
background-color: rgba(var(--color-control-rgb), 20%);
color: rgba(var(--color-text-rgb), 45%);
decorator: text("&#xe87b;" center center);
overflow: hidden;
}
mod-entry .mod-entry-info {
mod-icon img {
display: block;
width: 100%;
height: 100%;
border-radius: var(--radius-panel);
}
mod-info {
display: flex;
flex-flow: column;
flex: 1 1 0;
min-width: 0;
gap: 2dp;
gap: var(--space-2xs);
}
mod-entry .mod-entry-name {
mod-info header {
display: flex;
flex-flow: row;
align-items: baseline;
gap: 6dp;
}
mod-entry .mod-entry-name-text {
mod-info header b {
flex: 0 1 auto;
min-width: 0;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
}
mod-entry .mod-entry-version {
mod-info header small {
flex: 0 0 auto;
font-size: 13dp;
color: rgba(224, 219, 200, 50%);
font-size: var(--font-size-xs);
color: rgba(var(--color-text-rgb), 50%);
}
mod-entry .mod-entry-status.active {
color: #44cc55;
mod-status.active {
color: var(--color-success);
}
mod-entry .mod-entry-status.failed {
color: #cc4444;
mod-status.failed {
color: var(--color-error);
}
mod-entry .mod-entry-network {
mod-network {
margin-left: 6dp;
padding: 1dp 5dp;
border-radius: 5dp;
background-color: rgba(67, 151, 219, 20%);
color: #6fb7ef;
background-color: rgba(var(--color-info-rgb), 20%);
color: var(--color-info);
}
mod-entry .mod-entry-desc {
font-size: 14dp;
mod-info > p {
margin: 0;
font-size: var(--font-size-sm);
line-height: 1.3;
color: rgba(224, 219, 200, 65%);
color: rgba(var(--color-text-rgb), 65%);
max-height: 2.6em;
overflow: hidden;
white-space: pre-wrap;
}
mod-entry .mod-entry-sub {
font-size: 13dp;
color: rgba(224, 219, 200, 50%);
mod-info > small {
font-size: var(--font-size-xs);
color: rgba(var(--color-text-rgb), 50%);
}
mod-entry.inactive .mod-icon {
mod-entry.inactive mod-icon {
filter: grayscale(1);
}
mod-entry.inactive .mod-entry-info {
mod-entry.inactive mod-info {
opacity: 0.5;
}
@@ -155,20 +199,37 @@ mod-header.has-banner {
margin: -24dp -24dp 0dp -24dp;
}
mod-header .mod-actions {
mod-header-image {
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
mask-image: linear-gradient(180deg, #fff 40%, transparent);
filter: grayscale(0);
}
mod-header.inactive mod-header-image {
filter: grayscale(1);
}
mod-actions {
position: absolute;
top: 24dp;
left: 24dp;
display: flex;
flex-flow: row;
gap: 8dp;
gap: var(--space-sm);
}
mod-header .mod-actions button {
font-size: 16dp;
padding: 6dp 14dp;
background-color: rgba(21, 22, 16, 80%);
box-shadow: rgba(146, 135, 91, 60%) 0 0 0 1dp;
mod-actions button {
--button-background: rgba(var(--color-surface-rgb), 80%);
--button-background-hover: rgba(var(--color-control-rgb), 90%);
--button-background-selected: rgba(var(--color-control-rgb), 90%);
--button-background-active: rgba(var(--color-surface-rgb), 90%);
box-shadow: rgba(var(--color-border-rgb), 60%) 0 0 0 1dp;
}
mod-header.no-banner {
@@ -177,56 +238,55 @@ mod-header.no-banner {
align-items: center;
}
mod-header.no-banner .mod-actions {
mod-header.no-banner mod-actions {
position: static;
}
window.mods .mod-title {
mod-title {
display: block;
font-size: 28dp;
font-size: var(--font-size-5xl);
font-weight: bold;
}
window.mods .mod-title .mod-title-version {
mod-title small {
font-weight: normal;
font-size: 16dp;
color: rgba(224, 219, 200, 55%);
font-size: var(--font-size-md);
color: rgba(var(--color-text-rgb), 55%);
}
window.mods .mod-author {
mod-author {
display: block;
font-size: 15dp;
color: rgba(224, 219, 200, 55%);
font-size: var(--font-size-base);
color: rgba(var(--color-text-rgb), 55%);
}
window.mods .mod-restart-note {
font-size: 15dp;
color: #ffa826;
mod-restart-note {
font-size: var(--font-size-base);
color: var(--color-warning);
opacity: 0.85;
}
window.mods .mod-description {
mod-description {
line-height: 1.5;
}
.status-badge {
font-size: 14dp;
status-badge {
font-size: var(--font-size-sm);
opacity: 0.7;
}
.status-badge.active,
.mod-info-label.active {
color: #44cc55;
status-badge.active,
mod-info-row > b.active {
color: var(--color-success);
opacity: 1;
}
.status-badge.failed,
.mod-info-label.failed {
color: #cc4444;
status-badge.failed,
mod-info-row > b.failed {
color: var(--color-error);
opacity: 1;
}
.status-badge.network {
color: #6fb7ef;
status-badge.network {
color: var(--color-info);
opacity: 1;
}
+92 -54
View File
@@ -8,10 +8,10 @@ body {
height: 100%;
margin: 0;
padding: 0;
font-family: "Fira Sans";
font-family: var(--font-family-body);
font-weight: normal;
font-size: 20dp;
color: #E0DBC8;
font-size: var(--font-size-2xl);
color: var(--color-text);
display: flex;
flex-direction: column;
justify-content: flex-end;
@@ -24,16 +24,22 @@ fps,
pipeline-progress,
toast {
position: absolute;
border: 1dp #92875B;
background-color: rgba(21, 22, 16, 80%);
border-width: 1dp;
background-color: rgba(var(--color-surface-rgb), 80%);
}
fps,
pipeline-progress {
border-color: var(--color-border);
}
toast {
border-color: var(--toast-border-color);
top: 40dp;
right: 40dp;
display: flex;
flex-flow: column;
border-radius: 14dp;
border-radius: var(--radius-window);
overflow: hidden;
backdrop-filter: blur(5dp);
box-shadow: 0 0 15dp 3dp;
@@ -41,8 +47,8 @@ toast {
transform: scale(0.9);
transform-origin: center;
transition: filter transform 0.2s cubic-in-out;
padding: 18dp 24dp;
gap: 8dp;
padding: 18dp var(--space-xl);
gap: var(--space-sm);
}
toast[open] {
@@ -50,15 +56,6 @@ toast[open] {
transform: scale(1);
}
/*toast:hover {
cursor: pointer;
background-color: rgba(61, 59, 36, 80%);
}
toast:active {
background-color: rgba(45, 43, 26, 80%);
}*/
b {
font-weight: bold;
}
@@ -67,14 +64,14 @@ toast heading {
display: flex;
gap: 18dp;
align-items: center;
font-family: "Fira Sans Condensed";
font-size: 18dp;
font-family: var(--font-family-heading);
font-size: var(--font-size-xl);
font-weight: bold;
text-transform: uppercase;
color: #92875B;
color: var(--toast-heading-color);
}
toast heading > span {
toast heading > toast-title {
flex: 1 0 auto;
}
@@ -82,13 +79,13 @@ toast heading > row {
flex: 1 0 auto;
display: flex;
align-items: center;
gap: 4dp;
gap: var(--space-xs);
}
toast message {
display: flex;
flex-flow: column;
gap: 8dp;
gap: var(--space-sm);
}
toast message row {
@@ -99,6 +96,50 @@ toast message row.muted {
opacity: 0.5;
}
toast.mod-installed row {
align-items: center;
gap: var(--space-md);
}
mod-icon {
flex: 0 0 42dp;
width: 42dp;
height: 42dp;
overflow: hidden;
border-radius: var(--radius-panel);
background-color: rgba(var(--color-control-rgb), 45%);
color: rgba(var(--color-text-rgb), 45%);
font-family: var(--font-family-icons);
font-size: var(--font-size-4xl);
decorator: text("&#xe87b;" center center);
}
mod-icon img {
width: 100%;
height: 100%;
border-radius: var(--radius-panel);
}
mod-info {
display: flex;
flex-flow: column;
min-width: 0;
gap: var(--space-xs);
}
mod-name {
color: var(--color-white);
}
toast.mod-installed small {
font-size: var(--font-size-sm);
color: rgba(var(--color-text-rgb), 55%);
}
toast.mod-installed small.version {
margin-left: var(--space-sm);
}
progress {
height: 4dp;
position: absolute;
@@ -108,7 +149,7 @@ progress {
}
progress fill {
background-color: rgba(194, 164, 45, 80%);
background-color: rgba(var(--color-accent-rgb), 80%);
}
pipeline-progress {
@@ -119,8 +160,8 @@ pipeline-progress {
z-index: 100;
min-width: 260dp;
max-width: 90%;
padding: 10dp 16dp 12dp;
border-radius: 7dp;
padding: 10dp var(--space-lg) var(--space-md);
border-radius: var(--radius-control);
overflow: hidden;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
@@ -134,8 +175,8 @@ pipeline-progress[open] {
pipeline-status {
display: flex;
align-items: center;
gap: 8dp;
font-size: 18dp;
gap: var(--space-sm);
font-size: var(--font-size-xl);
font-weight: normal;
white-space: nowrap;
}
@@ -145,26 +186,16 @@ icon.pipeline-spinner {
height: 1.2em;
line-height: 1.2em;
font-size: 1.2em;
color: #C2A42D;
color: var(--color-accent);
text-align: center;
transform-origin: center;
animation: 1s linear infinite pipeline-spinner-spin;
}
toast.achievement {
border: 1dp #C2A42D;
}
toast.achievement heading {
color: #C2A42D;
}
toast.achievement,
toast.warning {
border: 1dp #C2A42D;
}
toast.warning heading {
color: #C2A42D;
--toast-border-color: var(--color-accent);
--toast-heading-color: var(--color-accent);
}
toast.controller-warning {
@@ -181,8 +212,8 @@ toast.controller-warning[open] {
transform: translateX(-50%) scale(1);
}
toast.controller-warning heading {
color: #C2A42D;
toast.controller-warning {
--toast-heading-color: var(--color-accent);
}
toast.menu-notification {
@@ -209,7 +240,7 @@ toast.menu-notification message row {
}
icon {
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
display: inline-block;
vertical-align: middle;
@@ -243,13 +274,20 @@ icon.warning {
decorator: text("&#xe002;" center center);
}
icon.download-done {
width: 1.2em;
height: 1.2em;
font-size: 1.2em;
decorator: text("&#xf091;" center center);
}
fps {
display: none;
z-index: 99;
font-size: 18dp;
font-size: var(--font-size-xl);
font-weight: bold;
padding: 9dp 12dp;
border-radius: 7dp;
padding: 9dp var(--space-md);
border-radius: var(--radius-control);
pointer-events: none;
white-space: nowrap;
}
@@ -260,12 +298,12 @@ speedrun-timer {
bottom: 0;
right: 0;
z-index: 99;
background-color: rgba(0, 0, 0, 65%);
padding: 2dp 4dp;
background-color: rgba(var(--color-black-rgb), 65%);
padding: var(--space-2xs) var(--space-xs);
pointer-events: none;
font-family: "Noto Mono";
font-size: 16dp;
color: #ffffff;
font-family: var(--font-family-monospace);
font-size: var(--font-size-md);
color: var(--color-white);
white-space: nowrap;
}
@@ -329,7 +367,7 @@ logo img {
left: 0;
width: 100%;
height: 100%;
filter: drop-shadow(#0008 0 0 14dp);
filter: drop-shadow(rgba(var(--color-black-rgb), 53.333333%) 0 0 14dp);
transform-origin: center;
}
+106 -40
View File
@@ -3,6 +3,8 @@
}
body {
--button-background: rgba(var(--color-control-rgb), 35%);
width: 100%;
height: 100%;
z-index: 10;
@@ -12,14 +14,15 @@ popover {
position: absolute;
display: flex;
flex-flow: column;
font-family: "Fira Sans";
font-size: 14dp;
color: #E0DBC8;
border-radius: 14dp;
border: 2dp #92875B;
background-color: rgba(21, 22, 16, 96%);
font-family: var(--font-family-body);
font-size: var(--font-size-sm);
color: var(--color-text);
border-radius: var(--radius-window);
border-width: 2dp;
border-color: var(--color-border);
background-color: rgba(var(--color-surface-rgb), 96%);
backdrop-filter: blur(5dp);
box-shadow: 0 6dp 24dp 2dp rgba(0, 0, 0, 55%);
box-shadow: 0 6dp 24dp 2dp rgba(var(--color-black-rgb), 55%);
filter: opacity(0);
transform: scale(0.95);
transform-origin: center;
@@ -43,8 +46,8 @@ color-sv {
position: relative;
width: 240dp;
height: 150dp;
border-radius: 8dp;
box-shadow: rgba(146, 135, 91, 50%) 0 0 0 1dp;
border-radius: var(--radius-panel);
box-shadow: rgba(var(--color-border-rgb), 50%) 0 0 0 1dp;
drag: drag;
focus: auto;
}
@@ -55,8 +58,8 @@ color-alpha {
position: relative;
width: 240dp;
height: 14dp;
border-radius: 7dp;
box-shadow: rgba(146, 135, 91, 50%) 0 0 0 1dp;
border-radius: var(--radius-control);
box-shadow: rgba(var(--color-border-rgb), 50%) 0 0 0 1dp;
drag: drag;
focus: auto;
}
@@ -64,13 +67,13 @@ color-alpha {
color-sv:focus-visible,
color-hue:focus-visible,
color-alpha:focus-visible {
box-shadow: #C2A42D 0 0 0 2dp;
box-shadow: var(--color-accent) 0 0 0 2dp;
}
color-sv.adjusting,
color-hue.adjusting,
color-alpha.adjusting {
box-shadow: #FFFFFF 0 0 0 3dp;
box-shadow: var(--color-white) 0 0 0 3dp;
}
color-hue {
@@ -82,20 +85,21 @@ color-cursor {
position: absolute;
width: 14dp;
height: 14dp;
border-radius: 7dp;
border: 2dp #ffffff;
box-shadow: 0 0 4dp 1dp rgba(0, 0, 0, 70%);
border-radius: var(--radius-control);
border-width: 2dp;
border-color: var(--color-white);
box-shadow: 0 0 4dp 1dp rgba(var(--color-black-rgb), 70%);
pointer-events: none;
}
color-heading {
display: block;
margin-top: 2dp;
font-family: "Fira Sans Condensed";
margin-top: var(--space-2xs);
font-family: var(--font-family-heading);
font-weight: bold;
font-size: 13dp;
font-size: var(--font-size-xs);
text-transform: uppercase;
color: rgba(224, 219, 200, 55%);
color: rgba(var(--color-text-rgb), 55%);
}
color-presets {
@@ -114,7 +118,7 @@ button.color-swatch-button {
width: 25dp;
height: 25dp;
padding: 0;
border-radius: 7dp;
border-radius: var(--radius-control);
}
color-chip {
@@ -123,62 +127,124 @@ color-chip {
width: 20dp;
height: 20dp;
border-radius: 5dp;
box-shadow: rgba(255, 255, 255, 45%) 0 0 0 1dp;
box-shadow: rgba(var(--color-white-rgb), 45%) 0 0 0 1dp;
}
button.color-swatch-button color-chip {
width: 25dp;
height: 25dp;
border-radius: 7dp;
border-radius: var(--radius-control);
}
color-chip.empty,
color-swatch.empty {
background-color: rgba(224, 219, 200, 12%);
decorator: linear-gradient(135deg, rgba(224, 219, 200, 0) 45%,
rgba(194, 164, 45, 70%) 48%, rgba(194, 164, 45, 70%) 52%,
rgba(224, 219, 200, 0) 55%);
background-color: rgba(var(--color-text-rgb), 12%);
decorator: linear-gradient(135deg, rgba(var(--color-text-rgb), 0) 45%,
rgba(var(--color-accent-rgb), 70%) 48%, rgba(var(--color-accent-rgb), 70%) 52%,
rgba(var(--color-text-rgb), 0) 55%);
}
color-footer {
display: flex;
align-items: center;
gap: 6dp;
padding-top: 2dp;
padding-top: var(--space-2xs);
}
button {
background-color: rgba(17, 16, 10, 35%);
padding: 4dp 8dp;
border-radius: 8dp;
box-shadow: rgba(146, 135, 91, 30%) 0 0 0 1dp;
color: #E0DBC8;
background-color: var(--button-background);
padding: var(--space-xs) var(--space-sm);
border-radius: var(--radius-panel);
box-shadow: rgba(var(--color-border-rgb), 30%) 0 0 0 1dp;
color: var(--button-color);
cursor: pointer;
focus: auto;
}
button:hover,
button:focus-visible {
background-color: rgba(204, 184, 119, 20%);
box-shadow: #C2A42D 0 0 0 2dp;
background-color: var(--button-background-hover);
box-shadow: var(--color-accent) 0 0 0 2dp;
}
button:active {
background-color: rgba(204, 184, 119, 40%);
background-color: var(--button-background-active);
}
color-value {
display: block;
flex: 1 1 auto;
text-align: right;
font-family: "Noto Mono";
font-size: 12dp;
color: #FFFFFF;
font-family: var(--font-family-monospace);
font-size: var(--font-size-2xs);
color: var(--color-white);
cursor: pointer;
focus: auto;
}
color-value:hover,
color-value:focus-visible {
color: #C2A42D;
color: var(--color-accent);
}
popover.context-menu {
min-width: 200dp;
max-width: 90%;
max-height: 90%;
overflow-y: auto;
padding: 6dp;
gap: 2dp;
transform-origin: left top;
}
.context-menu button {
display: flex;
align-items: center;
gap: 10dp;
padding: 8dp 12dp;
flex: 0 0 auto;
white-space: nowrap;
--button-background: transparent;
background-color: var(--button-background);
box-shadow: none;
transition: background-color 0.1s linear-in-out;
}
.context-menu button:not(:disabled):hover,
.context-menu button:not(:disabled):focus-visible {
background-color: var(--button-background-hover);
box-shadow: none;
}
.context-menu button:not(:disabled):active {
background-color: var(--button-background-active);
}
.context-menu button:disabled {
background-color: transparent;
box-shadow: none;
opacity: 0.4;
cursor: unavailable;
}
.context-menu button.destructive {
color: var(--color-error);
}
.context-menu icon {
display: block;
flex: 0 0 1em;
width: 1em;
height: 1em;
font-family: var(--font-family-icons);
font-weight: normal;
line-height: 1;
}
menu-separator {
display: block;
flex: 0 0 1dp;
height: 1dp;
margin: 4dp 6dp;
background-color: var(--color-border);
}
+9 -8
View File
@@ -8,10 +8,10 @@ body {
height: 100%;
margin: 0;
padding: 0;
font-family: "Fira Sans Condensed";
font-family: var(--font-family-heading);
font-weight: bold;
font-size: 18dp;
color: #E0DBC8;
font-size: var(--font-size-xl);
color: var(--color-text);
}
button {
@@ -23,11 +23,12 @@ popup {
width: 100%;
display: flex;
align-items: stretch;
height: 64dp;
background-color: rgba(21, 22, 16, 80%);
border-bottom: 2dp #92875B;
height: var(--toolbar-height);
background-color: rgba(var(--color-surface-rgb), 80%);
border-bottom-width: 2dp;
border-bottom-color: var(--color-border);
backdrop-filter: blur(5dp);
transform: translateY(-64dp);
transform: translateY(var(--toolbar-hidden-offset));
transition: transform 0.2s cubic-in-out;
}
@@ -41,5 +42,5 @@ popup tab-bar {
popup tab-bar tab {
opacity: 0.35;
color: #E0DBC8;
color: var(--color-text);
}
+91 -90
View File
@@ -1,32 +1,40 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
--color-prelaunch-accent: #FEE685;
--color-prelaunch-muted: #A6A09B;
--color-disc-error: #FFC9C9;
--color-disc-mismatch: #FFD6A7;
--color-ready: #D8F999;
--menu-button-decorator: horizontal-gradient(rgba(var(--color-black-rgb), 0%) rgba(var(--color-black-rgb), 0%));
--menu-button-decorator-hover: horizontal-gradient(#FEE685FF #FEE68500);
width: 100%;
height: 100%;
font-family: "Fira Sans";
font-family: var(--font-family-body);
font-weight: normal;
font-size: 20dp;
color: #FFFFFF;
font-size: var(--font-size-2xl);
color: var(--color-white);
filter: opacity(0);
transition: filter 1s 0.2s linear-in-out;
z-index: -1;
}
.gradient {
body.mirrored {
--menu-button-decorator-hover: horizontal-gradient(#FEE68500 #FEE685FF);
}
prelaunch-gradient {
position: absolute;
width: 100%;
height: 100%;
/* The color gradient from the Figma bands really badly. A fully black gradient does as well, but not as badly. */
decorator: horizontal-gradient(#000000FF #00000000);
decorator: horizontal-gradient(rgba(var(--color-black-rgb), 100%) rgba(var(--color-black-rgb), 0%));
}
body.mirrored .gradient {
decorator: horizontal-gradient(#00000000 #000000FF);
body.mirrored prelaunch-gradient {
decorator: horizontal-gradient(rgba(var(--color-black-rgb), 0%) rgba(var(--color-black-rgb), 100%));
}
.background {
prelaunch-background {
position: absolute;
width: 100%;
height: 100%;
@@ -39,11 +47,11 @@ body[open] {
filter: opacity(1);
}
body[open] .background {
body[open] prelaunch-background {
opacity: 1;
}
body.disc-ready .background {
body.disc-ready prelaunch-background {
opacity: 0;
}
@@ -84,7 +92,7 @@ hero {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 4dp;
gap: var(--space-xs);
}
body.mirrored hero {
@@ -96,8 +104,8 @@ hero img {
}
eyebrow {
font-family: "Alegreya SC";
font-size: 32dp;
font-family: var(--font-family-display);
font-size: var(--font-size-6xl);
}
@media (min-width: 1216dp) {
@@ -107,36 +115,36 @@ eyebrow {
}
}
eyebrow span {
eyebrow studio-name {
font-weight: bold;
}
#menu-list {
menu-list {
display: flex;
flex-direction: column;
gap: 12dp;
gap: var(--space-md);
align-items: flex-start;
}
#menu-list button {
width: 428dp;
height: 54dp;
padding: 8dp 16dp;
border-radius: 8dp;
padding: var(--space-sm) var(--space-lg);
border-radius: var(--radius-panel);
text-align: left;
text-transform: uppercase;
font-family: "Fira Sans Condensed";
font-size: 32dp;
font-family: var(--font-family-heading);
font-size: var(--font-size-6xl);
font-weight: normal;
cursor: pointer;
/* Define a fully transparent gradient as the default state, otherwise a white flash occurs */
decorator: horizontal-gradient(#00000000 #00000000);
decorator: var(--menu-button-decorator);
}
#menu-list button:disabled {
opacity: 0.75;
cursor: default;
decorator: horizontal-gradient(#00000000 #00000000);
decorator: var(--menu-button-decorator);
}
#menu-list button.anim-done {
@@ -157,7 +165,7 @@ eyebrow span {
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 8dp;
border-radius: var(--radius-panel);
pointer-events: none;
z-index: 0;
}
@@ -169,7 +177,7 @@ eyebrow span {
left: 0;
width: 100%;
height: 100%;
padding: 8dp 16dp;
padding: var(--space-sm) var(--space-lg);
opacity: 0;
text-overflow: ellipsis;
white-space: nowrap;
@@ -189,8 +197,8 @@ eyebrow span {
height: 54dp;
align-items: center;
justify-content: center;
color: #FFFFFF;
font-family: "Material Symbols Rounded";
color: var(--color-white);
font-family: var(--font-family-icons);
font-weight: normal;
font-size: 30dp;
z-index: 1;
@@ -213,8 +221,8 @@ eyebrow span {
#menu-list button:hover,
#menu-list button:focus-visible {
color: black;
decorator: horizontal-gradient(#FEE685FF #FEE68500);
color: var(--color-black);
decorator: var(--menu-button-decorator-hover);
}
body.mirrored #menu-list {
@@ -225,11 +233,6 @@ body.mirrored #menu-list button {
text-align: right;
}
body.mirrored #menu-list button:hover,
body.mirrored #menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE68500 #FEE685FF);
}
disc-info {
position: absolute;
left: 96dp;
@@ -237,8 +240,8 @@ disc-info {
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 12dp;
font-size: 24dp;
gap: var(--space-md);
font-size: var(--font-size-4xl);
font-effect: glow(0dp 4dp 0dp 4dp black);
text-align: left;
}
@@ -256,9 +259,9 @@ version-info {
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 12dp;
gap: var(--space-md);
text-align: right;
font-size: 24dp;
font-size: var(--font-size-4xl);
font-effect: glow(0dp 4dp 0dp 4dp black);
text-align: right;
}
@@ -272,40 +275,40 @@ body.mirrored version-info {
#disc-status {
display: flex;
align-items: center;
gap: 8dp;
gap: var(--space-sm);
}
#disc-status[status=good] {
color: #D8F999;
color: var(--color-ready);
}
#disc-status[status=bad] {
color: #FFC9C9;
color: var(--color-disc-error);
}
#disc-status[status=verifying] {
color: #FFFFFF;
color: var(--color-white);
}
#disc-status[status=mismatch] {
color: #FFD6A7;
color: var(--color-disc-mismatch);
}
#disc-status[status=unknown] {
color: rgba(224, 219, 200, 65%);
color: rgba(var(--color-text-rgb), 65%);
}
#disc-status[status=pending] {
color: #FEE685;
color: var(--color-prelaunch-accent);
}
#disc-status icon {
display: none;
width: 24dp;
height: 24dp;
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
font-size: 24dp;
font-size: var(--font-size-4xl);
}
#disc-status[status] icon {
@@ -337,24 +340,24 @@ body.mirrored version-info {
}
#disc-version {
font-size: 20dp;
font-size: var(--font-size-2xl);
}
.update {
update-status {
display: none;
color: #A6A09B;
color: var(--color-prelaunch-muted);
align-items: center;
justify-content: flex-end;
gap: 8dp;
font-size: 20dp;
gap: var(--space-sm);
font-size: var(--font-size-2xl);
}
.update[state=checking],
.update[state=failed] {
update-status[state=checking],
update-status[state=failed] {
display: block;
}
.update[state=available] {
update-status[state=available] {
display: flex;
}
@@ -364,33 +367,33 @@ body.mirrored version-info {
padding: 0dp;
border-width: 0dp;
background-color: transparent;
color: #D8F999;
color: var(--color-ready);
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
decorator: horizontal-gradient(#00000000 #00000000);
decorator: var(--menu-button-decorator);
}
.update[state=available] #update-download {
update-status[state=available] #update-download {
display: flex;
align-items: center;
gap: 2dp;
gap: var(--space-2xs);
}
#update-download icon {
display: block;
width: 18dp;
height: 18dp;
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
decorator: text("&#xe5c8;" center center);
}
.detail {
color: #A6A09B;
disc-version {
color: var(--color-prelaunch-muted);
}
body.mirrored .update {
body.mirrored update-status {
justify-content: flex-start;
}
@@ -436,12 +439,20 @@ body.animate-in .intro-item {
/* Mobile layout */
@media (max-height: 640dp) {
.gradient {
decorator: horizontal-gradient(#00000000 #000000FF);
body {
--menu-button-decorator-hover: horizontal-gradient(#FEE68500 #FEE685FF);
}
body.mirrored .gradient {
decorator: horizontal-gradient(#000000FF #00000000);
body.mirrored {
--menu-button-decorator-hover: horizontal-gradient(#FEE685FF #FEE68500);
}
prelaunch-gradient {
decorator: horizontal-gradient(rgba(var(--color-black-rgb), 0%) rgba(var(--color-black-rgb), 100%));
}
body.mirrored prelaunch-gradient {
decorator: horizontal-gradient(rgba(var(--color-black-rgb), 100%) rgba(var(--color-black-rgb), 0%));
}
menu {
@@ -453,7 +464,7 @@ body.animate-in .intro-item {
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 16dp;
gap: var(--space-lg);
}
body.mirrored menu {
@@ -466,7 +477,7 @@ body.animate-in .intro-item {
flex: 1 1 0;
min-width: 0;
max-width: 48%;
margin-left: 32dp;
margin-left: var(--space-2xl);
}
body.mirrored hero {
@@ -490,11 +501,6 @@ body.animate-in .intro-item {
text-align: right;
}
#menu-list button:hover,
#menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE68500 #FEE685FF);
}
body.mirrored #menu-list {
align-items: flex-start;
}
@@ -503,11 +509,6 @@ body.animate-in .intro-item {
text-align: left;
}
body.mirrored #menu-list button:hover,
body.mirrored #menu-list button:focus-visible {
decorator: horizontal-gradient(#FEE685FF #FEE68500);
}
eyebrow {
display: none;
}
@@ -518,8 +519,8 @@ body.animate-in .intro-item {
bottom: 32dp;
top: auto;
text-align: right;
font-size: 16dp;
gap: 8dp;
font-size: var(--font-size-md);
gap: var(--space-sm);
}
#disc-status {
@@ -527,11 +528,11 @@ body.animate-in .intro-item {
}
#disc-status icon {
font-size: 20dp;
font-size: var(--font-size-2xl);
}
#disc-version {
font-size: 16dp;
font-size: var(--font-size-md);
}
version-info {
@@ -540,12 +541,12 @@ body.animate-in .intro-item {
bottom: auto;
top: 32dp;
text-align: right;
font-size: 16dp;
gap: 8dp;
font-size: var(--font-size-md);
gap: var(--space-sm);
}
.update {
font-size: 16dp;
update-status {
font-size: var(--font-size-md);
}
body.mirrored disc-info {
+17 -16
View File
@@ -18,17 +18,18 @@ tab-bar scrollbarhorizontal sliderbar {
tab-bar tab {
flex: 0 0 auto;
padding: 0 24dp;
line-height: 64dp;
padding: 0 var(--space-xl);
line-height: var(--toolbar-height);
white-space: nowrap;
decorator: vertical-gradient(#c2a42d00 #c2a42d00);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 0%) rgba(var(--color-accent-rgb), 0%));
transition: decorator 0.1s linear-in-out, opacity 0.1s linear-in-out;
cursor: pointer;
}
tab-bar tab:selected {
opacity: 1;
border-bottom: 4dp #C2A42D;
border-bottom-width: 4dp;
border-bottom-color: var(--color-accent);
font-effect: glow(0dp 4dp 0dp 4dp black);
}
@@ -36,17 +37,17 @@ tab-bar tab:focus-visible,
tab-bar tab:hover {
opacity: 1;
font-effect: glow(0dp 4dp 0dp 4dp black);
decorator: vertical-gradient(#c2a42d00 #c2a42d26);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 0) rgba(var(--color-accent-rgb), 38));
}
tab-bar tab:active {
decorator: vertical-gradient(#c2a42d10 #c2a42d40);
decorator: vertical-gradient(rgba(var(--color-accent-rgb), 16) rgba(var(--color-accent-rgb), 64));
}
tab-bar[closable] tab-end-spacer {
display: block;
flex: 0 0 64dp;
width: 64dp;
flex: 0 0 var(--toolbar-height);
width: var(--toolbar-height);
pointer-events: none;
}
@@ -56,13 +57,13 @@ window > close {
position: fixed;
top: 8dp;
right: 8dp;
z-index: 1;
z-index: 2;
width: 48dp;
height: 48dp;
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
font-size: 24dp;
color: rgba(224, 219, 200, 70%);
font-size: var(--font-size-4xl);
color: rgba(var(--color-text-rgb), 70%);
backdrop-filter: blur(2dp);
border-radius: 6dp;
decorator: text("&#xe5cd;" center center);
@@ -74,8 +75,8 @@ tab-bar[closable] close:hover,
tab-bar[closable] close:focus-visible,
window > close:hover,
window > close:focus-visible {
color: #fff;
background-color: rgba(194, 164, 45, 24%);
color: var(--color-white);
background-color: rgba(var(--color-accent-rgb), 24%);
}
window > close {
@@ -85,6 +86,6 @@ window > close {
tab-bar[closable] close:active,
window > close:active {
color: #fff;
background-color: rgba(194, 164, 45, 40%);
color: var(--color-white);
background-color: rgba(var(--color-accent-rgb), 40%);
}
+80
View File
@@ -0,0 +1,80 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
--font-family-body: Fira Sans;
--font-family-heading: Fira Sans Condensed;
--font-family-monospace: Noto Mono;
--font-family-icons: Material Symbols Rounded;
--font-family-display: Alegreya SC;
--font-size-3xs: 11dp;
--font-size-2xs: 12dp;
--font-size-xs: 13dp;
--font-size-sm: 14dp;
--font-size-base: 15dp;
--font-size-md: 16dp;
--font-size-lg: 17dp;
--font-size-xl: 18dp;
--font-size-2xl: 20dp;
--font-size-3xl: 22dp;
--font-size-4xl: 24dp;
--font-size-5xl: 28dp;
--font-size-6xl: 32dp;
--space-2xs: 2dp;
--space-xs: 4dp;
--space-sm: 8dp;
--space-md: 12dp;
--space-lg: 16dp;
--space-xl: 24dp;
--space-2xl: 32dp;
--radius-small: 4dp;
--radius-control: 7dp;
--radius-panel: 8dp;
--radius-window: 14dp;
--toolbar-height: 64dp;
--toolbar-hidden-offset: -64dp;
--color-text-rgb: 224, 219, 200;
--color-text: rgb(var(--color-text-rgb));
--color-accent-rgb: 194, 164, 45;
--color-accent: rgb(var(--color-accent-rgb));
--color-border-rgb: 146, 135, 91;
--color-border: rgb(var(--color-border-rgb));
--color-surface-rgb: 21, 22, 16;
--color-interactive-rgb: 204, 184, 119;
--color-control-rgb: 17, 16, 10;
--color-neutral-rgb: 217, 217, 217;
--color-neutral: rgb(var(--color-neutral-rgb));
--color-white-rgb: 255, 255, 255;
--color-white: rgb(var(--color-white-rgb));
--color-black-rgb: 0, 0, 0;
--color-black: rgb(var(--color-black-rgb));
--color-success-rgb: 68, 204, 85;
--color-success: rgb(var(--color-success-rgb));
--color-info-rgb: 111, 183, 239;
--color-info: rgb(var(--color-info-rgb));
--color-warning-rgb: 255, 168, 38;
--color-warning: rgb(var(--color-warning-rgb));
--color-error-rgb: 204, 68, 68;
--color-error: rgb(var(--color-error-rgb));
--color-progress-done: #44AA22;
--color-progress-ongoing: #2255BB;
--color-danger-border: #852221;
--color-danger-heading: #B3261E;
--button-color: var(--color-text);
--button-background: rgba(var(--color-control-rgb), 20%);
--button-background-hover: rgba(var(--color-interactive-rgb), 20%);
--button-background-selected: rgba(var(--color-interactive-rgb), 40%);
--button-background-active: rgba(var(--color-interactive-rgb), 40%);
--toast-border-color: var(--color-border);
--toast-heading-color: var(--color-border);
}
+64 -57
View File
@@ -1,16 +1,28 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
--color-oil-border: rgba(42, 32, 18, 82%);
--color-oil-background: rgba(18, 14, 10, 70%);
--color-oil-fill: rgb(255, 232, 74);
--color-button-a: rgba(34, 112, 123, 62%);
--color-button-b: rgba(161, 61, 66, 58%);
--color-button-x: rgba(83, 115, 151, 56%);
--color-button-y: rgba(113, 91, 150, 54%);
--color-stick-background: rgba(18, 20, 24, 35%);
--color-stick-knob: rgba(238, 236, 226, 55%);
--button-color: rgba(248, 244, 232, 90%);
--button-background: rgba(22, 24, 28, 48%);
--button-background-active: rgba(63, 78, 90, 68%);
--button-border-color: rgba(var(--color-white-rgb), 22%);
--button-border-color-active: rgba(var(--color-white-rgb), 48%);
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: "Fira Sans Condensed";
font-family: var(--font-family-heading);
font-weight: bold;
color: rgba(248, 244, 232, 90%);
color: var(--button-color);
z-index: 1;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
@@ -30,12 +42,11 @@ button {
justify-content: center;
decorator: none;
padding: 0;
border: 1dp rgba(255, 255, 255, 22%);
background-color: rgba(22, 24, 28, 48%);
color: rgba(248, 244, 232, 90%);
border-width: 1dp;
border-color: var(--button-border-color);
background-color: var(--button-background);
color: var(--button-color);
text-align: center;
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
transform-origin: center;
transition: background-color border-color filter transform 0.08s linear-in-out,
opacity 0.2s linear-in-out;
@@ -43,8 +54,8 @@ button {
button.pressed,
button.active {
background-color: rgba(63, 78, 90, 68%);
border-color: rgba(255, 255, 255, 48%);
background-color: var(--button-background-active);
border-color: var(--button-border-color-active);
filter: brightness(1.18);
}
@@ -68,9 +79,9 @@ button icon {
button icon glyph {
display: block;
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
font-size: 24dp;
font-size: var(--font-size-4xl);
line-height: 1;
}
@@ -92,9 +103,9 @@ button icon glyph {
position: absolute;
}
.trigger-l.active {
background-color: rgba(57, 116, 133, 74%);
border-color: rgba(128, 222, 234, 72%);
.trigger-l {
--button-background-active: rgba(57, 116, 133, 74%);
--button-border-color-active: rgba(128, 222, 234, 72%);
}
.trigger,
@@ -103,12 +114,14 @@ button icon glyph {
}
.trigger {
font-size: 22dp;
font-size: var(--font-size-3xl);
}
.button-z {
background-color: rgba(118, 79, 158, 58%);
border-color: rgba(203, 170, 255, 36%);
--button-background: rgba(118, 79, 158, 58%);
--button-background-active: rgba(139, 91, 187, 82%);
--button-border-color: rgba(203, 170, 255, 36%);
--button-border-color-active: rgba(220, 194, 255, 70%);
}
.midna-icon {
@@ -121,7 +134,7 @@ button icon glyph {
.button-z.has-icon span,
.face.has-item span {
position: absolute;
font-size: 13dp;
font-size: var(--font-size-xs);
line-height: 1;
}
@@ -130,20 +143,14 @@ button icon glyph {
bottom: 7dp;
}
.button-z.pressed {
background-color: rgba(139, 91, 187, 82%);
border-color: rgba(220, 194, 255, 70%);
}
action-bar {
position: absolute;
display: flex;
align-items: center;
border: 1dp rgba(255, 255, 255, 22%);
border-width: 1dp;
border-color: var(--button-border-color);
border-radius: 23dp;
background-color: rgba(22, 24, 28, 48%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
background-color: var(--button-background);
overflow: hidden;
opacity: 1;
transform-origin: center;
@@ -175,7 +182,7 @@ action-bar:hidden separator {
}
.utility.pressed {
background-color: rgba(63, 78, 90, 68%);
background-color: var(--button-background-active);
}
.utility.pressed,
@@ -185,7 +192,7 @@ action-bar:hidden separator {
.skip {
z-index: 1;
border-color: rgba(255, 255, 255, 36%);
border-color: rgba(var(--color-white-rgb), 36%);
}
separator {
@@ -193,7 +200,7 @@ separator {
flex: 0 0 1dp;
width: 1dp;
height: 24dp;
background-color: rgba(255, 255, 255, 18%);
background-color: rgba(var(--color-white-rgb), 18%);
opacity: 1;
transition: opacity 0.2s linear-in-out;
}
@@ -201,7 +208,7 @@ separator {
.face {
position: absolute;
border-radius: 29dp;
font-size: 24dp;
font-size: var(--font-size-4xl);
overflow: visible;
}
@@ -219,10 +226,10 @@ separator {
min-width: 17dp;
height: 15dp;
padding: 1dp 3dp;
border-radius: 7dp;
background-color: rgba(0, 0, 0, 52%);
color: rgba(255, 255, 255, 92%);
font-size: 12dp;
border-radius: var(--radius-control);
background-color: rgba(var(--color-black-rgb), 52%);
color: rgba(var(--color-white-rgb), 92%);
font-size: var(--font-size-2xs);
line-height: 13dp;
text-align: center;
}
@@ -233,11 +240,10 @@ separator {
bottom: -5dp;
width: 34dp;
height: 8dp;
padding: 2dp;
border: 1dp rgba(42, 32, 18, 82%);
border-radius: 4dp;
background-color: rgba(18, 14, 10, 70%);
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
padding: var(--space-2xs);
border: 1dp var(--color-oil-border);
border-radius: var(--radius-small);
background-color: var(--color-oil-background);
}
oil-fill {
@@ -245,31 +251,31 @@ oil-fill {
width: 0%;
height: 100%;
border-radius: 2dp;
background-color: rgb(255, 232, 74);
background-color: var(--color-oil-fill);
}
.face.has-item span {
right: 6dp;
bottom: 6dp;
color: rgba(255, 255, 255, 88%);
color: rgba(var(--color-white-rgb), 88%);
}
.face.a {
border-radius: 37dp;
font-size: 31dp;
background-color: rgba(34, 112, 123, 62%);
background-color: var(--color-button-a);
}
.face.b {
background-color: rgba(161, 61, 66, 58%);
background-color: var(--color-button-b);
}
.face.x {
background-color: rgba(83, 115, 151, 56%);
background-color: var(--color-button-x);
}
.face.y {
background-color: rgba(113, 91, 150, 54%);
background-color: var(--color-button-y);
}
button.control.docked-top,
@@ -306,10 +312,9 @@ touch-stick {
width: 124dp;
height: 124dp;
border-radius: 62dp;
background-color: rgba(18, 20, 24, 35%);
border: 1dp rgba(255, 255, 255, 20%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
background-color: var(--color-stick-background);
border-width: 1dp;
border-color: rgba(var(--color-white-rgb), 20%);
opacity: 0;
pointer-events: none;
transition: opacity 0.18s linear-in-out;
@@ -326,7 +331,8 @@ stick-ring {
width: 88dp;
height: 88dp;
border-radius: 44dp;
border: 1dp rgba(255, 255, 255, 18%);
border-width: 1dp;
border-color: rgba(var(--color-white-rgb), 18%);
}
stick-knob {
@@ -334,6 +340,7 @@ stick-knob {
width: 48dp;
height: 48dp;
border-radius: 24dp;
background-color: rgba(238, 236, 226, 55%);
border: 1dp rgba(255, 255, 255, 45%);
background-color: var(--color-stick-knob);
border-width: 1dp;
border-color: rgba(var(--color-white-rgb), 45%);
}
+31 -17
View File
@@ -1,5 +1,10 @@
body.touch-editor {
background-color: rgba(4, 6, 8, 34%);
--color-editor-backdrop: rgba(4, 6, 8, 34%);
--color-editor-handle: rgba(34, 37, 42, 86%);
--color-editor-accent-rgb: 255, 232, 128;
--color-editor-highlight-rgb: 255, 244, 190;
background-color: var(--color-editor-backdrop);
z-index: 8;
}
@@ -14,7 +19,7 @@ body.touch-editor .control:hover,
body.touch-editor action-bar:hover,
body.touch-editor .control.editor-selected,
body.touch-editor action-bar.editor-selected {
border-color: rgba(255, 232, 128, 80%);
border-color: rgba(var(--color-editor-accent-rgb), 80%);
filter: brightness(1.15);
}
@@ -27,8 +32,9 @@ selection-frame {
display: none;
position: absolute;
z-index: 20;
border: 2dp rgba(255, 232, 128, 88%);
background-color: rgba(255, 232, 128, 7%);
border-width: 2dp;
border-color: rgba(var(--color-editor-accent-rgb), 88%);
background-color: rgba(var(--color-editor-accent-rgb), 7%);
pointer-events: none;
}
@@ -41,9 +47,10 @@ resize-handle {
position: absolute;
width: 22dp;
height: 22dp;
border: 2dp rgba(255, 244, 190, 96%);
border-width: 2dp;
border-color: rgba(var(--color-editor-highlight-rgb), 96%);
border-radius: 11dp;
background-color: rgba(34, 37, 42, 86%);
background-color: var(--color-editor-handle);
pointer-events: auto;
}
@@ -90,6 +97,12 @@ resize-handle.corner.bottom {
}
editor-toolbar {
--button-background: rgba(17, 19, 24, 88%);
--button-background-hover: rgba(78, 85, 96, 92%);
--button-border-color: rgba(var(--color-white-rgb), 26%);
--button-border-color-hover: rgba(var(--color-editor-highlight-rgb), 92%);
--button-color: rgba(255, 250, 232, 94%);
display: flex;
position: absolute;
left: 24dp;
@@ -98,7 +111,7 @@ editor-toolbar {
z-index: 30;
height: 48dp;
margin-top: -24dp;
gap: 8dp;
gap: var(--space-sm);
justify-content: center;
pointer-events: auto;
}
@@ -108,12 +121,13 @@ editor-toolbar button.editor-command {
min-width: 96dp;
height: 48dp;
padding: 0 14dp;
border-radius: 8dp;
border: 1dp rgba(255, 255, 255, 26%);
background-color: rgba(17, 19, 24, 88%);
color: rgba(255, 250, 232, 94%);
font-family: "Fira Sans";
font-size: 18dp;
border-radius: var(--radius-panel);
border-width: 1dp;
border-color: var(--button-border-color);
background-color: var(--button-background);
color: var(--button-color);
font-family: var(--font-family-body);
font-size: var(--font-size-xl);
line-height: 48dp;
opacity: 1;
cursor: pointer;
@@ -127,12 +141,12 @@ editor-toolbar button.editor-command span {
}
editor-toolbar button.editor-command.primary {
border-color: rgba(255, 232, 128, 70%);
background-color: rgba(96, 82, 38, 90%);
--button-border-color: rgba(var(--color-editor-accent-rgb), 70%);
--button-background: rgba(96, 82, 38, 90%);
}
editor-toolbar button.editor-command:hover,
editor-toolbar button.editor-command:focus-visible {
border-color: rgba(255, 244, 190, 92%);
background-color: rgba(78, 85, 96, 92%);
border-color: var(--button-border-color-hover);
background-color: var(--button-background-hover);
}
+31 -34
View File
@@ -1,90 +1,87 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
overflow: visible;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: "Fira Sans Condensed";
font-size: 24dp;
color: #FFFFFF;
font-family: var(--font-family-heading);
font-size: var(--font-size-4xl);
color: var(--color-white);
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
}
.tuner-root {
tuner-root {
width: 100%;
min-height: 45%;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
decorator: vertical-gradient(#00000000 #151610F2);
decorator: vertical-gradient(rgba(var(--color-black-rgb), 0%) rgba(var(--color-surface-rgb), 242));
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
.tuner-root[open] {
tuner-root[open] {
filter: opacity(1);
}
.tuner {
graphics-tuner {
width: 100%;
max-width: 1216dp;
margin-left: auto;
margin-right: auto;
display: flex;
flex-direction: column;
gap: 24dp;
gap: var(--space-xl);
padding: 48dp 64dp;
}
@media (max-height: 800dp) {
.tuner-root {
tuner-root {
min-height: 38%;
}
.tuner {
gap: 16dp;
padding: 32dp 48dp;
graphics-tuner {
gap: var(--space-lg);
padding: var(--space-2xl) 48dp;
}
}
.header {
tuner-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 24dp;
gap: var(--space-xl);
}
.carousel-container {
carousel-container {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
min-width: 0;
}
.description {
font-size: 18dp;
tuner-description {
font-size: var(--font-size-xl);
line-height: 22dp;
color: rgba(255, 255, 255, 50%);
color: rgba(var(--color-white-rgb), 50%);
}
.divider {
tuner-divider {
margin: 1dp 0;
border-top: 1dp rgba(217, 217, 217, 50%);
border-top-width: 1dp;
border-top-color: rgba(var(--color-neutral-rgb), 50%);
}
.footer {
tuner-footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: 24dp;
gap: var(--space-xl);
}
footer-button {
@@ -94,12 +91,12 @@ footer-button {
border: 0;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-family: var(--font-family-heading);
font-weight: bold;
font-size: 20dp;
font-size: var(--font-size-2xl);
line-height: 24dp;
text-transform: uppercase;
color: #FFFFFF;
color: var(--color-white);
opacity: 1;
cursor: pointer;
}
@@ -112,20 +109,20 @@ footer-button.reset {
text-align: right;
}
.stepped-carousel {
stepped-carousel {
display: flex;
align-items: center;
justify-content: center;
gap: 16dp;
gap: var(--space-lg);
width: auto;
min-width: 246dp;
padding: 0;
background-color: transparent;
font-family: "Fira Sans Condensed";
font-family: var(--font-family-heading);
font-weight: bold;
}
.stepped-carousel-value {
stepped-carousel-value {
line-height: 29dp;
min-width: 166dp;
text-align: center;
@@ -142,6 +139,6 @@ footer-button.reset {
background-color: transparent;
opacity: 1;
cursor: pointer;
font-family: "Material Symbols Rounded";
font-family: var(--font-family-icons);
font-weight: normal;
}
+443 -158
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -42,6 +42,8 @@ extern "C" {
#define MOD_ABI_VERSION 1u
#define MOD_ERROR_MESSAGE_SIZE 512u
#define DUSKLIGHT_SERVICE_ID_PREFIX "dev.twilitrealm.dusklight."
typedef struct ModContext ModContext;
typedef enum ModResult {
+1 -1
View File
@@ -3,7 +3,7 @@
#include <mods/api.h>
#include <mods/svc/config.h>
#define ACTOR_SERVICE_ID "dev.twilitrealm.dusklight.actor"
#define ACTOR_SERVICE_ID DUSKLIGHT_SERVICE_ID_PREFIX "actor"
#define ACTOR_SERVICE_MAJOR 1u
#define ACTOR_SERVICE_MINOR 0u

Some files were not shown because too many files have changed in this diff Show More