Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preferences System #1007

Merged
merged 18 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions fission/src/mirabuf/MirabufSceneObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class MirabufSceneObject extends SceneObject {
this._brain?.clearControls();
}

public GetRootNodeId(): Jolt.BodyID | undefined {
return this._mechanism.nodeToBody.get(this._mechanism.rootBody)
}

private CreateMeshForShape(shape: Jolt.Shape): THREE.Mesh {
const scale = new JOLT.Vec3(1, 1, 1)
const triangleContext = new JOLT.ShapeGetTriangles(
Expand Down
13 changes: 6 additions & 7 deletions fission/src/systems/input/InputSystem.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import WorldSystem from "../WorldSystem"
import PreferencesSystem from "../preferences/PreferencesSystem"
import { InputScheme } from "./DefaultInputs"

export type ModifierState = {
Expand Down Expand Up @@ -143,8 +144,6 @@ class AxisInput extends Input {
}

class InputSystem extends WorldSystem {
public static allInputs: Map<string, InputScheme> = new Map()

public static currentModifierState: ModifierState

// A list of keys currently being pressed
Expand Down Expand Up @@ -241,11 +240,11 @@ class InputSystem extends WorldSystem {
return !!InputSystem._keysPressed[key]
}

// If an input exists, return true if it is pressed
public static getInput(inputName: string, assemblyId: string): number {
// Looks for an input assigned to this action
const targetScheme = this.allInputs.get(assemblyId)
const targetInput = targetScheme?.inputs.find(input => input.inputName == inputName)
// If an input exists, return it's value
public static getInput(inputName: string, assemblyName: string, assemblyIndex: number): number {
const targetScheme = PreferencesSystem.getRobotPreferences(assemblyName).inputsSchemes[assemblyIndex]

const targetInput = targetScheme?.inputs.find(input => input.inputName == inputName) as (Input)

if (targetScheme == null || targetInput == null) return 0

Expand Down
74 changes: 74 additions & 0 deletions fission/src/systems/preferences/PreferenceTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Vector3Tuple, Vector4Tuple } from "three"
import { InputScheme } from "../input/DefaultInputs"

export type GlobalPreference =
| "ScreenMode"
| "QualitySettings"
| "ZoomSensitivity"
| "PitchSensitivity"
| "YawSensitivity"
| "ReportAnalytics"
| "UseMetric"
| "RenderScoringZones"

export const RobotPreferencesKey: string = "Robots"
export const FieldPreferencesKey: string = "Fields"

export const DefaultGlobalPreferences: { [key: string]: unknown } = {
ScreenMode: "Windowed",
QualitySettings: "High",
ZoomSensitivity: 15,
PitchSensitivity: 10,
YawSensitivity: 3,
ReportAnalytics: false,
UseMetric: false,
RenderScoringZones: true,
}

export type IntakePreferences = {
location: Vector3Tuple,
diameter: number
}

export type EjectorPreferences = {
location: Vector3Tuple,
ejectorVelocity: number
}

export type RobotPreferences = {
inputsSchemes: InputScheme[],
intake: IntakePreferences,
ejector: EjectorPreferences
}

export type Alliance = "Blue" | "Red"

export type ScoringZonePreferences = {
name: string,
alliance: Alliance,
parent: string,
points: number,
destroyGamepiece: boolean,
persistentPoints: boolean,
localPosition: Vector3Tuple,
localRotation: Vector4Tuple,
localScale: Vector3Tuple
}

export type FieldPreferences = {
defaultSpawnLocation: Vector3Tuple
scoringZones: ScoringZonePreferences[]
}


export function DefaultRobotPreferences(): RobotPreferences {
return {
inputsSchemes: [],
intake: { location: [0, 0, 0], diameter: 1 },
ejector: { location: [0, 0, 0], ejectorVelocity: 1 }
};
}

export function DefaultFieldPreferences(): FieldPreferences {
return { defaultSpawnLocation: [0, 1, 0], scoringZones: [] }
}
142 changes: 142 additions & 0 deletions fission/src/systems/preferences/PreferencesSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { DefaultFieldPreferences, DefaultGlobalPreferences, DefaultRobotPreferences, FieldPreferences, FieldPreferencesKey, GlobalPreference, RobotPreferences, RobotPreferencesKey } from "./PreferenceTypes"

class PreferenceEvent extends Event {
public prefName: GlobalPreference
public prefValue: object

constructor(prefName: GlobalPreference, prefValue: object) {
super("preferenceChanged")
this.prefName = prefName
this.prefValue = prefValue
}
}

class PreferencesSystem {
private static _preferences: { [key: string]: object }
private static _localStorageKey = "Preferences"

/** Event dispatched when any global preference is updated */
public static addEventListener(callback: (e: PreferenceEvent) => unknown) {
window.addEventListener("preferenceChanged", callback as EventListener)
}

/** Sets a global preference to be a value of a specific type */
public static setGlobalPreference<T extends object>(key: GlobalPreference, value: T) {
if (this._preferences == undefined) this.loadPreferences()

window.dispatchEvent(new PreferenceEvent(key, value))
this._preferences[key] = value
}

/** Gets any preference from the preferences map */
private static getPreference<T>(key: string): T | undefined {
if (this._preferences == undefined) this.loadPreferences()

return this._preferences[key] as T
}

/** Gets a global preference, or it's default value if it does not exist in the preferences map */
public static getGlobalPreference<T>(key: GlobalPreference): T {
const customPref = this.getPreference<T>(key)
if (customPref != undefined) return customPref

const defaultPref = DefaultGlobalPreferences[key]
if (defaultPref != undefined) return defaultPref as T

throw new Error("Preference '" + key + "' is not assigned a default!")
}

/** Gets a RobotPreferences object for a robot of a specific mira name */
public static getRobotPreferences(miraName: string): RobotPreferences {
const allRoboPrefs = this.getAllRobotPreferences()

if (allRoboPrefs[miraName] == undefined) {
const defaultPrefs = DefaultRobotPreferences()
allRoboPrefs[miraName] = defaultPrefs
return defaultPrefs
}

return allRoboPrefs[miraName]
}

/** Gets preferences for every robot in local storage */
public static getAllRobotPreferences(): { [key: string]: RobotPreferences } {
let allRoboPrefs = this.getPreference<{ [key: string]: RobotPreferences }>(RobotPreferencesKey)

if (allRoboPrefs == undefined) {
allRoboPrefs = {}
this._preferences[RobotPreferencesKey] = allRoboPrefs
}

return allRoboPrefs
}

/** Gets a FieldPreferences object for a robot of a specific mira name */
public static getFieldPreferences(miraName: string): FieldPreferences {
const allFieldPrefs = this.getAllFieldPreferences()

if (allFieldPrefs[miraName] == undefined) {
const defaultPrefs = DefaultFieldPreferences()
allFieldPrefs[miraName] = defaultPrefs
return defaultPrefs
}

return allFieldPrefs[miraName]
}

/** Gets preferences for every robot in local storage */
public static getAllFieldPreferences(): { [key: string]: FieldPreferences } {
let allFieldPrefs = this.getPreference<{ [key: string]: FieldPreferences }>(RobotPreferencesKey)

if (allFieldPrefs == undefined) {
allFieldPrefs = {}
this._preferences[FieldPreferencesKey] = allFieldPrefs
}

return allFieldPrefs
}

/** Load all preferences from local storage */
public static loadPreferences() {
const loadedPrefs = window.localStorage.getItem(this._localStorageKey)

if (loadedPrefs == undefined) {
console.log("Preferences not found in local storage!")
this._preferences = {}
return
}

try {
this._preferences = JSON.parse(loadedPrefs)
} catch (e) {
console.error(e)
this._preferences = {}
}
}

/** Save all preferences to local storage */
public static savePreferences() {
if (this._preferences == undefined) {
console.log("Preferences not loaded!")
return
}

const prefsString = JSON.stringify(this._preferences)

if (prefsString == undefined) {
console.log("Preferences loaded but undefined")
return
}

window.localStorage.setItem(this._localStorageKey, prefsString)
}

/** Remove all preferences from local storage */
public static clearPreferences() {
window.localStorage.removeItem(this._localStorageKey)
this._preferences = {}
console.log("Cleared all preferences")
}
}

export default PreferencesSystem
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ class ArcadeDriveBehavior extends Behavior {
private leftWheels: WheelDriver[];
private rightWheels: WheelDriver[];
private _assemblyName: string;
private _assemblyIndex: number

private _driveSpeed = 30
private _turnSpeed = 30

constructor(leftWheels: WheelDriver[], rightWheels: WheelDriver[], leftStimuli: WheelRotationStimulus[], rightStimuli: WheelRotationStimulus[], assemblyName: string) {
constructor(leftWheels: WheelDriver[], rightWheels: WheelDriver[], leftStimuli: WheelRotationStimulus[], rightStimuli: WheelRotationStimulus[], assemblyName: string, assemblyIndex: number) {
super(leftWheels.concat(rightWheels), leftStimuli.concat(rightStimuli));

this.leftWheels = leftWheels;
this.rightWheels = rightWheels;
this._assemblyName = assemblyName;
this._assemblyIndex = assemblyIndex
}

// Sets the drivetrains target linear and rotational velocity
Expand All @@ -29,8 +31,8 @@ class ArcadeDriveBehavior extends Behavior {
}

public Update(_: number): void {
const driveInput = InputSystem.getInput("arcadeDrive", this._assemblyName);
const turnInput = InputSystem.getInput("arcadeTurn", this._assemblyName);
const driveInput = InputSystem.getInput("arcadeDrive", this._assemblyName, this._assemblyIndex);
const turnInput = InputSystem.getInput("arcadeTurn", this._assemblyName, this._assemblyIndex);

this.DriveSpeeds(driveInput*this._driveSpeed, turnInput*this._turnSpeed);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ class GenericArmBehavior extends Behavior {
private _hingeDriver: HingeDriver
private _inputName: string
private _assemblyName: string
private _assemblyIndex: number

private _rotationalSpeed = 6

constructor(hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, jointIndex: number, assemblyName: string) {
constructor(hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, jointIndex: number, assemblyName: string, assemblyIndex: number) {
super([hingeDriver], [hingeStimulus])

this._hingeDriver = hingeDriver
this._inputName = "joint " + jointIndex
this._assemblyName = assemblyName
this._assemblyIndex = assemblyIndex
}

// Sets the arms target rotational velocity
Expand All @@ -24,7 +26,9 @@ class GenericArmBehavior extends Behavior {
}

public Update(_: number): void {
this.rotateArm(InputSystem.getInput(this._inputName, this._assemblyName) * this._rotationalSpeed)
this.rotateArm(
InputSystem.getInput(this._inputName, this._assemblyName, this._assemblyIndex) * this._rotationalSpeed
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ class GenericElevatorBehavior extends Behavior {
private _sliderDriver: SliderDriver
private _inputName: string
private _assemblyName: string
private _assemblyIndex: number

private _linearSpeed = 2.5

constructor(sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, jointIndex: number, assemblyName: string) {
constructor(sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, jointIndex: number, assemblyName: string, assemblyIndex: number) {
super([sliderDriver], [sliderStimulus])

this._sliderDriver = sliderDriver
this._inputName = "joint " + jointIndex
this._assemblyName = assemblyName
this._assemblyIndex = assemblyIndex
}

// Changes the elevators target position
Expand All @@ -24,7 +26,7 @@ class GenericElevatorBehavior extends Behavior {
}

public Update(_: number): void {
this.moveElevator(InputSystem.getInput(this._inputName, this._assemblyName) * this._linearSpeed)
this.moveElevator(InputSystem.getInput(this._inputName, this._assemblyName, this._assemblyIndex) * this._linearSpeed)
}
}

Expand Down
Loading
Loading