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

Input Manager #977

Merged
merged 17 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from 11 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
2 changes: 1 addition & 1 deletion engine/Assets/Scripts/Drivers/WheelDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,4 @@ private void VelocityControl() {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,4 @@ public enum SynthesisColor {
AcceptCancelButtonText
}
}
}
}
3 changes: 2 additions & 1 deletion fission/src/mirabuf/MirabufSceneObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { LayerReserve } from "@/systems/physics/PhysicsSystem";
import Mechanism from "@/systems/physics/Mechanism";
import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain";

const DEBUG_BODIES = true;
const DEBUG_BODIES = false;

interface RnDebugMeshes {
colliderMesh: THREE.Mesh;
Expand Down Expand Up @@ -91,6 +91,7 @@ class MirabufSceneObject extends SceneObject {
colliderMesh.rotation.setFromRotationMatrix(transform);

const comTransform = JoltMat44_ThreeMatrix4(body.GetCenterOfMassTransform());

comMesh.position.setFromMatrixPosition(comTransform);
comMesh.rotation.setFromRotationMatrix(comTransform);
}
Expand Down
5 changes: 5 additions & 0 deletions fission/src/systems/World.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as THREE from "three";
import PhysicsSystem from "./physics/PhysicsSystem";
import SceneRenderer from "./scene/SceneRenderer";
import SimulationSystem from "./simulation/SimulationSystem";
import InputSystem from "./input/InputSystem";

class World {

Expand All @@ -12,6 +13,7 @@ class World {
private static _sceneRenderer: SceneRenderer;
private static _physicsSystem: PhysicsSystem;
private static _simulationSystem: SimulationSystem;
private static _inputSystem: InputSystem;

public static get isAlive() { return World._isAlive; }

Expand All @@ -29,6 +31,7 @@ class World {
World._sceneRenderer = new SceneRenderer();
World._physicsSystem = new PhysicsSystem();
World._simulationSystem = new SimulationSystem();
World._inputSystem = new InputSystem();
}

public static DestroyWorld() {
Expand All @@ -40,12 +43,14 @@ class World {
World._physicsSystem.Destroy();
World._sceneRenderer.Destroy();
World._simulationSystem.Destroy();
World._inputSystem.Destroy();
}

public static UpdateWorld() {
const deltaT = World._clock.getDelta();
World._simulationSystem.Update(deltaT);
World._physicsSystem.Update(deltaT);
World._inputSystem.Update(deltaT);
World._sceneRenderer.Update(deltaT);
}
}
Expand Down
131 changes: 131 additions & 0 deletions fission/src/systems/input/InputSystem.ts
Original file line number Diff line number Diff line change
@@ -1,0 +1,131 @@
import WorldSystem from "../WorldSystem";

declare global {
type ModifierState = {
alt: boolean
ctrl: boolean
shift: boolean
meta: boolean
}

type Input = {
name: string
keybind: string
isGlobal: boolean
modifiers: ModifierState
}
}

export const emptyModifierState: ModifierState = { ctrl: false, alt: false, shift: false, meta: false };

// When a robot is loaded, default inputs replace any unassigned inputs
const defaultInputs: { [key: string]: Input } = {
"intake": { name: "intake", keybind: "e", isGlobal: true, modifiers: emptyModifierState },
"shootGamepiece": { name: "shootGamepiece", keybind: "q", isGlobal: true, modifiers: emptyModifierState },
"enableGodMode": { name: "enableGodMode", keybind: "g", isGlobal: true, modifiers: emptyModifierState },

"arcadeForward": { name: "arcadeForward", keybind: "w", isGlobal: false, modifiers: emptyModifierState },
"arcadeBackward": { name: "arcadeBackward", keybind: "s", isGlobal: false, modifiers: emptyModifierState },
"arcadeLeft": { name: "arcadeLeft", keybind: "a", isGlobal: false, modifiers: emptyModifierState },
"arcadeRight": { name: "arcadeRight", keybind: "d", isGlobal: false, modifiers: emptyModifierState },
}

class InputSystem extends WorldSystem {
public static allInputs: { [key: string]: Input } = { }
private static _currentModifierState: ModifierState;

// Inputs global to all of synthesis like camera controls
public static get globalInputs(): { [key: string]: Input } {
return Object.fromEntries(
Object.entries(InputSystem.allInputs)
.filter(([_, input]) => input.isGlobal));
}

// Robot specific controls like driving
public static get robotInputs(): { [key: string]: Input } {
return Object.fromEntries(
Object.entries(InputSystem.allInputs)
.filter(([_, input]) => !input.isGlobal));
}

// A list of keys currently being pressed
private static _keysPressed: { [key: string]: boolean } = {};

constructor() {
super();

this.handleKeyDown = this.handleKeyDown.bind(this);
document.addEventListener('keydown', this.handleKeyDown);

this.handleKeyUp = this.handleKeyUp.bind(this);
document.addEventListener('keyup', this.handleKeyUp);

// TODO: Load saved inputs from mira (robot specific) & global inputs

for (let key in defaultInputs) {

Check failure on line 65 in fission/src/systems/input/InputSystem.ts

View workflow job for this annotation

GitHub Actions / ESLint Format Validation

'key' is never reassigned. Use 'const' instead
if (defaultInputs.hasOwnProperty(key)) {

Check failure on line 66 in fission/src/systems/input/InputSystem.ts

View workflow job for this annotation

GitHub Actions / ESLint Format Validation

Do not access Object.prototype method 'hasOwnProperty' from target object
InputSystem.allInputs[key] = defaultInputs[key];
}
}
}

public Update(_: number): void {InputSystem
InputSystem._currentModifierState = { ctrl: InputSystem.isKeyPressed("Control"), alt: InputSystem.isKeyPressed("Alt"), shift: InputSystem.isKeyPressed("Shift"), meta: InputSystem.isKeyPressed("Meta") }
}

public Destroy(): void {
document.removeEventListener('keydown', this.handleKeyDown);
document.removeEventListener('keyup', this.handleKeyUp);
}

// Called when any key is pressed
handleKeyDown(event: KeyboardEvent) {
InputSystem._keysPressed[event.key] = true;
}

// Called when any key is released
handleKeyUp(event: KeyboardEvent) {
InputSystem._keysPressed[event.key] = false;
}

// Returns true if the given key is currently down
private static isKeyPressed(key: string): boolean {
return !!InputSystem._keysPressed[key];
}

// If an input exists, return true if it is pressed
public static getInput(inputName: string) : boolean {
// Checks if there is an input assigned to this action
if (inputName in this.allInputs) {
let targetInput = this.allInputs[inputName];

Check failure on line 100 in fission/src/systems/input/InputSystem.ts

View workflow job for this annotation

GitHub Actions / ESLint Format Validation

'targetInput' is never reassigned. Use 'const' instead

// Check for input modifiers
if (!this.compareModifiers(InputSystem._currentModifierState, targetInput.modifiers))
return false;

return this.isKeyPressed(targetInput.keybind);
}

// If the input does not exist, returns false
return false;
}

// Combines two inputs into a positive/negative axis
public static getAxis(positive: string, negative: string) {
return (this.getInput(positive) ? 1 : 0) - (this.getInput(negative) ? 1 : 0);
}

// Converts camelCase to Title Case for the inputs modal
public static toTitleCase(camelCase: string) : string {
const result = camelCase.replace(/([A-Z])/g, " $1");
const finalResult = result.charAt(0).toUpperCase() + result.slice(1);
return finalResult;
}

// Returns true if two modifier states are identical
private static compareModifiers(state1: ModifierState, state2: ModifierState) : boolean {
return state1.alt == state2.alt && state1.ctrl == state2.ctrl && state1.meta == state2.meta && state1.shift == state2.shift;
}
}

export default InputSystem;
8 changes: 6 additions & 2 deletions fission/src/systems/simulation/SimulationSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class SimulationLayer {
private _stimuli: Stimulus[];

public get brain() { return this._brain; }
public get drivers() { return this._drivers; }
public get stimuli() { return this._stimuli; }

constructor(mechanism: Mechanism) {
this._mechanism = mechanism;
Expand Down Expand Up @@ -105,9 +107,11 @@ class SimulationLayer {

this._brain = brain;

if (this._brain)
if (this._brain) {
this._brain.Enable();
}
}
}

export default SimulationSystem;
export default SimulationSystem;
export {SimulationLayer};
35 changes: 35 additions & 0 deletions fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import WheelDriver from "../driver/WheelDriver";
import WheelRotationStimulus from "../stimulus/WheelStimulus";
import Behavior from "./Behavior";
import InputSystem from "@/systems/input/InputSystem";

class ArcadeDriveBehavior extends Behavior {
leftWheels: WheelDriver[];
rightWheels: WheelDriver[];

private _driveSpeed = 30;
private _turnSpeed = 30;

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

this.leftWheels = leftWheels;
this.rightWheels = rightWheels;
}

// Sets the drivetrains target linear and rotational velocity
driveSpeeds(linearVelocity: number, rotationVelocity: number) {
let leftSpeed = linearVelocity + rotationVelocity;

Check failure on line 22 in fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts

View workflow job for this annotation

GitHub Actions / ESLint Format Validation

'leftSpeed' is never reassigned. Use 'const' instead
let rightSpeed = linearVelocity - rotationVelocity;

Check failure on line 23 in fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts

View workflow job for this annotation

GitHub Actions / ESLint Format Validation

'rightSpeed' is never reassigned. Use 'const' instead

this.leftWheels.forEach((wheel) => wheel.targetWheelSpeed = leftSpeed);
this.rightWheels.forEach((wheel) => wheel.targetWheelSpeed = rightSpeed);
}

public Update(_: number): void {
this.driveSpeeds(InputSystem.getAxis("arcadeForward", "arcadeBackward")*this._driveSpeed,
InputSystem.getAxis("arcadeRight", "arcadeLeft")*this._turnSpeed);
}
}

export default ArcadeDriveBehavior;
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ abstract class Behavior {
this._drivers = drivers;
this._stimuli = stimuli;
}

public abstract Update(deltaT: number): void;
}

export default Behavior;
37 changes: 37 additions & 0 deletions fission/src/systems/simulation/behavior/GenericArmBehavior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import HingeDriver from "../driver/HingeDriver";
import HingeStimulus from "../stimulus/HingeStimulus";
import Behavior from "./Behavior";
import InputSystem, { emptyModifierState } from "@/systems/input/InputSystem";

class GenericArmBehavior extends Behavior {
private _hingeDriver: HingeDriver;

private _positiveInput: string;
private _negativeInput: string;

private _rotationalSpeed = 30;

constructor(hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, jointIndex: number) {
super([hingeDriver], [hingeStimulus]);
this._hingeDriver = hingeDriver;

this._positiveInput = "jointPositive" + jointIndex;
this._negativeInput = "jointNegative" + jointIndex;

// TODO: load inputs from mira
InputSystem.allInputs[this._positiveInput] = { name: this._positiveInput, keybind: jointIndex.toString(), isGlobal: true, modifiers: emptyModifierState };
InputSystem.allInputs[this._negativeInput] = { name: this._negativeInput, keybind: jointIndex.toString(), isGlobal: true,
modifiers: { ctrl: false, alt: true, shift: false, meta: false } };
}

// Sets the arms target rotational velocity
rotateArm(rotationalVelocity: number) {
this._hingeDriver.targetVelocity = rotationalVelocity;
}

public Update(_: number): void {
this.rotateArm(InputSystem.getAxis(this._positiveInput, this._negativeInput)*this._rotationalSpeed);
}
}

export default GenericArmBehavior;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import SliderDriver from "../driver/SliderDriver";
import SliderStimulus from "../stimulus/SliderStimulus";
import Behavior from "./Behavior";
import InputSystem, { emptyModifierState } from "@/systems/input/InputSystem";

class GenericElevatorBehavior extends Behavior {
private _sliderDriver: SliderDriver;

private _positiveInput: string;
private _negativeInput: string;

private _linearSpeed = 1;

constructor(sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, jointIndex: number) {
super([sliderDriver], [sliderStimulus]);
this._sliderDriver = sliderDriver;

this._positiveInput = "jointPositive" + jointIndex;
this._negativeInput = "jointNegative" + jointIndex;

// TODO: load inputs from mira
InputSystem.allInputs[this._positiveInput] = { name: this._positiveInput, keybind: jointIndex.toString(), isGlobal: true, modifiers: emptyModifierState };
InputSystem.allInputs[this._negativeInput] = { name: this._negativeInput, keybind: jointIndex.toString(), isGlobal: true,
modifiers: { ctrl: false, alt: true, shift: false, meta: false } };
}

// Changes the elevators target position
moveElevator(positionDelta: number) {
this._sliderDriver.targetPosition += positionDelta;
}

public Update(deltaT: number): void {
this.moveElevator(InputSystem.getAxis(this._positiveInput, this._negativeInput)*this._linearSpeed*deltaT);
}
}

export default GenericElevatorBehavior;
2 changes: 2 additions & 0 deletions fission/src/systems/simulation/driver/SliderDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Jolt from "@barclah/jolt-physics";
import Driver from "./Driver";
import { SIMULATION_PERIOD } from "@/systems/physics/PhysicsSystem";
import JOLT from "@/util/loading/JoltSyncLoader";
import InputSystem from "@/systems/input/InputSystem";

class SliderDriver extends Driver {

Expand Down Expand Up @@ -44,6 +45,7 @@ class SliderDriver extends Driver {
}

public Update(_: number): void {
this._targetPosition += ((InputSystem.getInput("sliderUp") ? 1 : 0) - (InputSystem.getInput("sliderDown") ? 1 : 0))*3;
this._constraint.SetTargetPosition(this._targetPosition);
}
}
Expand Down
11 changes: 3 additions & 8 deletions fission/src/systems/simulation/driver/WheelDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,16 @@ class WheelDriver extends Driver {
this._targetWheelSpeed = radsPerSec;
}

public get constraint(): Jolt.VehicleConstraint { return this._constraint }

public constructor(constraint: Jolt.VehicleConstraint) {
super();

this._constraint = constraint;
this._wheel = JOLT.castObject(this._constraint.GetWheel(0), JOLT.WheelWV);

console.log(`Wheel X: ${constraint.GetVehicleBody().GetCenterOfMassPosition().GetX().toFixed(5)}`);
if (constraint.GetVehicleBody().GetCenterOfMassPosition().GetX() < 0) {
this._targetWheelSpeed = 10.0;
} else {
this._targetWheelSpeed = 10.0;
}
}

public Update(_: number): void {
public Update(_: number): void {
this._wheel.SetAngularVelocity(this._targetWheelSpeed);
}
}
Expand Down
Loading
Loading