Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fission/src/systems/analytics/AnalyticsSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export interface AnalyticsEvents {
// Scheme Events
"Scheme Applied": {
isCustomized: boolean
schemeId: string
schemeName: string
}

Expand Down
12 changes: 12 additions & 0 deletions fission/src/systems/input/DefaultInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TouchControlsAxes } from "@/ui/components/TouchControls"
import type { InputScheme, ModifierState } from "./InputTypes"
import AxisInput from "./inputs/AxisInput"
import ButtonInput from "./inputs/ButtonInput"
import * as uuid from "uuid"

type InputSupplier = () => InputScheme
/** The purpose of this class is to store any defaults related to the input system. */
Expand All @@ -15,6 +16,7 @@ class DefaultInputs {
meta: false,
}
return {
schemeId: "7e3893a0-bfe1-48f5-b9cb-d0a2e8735aff",
schemeName: "Ernie",
descriptiveName: "WASD",
customized: false,
Expand Down Expand Up @@ -46,6 +48,7 @@ class DefaultInputs {
meta: false,
}
return {
schemeId: "d3679b65-3660-444b-984e-5f97a1a0f0a1",
schemeName: "Bert",
descriptiveName: "WSIK",
customized: false,
Expand Down Expand Up @@ -77,6 +80,7 @@ class DefaultInputs {
meta: false,
}
return {
schemeId: "2552cda2-8784-46b6-9661-227b2b6a323f",
schemeName: "Luna",
descriptiveName: "Arrow Keys",
customized: false,
Expand All @@ -102,6 +106,7 @@ class DefaultInputs {

public static jax: InputSupplier = () => {
return {
schemeId: "48d1db69-2a71-4244-9b21-cf544af19d5d",
schemeName: "Jax",
descriptiveName: "Full Controller",
customized: false,
Expand Down Expand Up @@ -129,6 +134,7 @@ class DefaultInputs {
/** We like this guy */
public static hunter: InputSupplier = () => {
return {
schemeId: "1cd109b1-91cc-4458-a5d9-bdaa9c5c38d2",
schemeName: "Hunter",
descriptiveName: "Left Stick",
customized: false,
Expand All @@ -151,6 +157,7 @@ class DefaultInputs {

public static carmela: InputSupplier = () => {
return {
schemeId: "fcce7958-1471-420e-b886-4541b236faff",
schemeName: "Carmela",
descriptiveName: "Right Stick",
customized: false,
Expand All @@ -173,6 +180,7 @@ class DefaultInputs {

public static brandon: InputSupplier = () => {
return {
schemeId: "416b39da-6019-49ed-b850-b94e350c61f3",
schemeName: "Brandon",
descriptiveName: "Touch Controls",
customized: false,
Expand All @@ -187,6 +195,7 @@ class DefaultInputs {
}
public static julian: InputSupplier = () => {
return {
schemeId: "39b7c8e4-2253-4f07-aa97-35cad79c473e",
schemeName: "Julian",
descriptiveName: "Touch Controls",
customized: false,
Expand All @@ -208,6 +217,7 @@ class DefaultInputs {
meta: false,
}
return {
schemeId: "7e9a4167-e2a0-47dd-a596-60e043177c42",
schemeName: "Felix",
descriptiveName: "WASD + Arrows (Swerve)",
customized: false,
Expand Down Expand Up @@ -236,6 +246,7 @@ class DefaultInputs {

public static gizmo: InputSupplier = () => {
return {
schemeId: "8cbe6b7e-10ca-4d15-b26b-feedf690f762",
schemeName: "Gizmo",
descriptiveName: "Dual Stick (Swerve)",
customized: false,
Expand Down Expand Up @@ -295,6 +306,7 @@ class DefaultInputs {
break
}
return {
schemeId: uuid.v4(),
schemeName: "",
descriptiveName: "",
customized: true,
Expand Down
28 changes: 9 additions & 19 deletions fission/src/systems/input/InputSchemeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ class InputSchemeManager {
}

public static rebindOldBrainSchemes() {
const schemesByName = new Map(this.allInputSchemes.map(s => [s.schemeName, s] as const))
const schemesById = new Map(this.allInputSchemes.map(s => [s.schemeId, s] as const))
for (const [brainIndex, scheme] of InputSystem.brainIndexSchemeMap) {
const reverted = schemesByName.get(scheme.schemeName)
const reverted = schemesById.get(scheme.schemeId)
if (reverted && scheme.customized) {
InputSystem.setBrainIndexSchemeMapping(brainIndex, reverted)
}
Expand All @@ -95,18 +95,7 @@ class InputSchemeManager {

/** Creates an array of every input scheme that is either a default or customized by the user. Custom themes will appear on top. */
public static get allInputSchemes(): InputScheme[] {
// Start with custom input schemes
const allSchemes: InputScheme[] = []

this.customInputSchemes.forEach(s => allSchemes.push(s))

// Add default schemes if they have not been customized
this.defaultInputSchemes.forEach(defaultScheme => {
if (allSchemes.some(s => s.schemeName === defaultScheme.schemeName)) return
allSchemes.push(defaultScheme)
})

return allSchemes
return [...this.customInputSchemes, ...this.defaultInputSchemes]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different behavior from before, and will show both Ernie and customized Ernie, rather than just the customized one.

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I asked azalea about that and she said not filtering out default schemes with the same name was a good idea, but I can revert that change.

}

/** Creates an array of every input scheme that is not currently in use by a robot */
Expand All @@ -115,9 +104,10 @@ class InputSchemeManager {

// Remove schemes that have conflicts
const usedKeyMap = new Map<KeyDescriptor, string[]>()
// maps scheme ids to availability
const result: Record<string, InputSchemeAvailability> = {}
for (const scheme of InputSystem.brainIndexSchemeMap.values()) {
result[scheme.schemeName] = {
result[scheme.schemeId] = {
scheme,
status: InputSchemeUseType.IN_USE,
}
Expand All @@ -127,9 +117,9 @@ class InputSchemeManager {
.forEach(key => {
const entry = usedKeyMap.get(key)
if (entry != null) {
entry.push(scheme.schemeName)
entry.push(scheme.schemeId)
} else {
usedKeyMap.set(key, [scheme.schemeName])
usedKeyMap.set(key, [scheme.schemeId])
}
})
})
Expand All @@ -140,13 +130,13 @@ class InputSchemeManager {
input.keysUsed.flatMap(key => usedKeyMap.get(key) ?? [])
)
if (conflictingSchemes.length > 0) {
result[scheme.schemeName] ??= {
result[scheme.schemeId] ??= {
scheme,
status: InputSchemeUseType.CONFLICT,
conflictingSchemeNames: [...new Set(conflictingSchemes)].join(", "),
}
} else {
result[scheme.schemeName] ??= {
result[scheme.schemeId] ??= {
scheme,
status: InputSchemeUseType.AVAILABLE,
}
Expand Down
1 change: 1 addition & 0 deletions fission/src/systems/input/InputSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class InputSystem extends WorldSystem {
this.brainIndexSchemeMap.set(index, scheme)
World.analyticsSystem?.event("Scheme Applied", {
isCustomized: scheme.customized,
schemeId: scheme.schemeId,
schemeName: scheme.schemeName,
})
}
Expand Down
2 changes: 2 additions & 0 deletions fission/src/systems/input/InputTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export type ModifierState = Readonly<{
}>

export type InputScheme = {
// UUID
schemeId: string
schemeName: string
descriptiveName: string
customized: boolean
Expand Down
29 changes: 28 additions & 1 deletion fission/src/systems/preferences/PreferencesSystem.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import DefaultInputs from "../input/DefaultInputs"
import * as UUID from "uuid"
import {
defaultFieldPreferences,
defaultGraphicsPreferences,
Expand Down Expand Up @@ -184,7 +186,32 @@ class PreferencesSystem {

unmigratedKeys.forEach(key => {
const userPreferences = saved[USER_PREFERENCE_KEY] as Record<UserPreference, unknown>
userPreferences[key] = saved[key]

switch (key) {
case "InputSchemes": {
// migrate to uuids
const defaultSchemes = DefaultInputs.defaultInputCopies
userPreferences[key] = saved[key].map(scheme => {
if (scheme.schemeId) return scheme

if (scheme.customized) {
scheme.schemeId = UUID.v4()
return scheme
}

const matchingDefaultScheme =
defaultSchemes.find(s => s.descriptiveName === scheme.descriptiveName) ??
defaultSchemes.find(s => s.schemeName === scheme.schemeName)

scheme.schemeId = matchingDefaultScheme?.schemeId ?? UUID.v4()

return scheme
})
break
}
default:
userPreferences[key] = saved[key]
}
Comment on lines +190 to +214

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will only migrate people from before #1371, otherwise they won't be considered "umigratedKeys"


delete saved[key]
})
Expand Down
2 changes: 1 addition & 1 deletion fission/src/test/InputSystem.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe("Input Scheme Manager Checks", () => {

const rebound = InputSystem.getBrainIndexSchemeMapping(brainIndex)!
expect(rebound).not.toBe(edited)
expect(rebound.schemeName).toBe(DefaultInputs.ernie().schemeName)
expect(rebound.schemeId).toBe(DefaultInputs.ernie().schemeId)
})
})

Expand Down
19 changes: 17 additions & 2 deletions fission/src/ui/StateProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import type React from "react"
import { useMemo, useState } from "react"
import { useMemo, useState, useReducer } from "react"
import type { AppMode } from "@/systems/AppMode"
import type { InputScheme } from "@/systems/input/InputTypes"
import * as UUID from "uuid"
import { StateContext, type StateProviderProps } from "./helpers/StateProviderHelpers"

function updateScheme(
newScheme: InputScheme | undefined,
previousScheme: InputScheme | undefined
): InputScheme | undefined {
if (newScheme === undefined) return undefined
if (previousScheme === undefined) return newScheme

return {
...newScheme,
customized: true,
schemeId: previousScheme.customized ? previousScheme.schemeId : UUID.v4(),
}
}

export const StateProvider: React.FC<StateProviderProps> = ({ children }) => {
const [selectedScheme, setSelectedScheme] = useState<InputScheme | undefined>(undefined)
const [selectedScheme, setSelectedScheme] = useReducer(updateScheme, undefined)
const [appMode, setAppMode] = useState<AppMode>("Configure")

const stateContextValue = useMemo(
Expand Down
1 change: 1 addition & 0 deletions fission/src/ui/helpers/StateProviderHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface StateProviderProps {
export interface AppState {
// ConfigureInputs stuff
selectedScheme?: InputScheme
// setSelectedScheme will handle updating schemeId and customized
setSelectedScheme: (_scheme: InputScheme | undefined) => void
// Top bar mode selector
appMode: AppMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { setSpotlightAssembly } from "@/mirabuf/MirabufSceneObject.ts"
import ChooseInputSchemePanel from "@/panels/configuring/ChooseInputSchemePanel.tsx"
import { CloseType, useUIContext } from "@/ui/helpers/UIProviderHelpers.ts"
import ConfigureSchemeInterface from "@/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx"
import { useMemo, useState } from "react"
import { useEffect, useMemo, useState } from "react"
import type SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain.ts"
import { Stack } from "@mui/material"
import ConfirmChangesModal from "@/modals/configuring/ConfirmChangesModal.tsx"
Expand All @@ -20,7 +20,15 @@ const ControlsConfigInterface: ConfigurationSubpanelComponent = ({

const [isEditing, setIsEditing] = useState<boolean>(false)
const brainIndex = useMemo(() => (selectedAssembly.brain as SynthesisBrain).brainIndex, [selectedAssembly])
const scheme = useMemo(() => InputSystem.getBrainIndexSchemeMapping(brainIndex), [brainIndex])

const [scheme, setScheme] = useState(InputSystem.getBrainIndexSchemeMapping(brainIndex))
useEffect(() => {
setScheme(InputSystem.getBrainIndexSchemeMapping(brainIndex))
}, [brainIndex])
useEffect(() => {
if (scheme === undefined) return
InputSystem.setBrainIndexSchemeMapping(brainIndex, scheme)
}, [scheme])

const { openPanel, closePanel, openModal } = useUIContext()
return (
Expand Down Expand Up @@ -59,6 +67,7 @@ const ControlsConfigInterface: ConfigurationSubpanelComponent = ({
<ConfigureSchemeInterface
registerCleanupFunction={registerCleanupFunction}
selectedScheme={scheme}
setSelectedScheme={setScheme}
panelId={panel?.id}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ const ConfigureInputsInterface: React.FC<Pick<ConfigurationSubpanelProps, "regis
registerCleanupFunction,
}) => {
const { openModal, closePanel } = useUIContext()
const { selectedScheme: currentSelectedScheme, setSelectedScheme: setGlobalSelectedScheme } = useStateContext()
const { selectedScheme, setSelectedScheme } = useStateContext()

const [selectedScheme, setSelectedScheme] = useState<InputScheme | undefined>(currentSelectedScheme)
const [schemes, setSchemes] = useState<InputScheme[]>(InputSchemeManager.allInputSchemes)

const saveEvent = useCallback(() => {
Expand All @@ -66,11 +65,10 @@ const ConfigureInputsInterface: React.FC<Pick<ConfigurationSubpanelProps, "regis
const unsubscribeInput = EventSystem.listen("InputSchemeChanged", handleSchemeChange)
return () => {
setSelectedScheme(undefined)
setGlobalSelectedScheme(undefined)
unsubscribeConfig()
unsubscribeInput()
}
}, [saveEvent, handleSchemeChange, setGlobalSelectedScheme])
}, [saveEvent, handleSchemeChange])

const schemeOptionMap = useMemo(() => {
const map = new Map<InputScheme, SchemeSelectionOption>()
Expand Down Expand Up @@ -134,6 +132,7 @@ const ConfigureInputsInterface: React.FC<Pick<ConfigurationSubpanelProps, "regis
) : (
<ConfigureSchemeInterface
selectedScheme={selectedScheme}
setSelectedScheme={setSelectedScheme}
panelId={panel?.id}
registerCleanupFunction={registerCleanupFunction}
onBack={() => setSelectedScheme(undefined)}
Expand Down
Loading
Loading