/** * @file Game Controller Node - Interactive game controller visualization */ import * as React from "react"; import type { NodeDefinition, NodeRendererProps, InspectorRenderProps, ExternalDataReference, } from "../../../../../types/NodeDefinition"; import classes from "./GameControllerNode.module.css"; export type GameControllerData = { id: string; controllerType: "xbox" | "playstation" | "nintendo"; buttons: { a: boolean; b: boolean; x: boolean; y: boolean; lb: boolean; rb: boolean; lt: number; // 0-100 rt: number; // 0-100 }; dpad: { up: boolean; down: boolean; left: boolean; right: boolean; }; leftStick: { x: number; y: number }; // -100 to 100 rightStick: { x: number; y: number }; // -100 to 100 connected: boolean; battery: number; // 0-100 }; export const GameControllerRenderer = ({ node, isSelected, isDragging, externalData }: NodeRendererProps) => { const controllerData = externalData as GameControllerData | undefined; const getControllerColor = (type?: string) => { switch (type) { case "xbox": return "#107c10"; case "playstation": return "#003791"; case "nintendo": return "#e60012"; default: return "#6b7280"; } }; const controllerColor = getControllerColor(controllerData?.controllerType); const renderStick = (x: number, y: number) => { const centerX = 50; const centerY = 50; const stickX = centerX + (x / 100) * 30; const stickY = centerY + (y / 100) * 30; return ( ); }; return (
🎮 {controllerData?.controllerType?.toUpperCase() || "CONTROLLER"}
{controllerData?.connected ? "✓ Connected" : "✗ Disconnected"} | Battery: {controllerData?.battery || 0}%
â–²
â—€
â–¶
â–¼
{renderStick(controllerData?.leftStick.x || 0, controllerData?.leftStick.y || 0)}
Y
X
B
A
{renderStick(controllerData?.rightStick.x || 0, controllerData?.rightStick.y || 0)}
LT
RT
); }; export const GameControllerInspectorRenderer = ({ externalData, onUpdateExternalData }: InspectorRenderProps) => { const controllerData = externalData as GameControllerData | undefined; const [editedData, setEditedData] = React.useState({ id: controllerData?.id || "", controllerType: controllerData?.controllerType || "xbox", buttons: controllerData?.buttons || { a: false, b: false, x: false, y: false, lb: false, rb: false, lt: 0, rt: 0, }, dpad: controllerData?.dpad || { up: false, down: false, left: false, right: false, }, leftStick: controllerData?.leftStick || { x: 0, y: 0 }, rightStick: controllerData?.rightStick || { x: 0, y: 0 }, connected: controllerData?.connected ?? true, battery: controllerData?.battery || 75, }); const handleSave = async () => { if (onUpdateExternalData) { await onUpdateExternalData(editedData); } }; const randomizeInputs = () => { setEditedData((prev) => ({ ...prev, buttons: { a: Math.random() > 0.5, b: Math.random() > 0.5, x: Math.random() > 0.5, y: Math.random() > 0.5, lb: Math.random() > 0.5, rb: Math.random() > 0.5, lt: Math.random() * 100, rt: Math.random() * 100, }, dpad: { up: Math.random() > 0.5, down: Math.random() > 0.5, left: Math.random() > 0.5, right: Math.random() > 0.5, }, leftStick: { x: (Math.random() - 0.5) * 200, y: (Math.random() - 0.5) * 200, }, rightStick: { x: (Math.random() - 0.5) * 200, y: (Math.random() - 0.5) * 200, }, })); }; return (

Game Controller

setEditedData({ ...editedData, buttons: { ...editedData.buttons, lt: Number(e.target.value) } }) } className={classes.slider} />
setEditedData({ ...editedData, buttons: { ...editedData.buttons, rt: Number(e.target.value) } }) } className={classes.slider} />
setEditedData({ ...editedData, battery: Number(e.target.value) })} className={classes.slider} />
); }; export const GameControllerNodeDefinition: NodeDefinition = { type: "game-controller", displayName: "Game Controller", description: "Interactive game controller visualization", category: "Gaming", defaultData: { title: "Game Controller", }, defaultSize: { width: 340, height: 220 }, ports: [ { id: "input-data", type: "input", label: "Input Data", position: "left", }, { id: "output-actions", type: "output", label: "Actions", position: "right", }, ], renderNode: GameControllerRenderer, renderInspector: GameControllerInspectorRenderer, loadExternalData: async (ref: ExternalDataReference) => { await new Promise((resolve) => setTimeout(resolve, 200)); return { id: ref.id, controllerType: "xbox", buttons: { a: false, b: true, x: false, y: false, lb: false, rb: false, lt: 25, rt: 50, }, dpad: { up: false, down: false, left: true, right: false, }, leftStick: { x: -30, y: 40 }, rightStick: { x: 20, y: -50 }, connected: true, battery: 75, }; }, updateExternalData: async (_ref: ExternalDataReference, data: unknown) => { await new Promise((resolve) => setTimeout(resolve, 200)); console.log("Updated game controller data:", data); }, };