[feat] add editor launch option

This commit is contained in:
MathieuG-P
2024-12-22 16:28:33 +01:00
parent 35d1623e8b
commit a45af5baee
15 changed files with 71 additions and 35 deletions
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "Weitere Argumente, bspw: --revert; --nowait"
},
"skipsteam": "Steam überspringen",
"skipsteam-description": "Verhindert, dass Steam automatisch mit Beat Saber geöffnet wird. Aktivieren Sie dies, wenn Sie eine andere VR-Laufzeit wie WiVRn oder Monado verwenden, mit der SteamVR interferieren könnte."
"skipsteam-description": "Verhindert, dass Steam automatisch mit Beat Saber geöffnet wird. Aktivieren Sie dies, wenn Sie eine andere VR-Laufzeit wie WiVRn oder Monado verwenden, mit der SteamVR interferieren könnte.",
"map-editor": "Karteneditor",
"map-editor-description": "Starte den offiziellen Beat Saber-Karteneditor anstelle des Spiels."
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "Additional arguments ex: --revert; --nowait"
},
"skipsteam": "Skip Steam",
"skipsteam-description": "Stops Steam from opening automatically with Beat Saber, enable if you are using a different VR runtime like WiVRn or Monado that SteamVR may interfere with."
"skipsteam-description": "Stops Steam from opening automatically with Beat Saber, enable if you are using a different VR runtime like WiVRn or Monado that SteamVR may interfere with.",
"map-editor": "Map Editor",
"map-editor-description": "Start the official Beat Saber map editor instead of the game."
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -64,7 +64,9 @@
"delete-duplicate-maps": "Borrar duplicados"
},
"skipsteam": "Saltar Steam",
"skipsteam-description": "Evita que Steam se abra automáticamente con Beat Saber, habilita esto si estás usando un runtime de VR diferente como WiVRn o Monado que SteamVR podría interferir."
"skipsteam-description": "Evita que Steam se abra automáticamente con Beat Saber, habilita esto si estás usando un runtime de VR diferente como WiVRn o Monado que SteamVR podría interferir.",
"map-editor": "Editor de mapas",
"map-editor-description": "Inicia el editor oficial de mapas de Beat Saber en lugar del juego."
},
"tabs": {
"maps": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "Arguments supplémentaires ex: --revert; --nowait"
},
"skipsteam": "Ignorer Steam",
"skipsteam-description": "Empêche Steam de s'ouvrir automatiquement avec Beat Saber, activez-le si vous utilisez un autre runtime VR comme WiVRn ou Monado avec lequel SteamVR pourrait interférer."
"skipsteam-description": "Empêche Steam de s'ouvrir automatiquement avec Beat Saber, activez-le si vous utilisez un autre runtime VR comme WiVRn ou Monado avec lequel SteamVR pourrait interférer.",
"map-editor": "Éditeur de map",
"map-editor-description": "Lance l'éditeur officiel de map de Beat Saber au lieu du jeu."
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "추가 인수 예: --revert; --nowait"
},
"skipsteam": "Steam 실행 건너뛰기",
"skipsteam-description": "Beat Saber와 함께 Steam이 자동으로 열리는 것을 방지합니다. SteamVR이 간섭할 수 있는 WiVRn 또는 Monado와 같은 다른 VR 런타임을 사용하는 경우 활성화하세요."
"skipsteam-description": "Beat Saber와 함께 Steam이 자동으로 열리는 것을 방지합니다. SteamVR이 간섭할 수 있는 WiVRn 또는 Monado와 같은 다른 VR 런타임을 사용하는 경우 활성화하세요.",
"map-editor": "맵 편집기",
"map-editor-description": "게임 대신 공식 Beat Saber 맵 편집기를 실행해."
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "Параметры запуска, например: --revert; --nowait"
},
"skipsteam": "Пропустить Steam",
"skipsteam-description": "Предотвращает автоматическое открытие Steam с Beat Saber, включите, если вы используете другую VR-среду, такую как WiVRn или Monado, с которой SteamVR может мешать."
"skipsteam-description": "Предотвращает автоматическое открытие Steam с Beat Saber, включите, если вы используете другую VR-среду, такую как WiVRn или Monado, с которой SteamVR может мешать.",
"map-editor": "Редактор карт",
"map-editor-description": "Запусти официальный редактор карт Beat Saber вместо игры."
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "額外啟動參數,例如: --revert; --nowait"
},
"skipsteam": "跳過 Steam",
"skipsteam-description": "防止 Steam 與 Beat Saber 自動打開,如果您使用的是其他 VR 執行時,如 WiVRn 或 Monado,SteamVR 可能會干擾,請啟用此選項。"
"skipsteam-description": "防止 Steam 與 Beat Saber 自動打開,如果您使用的是其他 VR 執行時,如 WiVRn 或 Monado,SteamVR 可能會干擾,請啟用此選項。",
"map-editor": "地圖編輯器",
"map-editor-description": "啟動官方的 Beat Saber 地圖編輯器,而不是遊戲。"
},
"maps": {
"search-bar": {
+3 -1
View File
@@ -54,7 +54,9 @@
"placeholder": "额外启动参数,例如: --revert; --nowait"
},
"skipsteam": "跳过 Steam",
"skipsteam-description": "防止 Steam 与 Beat Saber 自动打开,如果您使用的是其他 VR 运行时,如 WiVRn 或 Monado,SteamVR 可能会干扰,请启用此选项。"
"skipsteam-description": "防止 Steam 与 Beat Saber 自动打开,如果您使用的是其他 VR 运行时,如 WiVRn 或 Monado,SteamVR 可能会干扰,请启用此选项。",
"map-editor": "地图编辑器",
"map-editor-description": "启动官方的 Beat Saber 地图编辑器,而不是游戏。"
},
"maps": {
"search-bar": {
@@ -25,16 +25,20 @@ export abstract class AbstractLauncherService {
if(!launchOptions.version.steam && !launchOptions.version.oculus){
launchArgs.push("--no-yeet")
}
if (launchOptions.launchMods?.includes(LaunchMods.OCULUS)) {
if(launchOptions.launchMods?.includes(LaunchMods.OCULUS)) {
launchArgs.push("-vrmode");
launchArgs.push("oculus");
}
if (launchOptions.launchMods?.includes(LaunchMods.FPFC)) {
if(launchOptions.launchMods?.includes(LaunchMods.FPFC)) {
launchArgs.push("fpfc");
}
if (launchOptions.launchMods?.includes(LaunchMods.DEBUG)) {
if(launchOptions.launchMods?.includes(LaunchMods.DEBUG)) {
launchArgs.push("--verbose");
}
if(launchOptions.launchMods?.includes(LaunchMods.EDITOR)) {
launchArgs.push("editor");
}
if (launchOptions.additionalArgs) {
launchArgs.push(...launchOptions.additionalArgs);
}
@@ -16,7 +16,7 @@ import { TaskIcon } from "./icons/task-icon.component";
import { CopyIcon } from "./icons/copy-icon.component";
import { SteamIcon } from "./icons/steam-icon.component";
import { CSSProperties, memo } from "react";
import EditIcon from "./icons/edit-icon.component";
import { EditIcon } from "./icons/edit-icon.component";
import { ExportIcon } from "./icons/export-icon.component";
import PatreonIcon from "./icons/patreon-icon.component";
import { SearchIcon } from "./icons/search-icon.component";
@@ -1,9 +1,9 @@
import { CSSProperties } from "react";
import { createSvgIcon } from "../svg-icon.type";
export default function EditIcon(props: { className?: string; style?: CSSProperties }) {
export const EditIcon = createSvgIcon((props, ref) => {
return (
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" height="40" width="40">
<svg ref={ref} {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" height="40" width="40">
<path fill="currentColor" d="M7.833 32.25h1.875L26.75 15.208l-1.875-1.875L7.833 30.375Zm24.959-19.042-5.959-5.916 1.917-1.917q.833-.833 2.042-.833 1.208 0 2.083.875l1.833 1.833q.875.833.854 2.021-.02 1.187-.854 2.021ZM6.542 35.125q-.667 0-1.125-.458-.459-.459-.459-1.125v-3.709q0-.333.104-.604.105-.271.355-.521L24.875 9.25l5.958 5.958-19.458 19.459q-.25.25-.542.354-.291.104-.583.104Zm19.25-20.833-.917-.959 1.875 1.875Z" />
</svg>
);
}
})
@@ -16,7 +16,7 @@ export function LaunchModToogle({ onClick, active, text, icon: Icon, infoText }:
const t = useTranslation();
return (
<button className={`relative rounded-full cursor-pointer group active:scale-95 transition-transform ${!active && "shadow-md shadow-black"}`} onClick={() => onClick(!active)}>
<button className={`shrink-0 relative rounded-full cursor-pointer group active:scale-95 transition-transform ${!active && "shadow-md shadow-black"}`} onClick={() => onClick(!active)}>
<GlowEffect visible={active} className="absolute !rounded-full blur-[2px]" />
<div className="w-full h-full px-6 flex gap-1.5 justify-center items-center bg-light-main-color-2 dark:bg-main-color-2 p-3 rounded-full text-gray-800 dark:text-white group-hover:bg-light-main-color-1 dark:group-hover:bg-main-color-1">
{Icon && <Icon className="h-7 shrink-0 text-gray-800 dark:text-white" />}
@@ -37,7 +37,7 @@ export function LaunchOptionsPanel({ className, open, launchArgs, launchMods, on
export type LaunchModItemProps = {
readonly id: LaunchMod;
readonly Icon?: SvgIcon;
readonly icon?: SvgIcon;
readonly label: string;
readonly description: string;
readonly active: boolean;
@@ -47,21 +47,23 @@ export type LaunchModItemProps = {
readonly onPinChange?: (val: boolean) => void;
}
export function LaunchModItem({ id, Icon, label, description, active, visible, pinned, onChange, onPinChange }: LaunchModItemProps) {
export function LaunchModItem({ id, icon: Icon, label, description, active, visible, pinned, onChange, onPinChange }: LaunchModItemProps) {
const { text: t } = useTranslationV2();
return (
<Tippy theme="default" placement="top" content={description}>
<button id={id} className={cn("grow rounded-md bg-theme-1 relative flex justify-center items-center gap-1.5 h-10 py-1 px-3", visible === false && "hidden")} onClick={e => { e.preventDefault(); e.stopPropagation(); onChange?.(!active) }}>
<BsmCheckbox className="h-4 aspect-square z-[1] relative" checked={active} onChange={onChange}/>
{Icon && <Icon className="h-full w-fit py-0.5"/>}
<button id={id} className={cn("grow rounded-md bg-theme-1 relative flex justify-center items-center h-10 py-1 px-3", visible === false && "hidden")} onClick={e => { e.preventDefault(); e.stopPropagation(); onChange?.(!active) }}>
<BsmCheckbox className="h-4 aspect-square z-[1] relative mr-1.5" checked={active} onChange={onChange}/>
{Icon && <Icon className="h-full w-fit py-0.5 mr-1.5"/>}
<span className="font-bold">{label}</span>
<Tippy theme="default" placement="right" content={pinned ? t("misc.unpin") : t("misc.pin")} hideOnClick>
<button className="h-full py-2" onClick={e => { e.preventDefault(); e.stopPropagation(); onPinChange?.(!pinned) }}>
{pinned ? <UnpinIcon className="size-full"/> : <PinIcon className="size-full"/>}
</button>
</Tippy>
{onPinChange && (
<Tippy theme="default" placement="right" content={pinned ? t("misc.unpin") : t("misc.pin")} hideOnClick>
<button className="h-full py-2 px-1.5" onClick={e => { e.preventDefault(); e.stopPropagation(); onPinChange?.(!pinned) }}>
{pinned ? <UnpinIcon className="size-full"/> : <PinIcon className="size-full"/>}
</button>
</Tippy>
)}
</button>
</Tippy>
);
@@ -25,6 +25,7 @@ import { OculusIcon } from "renderer/components/svgs/icons/oculus-icon.component
import { DesktopIcon } from "renderer/components/svgs/icons/desktop-icon.component";
import { TerminalIcon } from "renderer/components/svgs/icons/terminal-icon.component";
import { DefaultConfigKey } from "renderer/config/default-configuration.config";
import { EditIcon } from "renderer/components/svgs/icons/edit-icon.component";
type Props = { version: BSVersion };
@@ -65,7 +66,7 @@ export function LaunchSlide({ version }: Props) {
setLaunchModItems(() => [
{
id: LaunchMods.OCULUS,
Icon: OculusIcon,
icon: OculusIcon,
label: t("pages.version-viewer.launch-mods.oculus"),
description: t("pages.version-viewer.launch-mods.oculus-description"),
active: activeLaunchMods.includes(LaunchMods.OCULUS),
@@ -76,7 +77,7 @@ export function LaunchSlide({ version }: Props) {
},
{
id: LaunchMods.FPFC,
Icon: DesktopIcon,
icon: DesktopIcon,
label: t("pages.version-viewer.launch-mods.desktop"),
description: t("pages.version-viewer.launch-mods.desktop-description"),
active: activeLaunchMods.includes(LaunchMods.FPFC),
@@ -86,7 +87,7 @@ export function LaunchSlide({ version }: Props) {
},
{
id: LaunchMods.DEBUG,
Icon: TerminalIcon,
icon: TerminalIcon,
label: t("pages.version-viewer.launch-mods.debug"),
description: t("pages.version-viewer.launch-mods.debug-description"),
active: activeLaunchMods.includes(LaunchMods.DEBUG),
@@ -102,6 +103,18 @@ export function LaunchSlide({ version }: Props) {
pinned: pinnedLaunchMods.includes(LaunchMods.SKIP_STEAM),
onChange: checked => checked ? setActiveLaunchMods(prev => [...prev, LaunchMods.SKIP_STEAM]) : setActiveLaunchMods(prev => prev.filter(mod => mod !== LaunchMods.SKIP_STEAM)),
onPinChange: pinned => pinned ? setPinnedLaunchMods(prev => [...prev, LaunchMods.SKIP_STEAM]) : setPinnedLaunchMods(prev => prev.filter(mod => mod !== LaunchMods.SKIP_STEAM)),
},
{
id: LaunchMods.EDITOR,
icon: EditIcon,
label: t("pages.version-viewer.launch-mods.map-editor"),
description: t("pages.version-viewer.launch-mods.map-editor-description"),
active: activeLaunchMods.includes(LaunchMods.EDITOR),
pinned: pinnedLaunchMods.includes(LaunchMods.EDITOR),
visible: !safeLt(version.BSVersion, "1.23.0"),
onChange: checked => checked ? setActiveLaunchMods(prev => [...prev, LaunchMods.EDITOR]) : setActiveLaunchMods(prev => prev.filter(mod => mod !== LaunchMods.EDITOR)),
onPinChange: pinned => pinned ? setPinnedLaunchMods(prev => [...prev, LaunchMods.EDITOR]) : setPinnedLaunchMods(prev => prev.filter(mod => mod !== LaunchMods.EDITOR)),
}
]);
}, [activeLaunchMods, pinnedLaunchMods, version]);
@@ -123,8 +136,8 @@ export function LaunchSlide({ version }: Props) {
}, [version]);
return (
<div className="w-full shrink-0 items-center relative flex flex-col justify-start">
<div className="flex flex-col gap-3 justify-center items-center mb-5">
<div className="w-full shrink-0 items-center relative flex flex-col justify-start overflow-hidden">
<div className="flex flex-col gap-3 justify-center items-center mb-4">
<div className="h-24 flex justify-center items-center">
<BsmImage className="relative object-cover h-28" image={BSLogo} />
</div>
@@ -139,12 +152,12 @@ export function LaunchSlide({ version }: Props) {
)}
</h1>
</div>
<div className="grid grid-flow-col gap-6">
<div className="w-full flex justify-center items-center gap-4 flex-wrap scrollbar-default">
{pinnedLaunchMods.map(id => launchModItems.find(mod => mod.id === id)).map(launchMod => {
if(launchMod?.visible === false || !launchMod?.pinned) { return undefined; }
return (
<LaunchModToogle
icon={launchMod.Icon}
icon={launchMod.icon}
infoText={launchMod.description}
text={launchMod.label}
active={launchMod.active}
@@ -153,7 +166,7 @@ export function LaunchSlide({ version }: Props) {
);
})}
</div>
<div className="pt-4 w-2/3 flex flex-col items-center gap-3">
<div className="mt-4 flex flex-col items-center justify-center gap-3">
<div className="relative">
<GlowEffect className="!rounded-full" visible={!!(activeLaunchMods?.length || additionalArgsString)}/>
<BsmButton
@@ -5,6 +5,7 @@ export const LaunchMods = {
FPFC: "fpfc",
DEBUG: "debug",
SKIP_STEAM: "skip_steam",
EDITOR: "editor",
} as const;
export type LaunchMod = typeof LaunchMods[keyof typeof LaunchMods];