Update USDPL WIP
This commit is contained in:
parent
51d9e6565d
commit
0435f14680
16 changed files with 3218 additions and 1223 deletions
2587
package-lock.json
generated
Normal file
2587
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "decky-plugin-template",
|
"name": "kaylon",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "A template to quickly create decky plugins from scratch, based on TypeScript and webpack",
|
"description": "Better than the Borg",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "shx rm -rf dist && rollup -c",
|
"build": "shx rm -rf dist && rollup -c",
|
||||||
"watch": "rollup -c -w",
|
"watch": "rollup -c -w",
|
||||||
|
@ -9,21 +9,20 @@
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/SteamDeckHomebrew/decky-plugin-template.git"
|
"url": "git+https://github.com/NGnius/kaylon.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"decky",
|
"decky",
|
||||||
"plugin",
|
"plugin",
|
||||||
"plugin-template",
|
|
||||||
"steam-deck",
|
"steam-deck",
|
||||||
"deck"
|
"deck"
|
||||||
],
|
],
|
||||||
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/SteamDeckHomebrew/decky-plugin-template/issues"
|
"url": "https://github.com/NGnius/kaylon/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/SteamDeckHomebrew/decky-plugin-template#readme",
|
"homepage": "https://github.com/NGnius/kaylon#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^21.1.0",
|
"@rollup/plugin-commonjs": "^21.1.0",
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
|
@ -41,7 +40,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"decky-frontend-lib": "^1.0.1",
|
"decky-frontend-lib": "^1.0.1",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"usdpl-front": "file:./src/usdpl-front"
|
"usdpl-front": "file:./src/usdpl_front"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"peerDependencyRules": {
|
"peerDependencyRules": {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "Example Plugin",
|
"name": "Kaylon",
|
||||||
"author": "John Doe",
|
"author": "NGnius",
|
||||||
"flags": ["debug", "_root"],
|
"flags": ["debug", "_root"],
|
||||||
"publish": {
|
"publish": {
|
||||||
"tags": ["template", "root"],
|
"tags": ["template", "root"],
|
||||||
"description": "Decky example plugin.",
|
"description": "Better than the Borg",
|
||||||
"image": "https://opengraph.githubassets.com/1/SteamDeckHomebrew/PluginLoader"
|
"image": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,13 +38,13 @@ export type CButton = {
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CToggle {
|
export type CToggle = {
|
||||||
element: string; // "toggle"
|
element: string; // "toggle"
|
||||||
title: string;
|
title: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CSlider {
|
export type CSlider = {
|
||||||
element: string; // "slider"
|
element: string; // "slider"
|
||||||
title: string;
|
title: string;
|
||||||
min: number;
|
min: number;
|
||||||
|
@ -52,7 +52,7 @@ export type CSlider {
|
||||||
notches: string[] | null;
|
notches: string[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CReading {
|
export type CReading = {
|
||||||
element: string; // "reading"
|
element: string; // "reading"
|
||||||
title: string;
|
title: string;
|
||||||
period_ms: number;
|
period_ms: number;
|
||||||
|
|
147
src/index.tsx
147
src/index.tsx
|
@ -2,21 +2,24 @@ import {
|
||||||
ButtonItem,
|
ButtonItem,
|
||||||
definePlugin,
|
definePlugin,
|
||||||
DialogButton,
|
DialogButton,
|
||||||
Menu,
|
//Menu,
|
||||||
MenuItem,
|
//MenuItem,
|
||||||
PanelSection,
|
PanelSection,
|
||||||
PanelSectionRow,
|
PanelSectionRow,
|
||||||
Router,
|
//Router,
|
||||||
ServerAPI,
|
ServerAPI,
|
||||||
showContextMenu,
|
//showContextMenu,
|
||||||
staticClasses,
|
staticClasses,
|
||||||
|
SliderField,
|
||||||
|
ToggleField,
|
||||||
|
//NotchLabel
|
||||||
|
gamepadDialogClasses,
|
||||||
|
joinClassNames,
|
||||||
} from "decky-frontend-lib";
|
} from "decky-frontend-lib";
|
||||||
import { VFC } from "react";
|
import { VFC, useState } from "react";
|
||||||
import { FaShip } from "react-icons/fa";
|
import { GiWashingMachine } from "react-icons/gi";
|
||||||
|
|
||||||
import logo from "../assets/logo.png";
|
import { call_backend } from "usdpl-front";
|
||||||
|
|
||||||
import {init_usdpl, target, init_embedded, call_backend} from "usdpl-front";
|
|
||||||
import * as backend from "./backend";
|
import * as backend from "./backend";
|
||||||
|
|
||||||
// interface AddMethodArgs {
|
// interface AddMethodArgs {
|
||||||
|
@ -24,6 +27,10 @@ import * as backend from "./backend";
|
||||||
// right: number;
|
// right: number;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
const FieldWithSeparator = joinClassNames(gamepadDialogClasses.Field, gamepadDialogClasses.WithBottomSeparatorStandard);
|
||||||
|
|
||||||
|
let items: backend.CElement[] = [];
|
||||||
|
|
||||||
const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
// const [result, setResult] = useState<number | undefined>();
|
// const [result, setResult] = useState<number | undefined>();
|
||||||
|
|
||||||
|
@ -39,6 +46,16 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
// setResult(result.result);
|
// setResult(result.result);
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
const [triggerInternal, updateInternal] = useState<boolean>(false);
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
updateInternal(!triggerInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateIdc(_: any) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
// call hello callback on backend
|
// call hello callback on backend
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -48,41 +65,11 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelSection title="Panel Section">
|
<PanelSection title="Panel Section">
|
||||||
<PanelSectionRow>
|
{items.map(
|
||||||
<ButtonItem
|
(elem, i) => {
|
||||||
layout="below"
|
return <PanelSectionRow>{buildHtmlElement(elem, i, updateIdc)}</PanelSectionRow>
|
||||||
onClick={(e) =>
|
})
|
||||||
showContextMenu(
|
}
|
||||||
<Menu label="Menu" cancelText="CAAAANCEL" onCancel={() => {}}>
|
|
||||||
<MenuItem onSelected={() => {}}>Item #1</MenuItem>
|
|
||||||
<MenuItem onSelected={() => {}}>Item #2</MenuItem>
|
|
||||||
<MenuItem onSelected={() => {}}>Item #3</MenuItem>
|
|
||||||
</Menu>,
|
|
||||||
e.currentTarget ?? window
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Server says yolo
|
|
||||||
</ButtonItem>
|
|
||||||
</PanelSectionRow>
|
|
||||||
|
|
||||||
<PanelSectionRow>
|
|
||||||
<div style={{ display: "flex", justifyContent: "center" }}>
|
|
||||||
<img src={logo} />
|
|
||||||
</div>
|
|
||||||
</PanelSectionRow>
|
|
||||||
|
|
||||||
<PanelSectionRow>
|
|
||||||
<ButtonItem
|
|
||||||
layout="below"
|
|
||||||
onClick={() => {
|
|
||||||
Router.CloseSideMenus();
|
|
||||||
Router.Navigate("/decky-plugin-test");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Router
|
|
||||||
</ButtonItem>
|
|
||||||
</PanelSectionRow>
|
|
||||||
</PanelSection>
|
</PanelSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -91,13 +78,76 @@ const DeckyPluginRouterTest: VFC = () => {
|
||||||
return (
|
return (
|
||||||
<div style={{ marginTop: "50px", color: "white" }}>
|
<div style={{ marginTop: "50px", color: "white" }}>
|
||||||
Hello World!
|
Hello World!
|
||||||
<DialogButton onClick={() => Router.NavigateToStore()}>
|
<DialogButton onClick={() => {}}>
|
||||||
Go to Store
|
Go to Store
|
||||||
</DialogButton>
|
</DialogButton>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function buildHtmlElement(element: backend.CElement, index: number, updateIdc: any) {
|
||||||
|
switch (element.element) {
|
||||||
|
case "button":
|
||||||
|
return buildButton(element as backend.CButton, index, updateIdc);
|
||||||
|
case "slider":
|
||||||
|
return buildSlider(element as backend.CSlider, index, updateIdc);
|
||||||
|
case "toggle":
|
||||||
|
return buildToggle(element as backend.CToggle, index, updateIdc);
|
||||||
|
case "reading":
|
||||||
|
return buildReading(element as backend.CReading, index, updateIdc);
|
||||||
|
}
|
||||||
|
return "Unsupported";
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildButton(element: backend.CButton, index: number, updateIdc: any) {
|
||||||
|
return (
|
||||||
|
<ButtonItem
|
||||||
|
layout="below"
|
||||||
|
onClick={() => {backend.resolve(backend.onUpdate(index, null), updateIdc)}}>
|
||||||
|
{element.title}
|
||||||
|
</ButtonItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSlider(element: backend.CSlider, index: number, updateIdc: any) {
|
||||||
|
return (
|
||||||
|
<SliderField
|
||||||
|
label={element.title}
|
||||||
|
value={element.min}
|
||||||
|
max={element.max}
|
||||||
|
min={element.min}
|
||||||
|
showValue={true}
|
||||||
|
onChange={(value: number) => {
|
||||||
|
backend.resolve(backend.onUpdate(index, value), updateIdc)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildToggle(element: backend.CToggle, index: number, updateIdc: any) {
|
||||||
|
return (
|
||||||
|
<ToggleField
|
||||||
|
checked={false}
|
||||||
|
label={element.title}
|
||||||
|
description={element.description!}
|
||||||
|
onChange={(value: boolean) => {
|
||||||
|
backend.resolve(backend.onUpdate(index, value), updateIdc)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildReading(element: backend.CReading, _index: number, _updateIdc: any) {
|
||||||
|
return (
|
||||||
|
<div className={FieldWithSeparator}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
|
<div className={gamepadDialogClasses.FieldLabel}>{element.title}</div>
|
||||||
|
<div className={gamepadDialogClasses.FieldChildren}>{"idk"}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default definePlugin((serverApi: ServerAPI) => {
|
export default definePlugin((serverApi: ServerAPI) => {
|
||||||
serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
|
serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
|
||||||
exact: true,
|
exact: true,
|
||||||
|
@ -106,15 +156,14 @@ export default definePlugin((serverApi: ServerAPI) => {
|
||||||
// init USDPL WASM frontend
|
// init USDPL WASM frontend
|
||||||
// this is required to interface with the backend
|
// this is required to interface with the backend
|
||||||
(async () => {
|
(async () => {
|
||||||
await init_embedded();
|
await backend.initBackend();
|
||||||
init_usdpl(USDPL_PORT);
|
items = await backend.getElements();
|
||||||
console.log("USDPL started for framework: " + target());
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: <div className={staticClasses.Title}>Example Plugin</div>,
|
title: <div className={staticClasses.Title}>Example Plugin</div>,
|
||||||
content: <Content serverAPI={serverApi} />,
|
content: <Content serverAPI={serverApi} />,
|
||||||
icon: <FaShip />,
|
icon: <GiWashingMachine />,
|
||||||
onDismount() {
|
onDismount() {
|
||||||
serverApi.routerHook.removeRoute("/decky-plugin-test");
|
serverApi.routerHook.removeRoute("/decky-plugin-test");
|
||||||
},
|
},
|
||||||
|
|
57
src/usdpl-front/usdpl.d.ts
vendored
57
src/usdpl-front/usdpl.d.ts
vendored
|
@ -1,57 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* Initialize the front-end library
|
|
||||||
* @param {number} port
|
|
||||||
*/
|
|
||||||
export function init_usdpl(port: number): void;
|
|
||||||
/**
|
|
||||||
* Get the targeted plugin framework, or "any" if unknown
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function target(): string;
|
|
||||||
/**
|
|
||||||
* Call a function on the back-end.
|
|
||||||
* Returns null (None) if this fails for any reason.
|
|
||||||
* @param {string} name
|
|
||||||
* @param {any[]} parameters
|
|
||||||
* @returns {Promise<any>}
|
|
||||||
*/
|
|
||||||
export function call_backend(name: string, parameters: any[]): Promise<any>;
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export class UsdplContext {
|
|
||||||
free(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
||||||
|
|
||||||
export interface InitOutput {
|
|
||||||
readonly memory: WebAssembly.Memory;
|
|
||||||
readonly __wbg_usdplcontext_free: (a: number) => void;
|
|
||||||
readonly init_usdpl: (a: number) => void;
|
|
||||||
readonly target: (a: number) => void;
|
|
||||||
readonly call_backend: (a: number, b: number, c: number, d: number) => number;
|
|
||||||
readonly __wbindgen_malloc: (a: number) => number;
|
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
|
|
||||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
|
||||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h16ac289f583b8044: (a: number, b: number, c: number) => void;
|
|
||||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
||||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
|
||||||
readonly __wbindgen_exn_store: (a: number) => void;
|
|
||||||
readonly wasm_bindgen__convert__closures__invoke2_mut__ha1c5a356ae6a22de: (a: number, b: number, c: number, d: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
||||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
||||||
*
|
|
||||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
|
||||||
*
|
|
||||||
* @returns {Promise<InitOutput>}
|
|
||||||
*/
|
|
||||||
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
|
||||||
|
|
||||||
|
|
||||||
// USDPL customization
|
|
||||||
export function init_embedded();
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
15
src/usdpl-front/usdpl_bg.wasm.d.ts
vendored
15
src/usdpl-front/usdpl_bg.wasm.d.ts
vendored
|
@ -1,15 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
export const memory: WebAssembly.Memory;
|
|
||||||
export function __wbg_usdplcontext_free(a: number): void;
|
|
||||||
export function init_usdpl(a: number): void;
|
|
||||||
export function target(a: number): void;
|
|
||||||
export function call_backend(a: number, b: number, c: number, d: number): number;
|
|
||||||
export function __wbindgen_malloc(a: number): number;
|
|
||||||
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
|
||||||
export const __wbindgen_export_2: WebAssembly.Table;
|
|
||||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h16ac289f583b8044(a: number, b: number, c: number): void;
|
|
||||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
|
||||||
export function __wbindgen_free(a: number, b: number): void;
|
|
||||||
export function __wbindgen_exn_store(a: number): void;
|
|
||||||
export function wasm_bindgen__convert__closures__invoke2_mut__ha1c5a356ae6a22de(a: number, b: number, c: number, d: number): void;
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
21
src/usdpl_front/package.json
Normal file
21
src/usdpl_front/package.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "usdpl-front",
|
||||||
|
"collaborators": [
|
||||||
|
"NGnius (Graham) <ngniusness@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Universal Steam Deck Plugin Library front-end designed for WASM",
|
||||||
|
"version": "0.6.0",
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/NGnius/usdpl-rs"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"usdpl_front_bg.wasm",
|
||||||
|
"usdpl_front.js",
|
||||||
|
"usdpl_front.d.ts"
|
||||||
|
],
|
||||||
|
"module": "usdpl_front.js",
|
||||||
|
"types": "usdpl_front.d.ts",
|
||||||
|
"sideEffects": false
|
||||||
|
}
|
499
src/usdpl_front/usdpl_front.js
Normal file
499
src/usdpl_front/usdpl_front.js
Normal file
File diff suppressed because one or more lines are too long
BIN
src/usdpl_front/usdpl_front_bg.wasm
Normal file
BIN
src/usdpl_front/usdpl_front_bg.wasm
Normal file
Binary file not shown.
Reference in a new issue