@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
314 lines (301 loc) • 8.91 kB
text/typescript
import {Object3D} from 'three';
import {ref} from '../../core/reactivity/CoreReactivity';
import {Ref} from '@vue/reactivity';
import {ObjectNamedFunction0, ObjectNamedFunction1} from './_Base';
type EventFunction = () => void;
interface onEvent {
forward: EventFunction;
backward: EventFunction;
left: EventFunction;
right: EventFunction;
jump: EventFunction;
run: EventFunction;
}
interface onStartEndEvents {
start: onEvent;
end: onEvent;
}
// type AllowedKeyCode = 'ArrowUp'|'ArrowDown'|'ArrowLeft'|'ArrowRight'|'KeyW'|'KeyS'|'KeyA'|'KeyD'
interface ArrowEvents {
ArrowUp: EventFunction;
ArrowDown: EventFunction;
ArrowLeft: EventFunction;
ArrowRight: EventFunction;
}
interface WASDEvents {
KeyW: EventFunction;
KeyS: EventFunction;
KeyA: EventFunction;
KeyD: EventFunction;
}
interface JumpRunEvents {
ShiftLeft: EventFunction;
ShiftRight: EventFunction;
Space: EventFunction;
}
interface JumpRunEvents {
ShiftLeft: EventFunction;
ShiftRight: EventFunction;
Space: EventFunction;
}
interface CorePlayerInputDataRef {
forward: Ref<boolean>;
backward: Ref<boolean>;
left: Ref<boolean>;
right: Ref<boolean>;
run: Ref<boolean>;
jump: Ref<boolean>;
}
function _createInputData(): CorePlayerInputDataRef {
return {
forward: ref(false),
backward: ref(false),
left: ref(false),
right: ref(false),
run: ref(false),
jump: ref(false),
};
}
class InputDataHandler {
public readonly _playerInputData = _createInputData();
// public useWASDkeys = true;
// public useArrowkeys = true;
callback(eventType: 'keydown' | 'keyup') {
return this._callbackByEventType[eventType];
}
private _callbackByEventType = {
keydown: (code: string) => this._onKeydownCallback(code),
keyup: (code: string) => this._onKeyupCallback(code),
};
private _onKeydownCallback(keyCode: string): EventFunction | undefined {
const jumpRunKeyCallback = this._runJumpEventByKeyOnkeydown[keyCode as keyof JumpRunEvents];
if (jumpRunKeyCallback) {
return jumpRunKeyCallback;
}
// if (isBooleanTrue(this.useWASDkeys)) {
const wasdKeyCallback = this._eventByWASNKeyOnKeydown[keyCode as keyof WASDEvents];
if (wasdKeyCallback) {
return wasdKeyCallback;
}
// }
// if (isBooleanTrue(this.useArrowkeys)) {
const arrowKeyCallback = this._eventByArrowKeyOnKeydown[keyCode as keyof ArrowEvents];
if (arrowKeyCallback) {
return arrowKeyCallback;
}
// }
}
private _onKeyupCallback(keyCode: string): EventFunction | undefined {
const jumpRunKeyCallback = this._runJumpEventByKeyOnkeyup[keyCode as keyof JumpRunEvents];
if (jumpRunKeyCallback) {
return jumpRunKeyCallback;
}
// if (isBooleanTrue(this.useWASDkeys)) {
const wasdKeyCallback = this._eventByWASNKeyOnKeyup[keyCode as keyof WASDEvents];
if (wasdKeyCallback) {
return wasdKeyCallback;
}
// }
// if (isBooleanTrue(this.useArrowkeys)) {
const arrowKeyCallback = this._eventByArrowKeyOnKeyup[keyCode as keyof ArrowEvents];
if (arrowKeyCallback) {
return arrowKeyCallback;
}
// }
}
private _onEvent: onStartEndEvents = {
start: {
forward: this._onForwardStart.bind(this),
backward: this._onBackwardStart.bind(this),
left: this._onLeftStart.bind(this),
right: this._onRightStart.bind(this),
jump: this._onJumpStart.bind(this),
run: this._onRunStart.bind(this),
},
end: {
forward: this._onForwardEnd.bind(this),
backward: this._onBackwardEnd.bind(this),
left: this._onLeftEnd.bind(this),
right: this._onRightEnd.bind(this),
jump: this._onJumpEnd.bind(this),
run: this._onRunEnd.bind(this),
},
};
private _eventByArrowKeyOnKeydown: ArrowEvents = {
ArrowUp: this._onEvent.start.forward,
ArrowDown: this._onEvent.start.backward,
ArrowLeft: this._onEvent.start.left,
ArrowRight: this._onEvent.start.right,
};
private _eventByWASNKeyOnKeydown: WASDEvents = {
KeyW: this._onEvent.start.forward,
KeyS: this._onEvent.start.backward,
KeyA: this._onEvent.start.left,
KeyD: this._onEvent.start.right,
};
private _eventByArrowKeyOnKeyup: ArrowEvents = {
ArrowUp: this._onEvent.end.forward,
ArrowDown: this._onEvent.end.backward,
ArrowLeft: this._onEvent.end.left,
ArrowRight: this._onEvent.end.right,
};
private _eventByWASNKeyOnKeyup: WASDEvents = {
KeyW: this._onEvent.end.forward,
KeyS: this._onEvent.end.backward,
KeyA: this._onEvent.end.left,
KeyD: this._onEvent.end.right,
};
private _runJumpEventByKeyOnkeydown: JumpRunEvents = {
ShiftLeft: this._onEvent.start.run,
ShiftRight: this._onEvent.start.run,
Space: this._onEvent.start.jump,
};
private _runJumpEventByKeyOnkeyup: JumpRunEvents = {
ShiftLeft: this._onEvent.end.run,
ShiftRight: this._onEvent.end.run,
Space: this._onEvent.end.jump,
};
private _onForwardStart() {
this._playerInputData.forward.value = true;
}
private _onBackwardStart() {
this._playerInputData.backward.value = true;
}
private _onLeftStart() {
this._playerInputData.left.value = true;
}
private _onRightStart() {
this._playerInputData.right.value = true;
}
private _onJumpStart() {
this._playerInputData.jump.value = true;
}
private _onRunStart() {
this._playerInputData.run.value = true;
}
private _onForwardEnd() {
this._playerInputData.forward.value = false;
}
private _onBackwardEnd() {
this._playerInputData.backward.value = false;
}
private _onLeftEnd() {
this._playerInputData.left.value = false;
}
private _onRightEnd() {
this._playerInputData.right.value = false;
}
private _onJumpEnd() {
this._playerInputData.jump.value = false;
}
private _onRunEnd() {
this._playerInputData.run.value = false;
}
}
const _inputDataByObject3D: WeakMap<Object3D, InputDataHandler> = new WeakMap();
function _findOrCreateHandler(object3D: Object3D): InputDataHandler {
let inputData = _inputDataByObject3D.get(object3D);
if (inputData) {
return inputData;
}
inputData = new InputDataHandler();
_inputDataByObject3D.set(object3D, inputData);
return inputData;
}
// interface OnPlayerEventOptions {
// // stopPropagation: boolean;
// // useWASDkeys: boolean;
// // useArrowkeys: boolean;
// }
// export interface OnPlayerEventOptionsString {
// // stopPropagation: string;
// // useWASDkeys: string;
// // useArrowkeys: string;
// }
export class setPlayerInput extends ObjectNamedFunction1<[boolean]> {
static override type() {
return 'setPlayerInput';
}
func(object3D: Object3D, stopEventsPropagation: boolean): void {
// const {stopPropagation, useWASDkeys, useArrowkeys} = options;
const events = this.scene.eventsDispatcher.keyboardEventsController.currentEvents();
if (events.length == 0) {
return;
}
// console.log(
// events.map((e) => e.type),
// events.map((e) => e.code)
// );
const handler = _findOrCreateHandler(object3D);
// handler.useWASDkeys = useWASDkeys;
// handler.useArrowkeys = useArrowkeys;
for (let event of events) {
if (event.ctrlKey) {
// if ctrl is pressed, we do not register any event.
// this is mostly to allow Ctrl+S to work without triggering a player movement
return;
}
const callbackMethod = handler.callback(event.type as 'keydown' | 'keyup');
if (!callbackMethod) {
return;
}
const callback = callbackMethod(event.code);
if (callback) {
callback();
if (stopEventsPropagation == true) {
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
}
}
}
}
}
export class getPlayerInputDataLeft extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataLeft';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.left.value;
}
}
export class getPlayerInputDataRight extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataRight';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.right.value;
}
}
export class getPlayerInputDataForward extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataForward';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.forward.value;
}
}
export class getPlayerInputDataBackward extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataBackward';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.backward.value;
}
}
export class getPlayerInputDataRun extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataRun';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.run.value;
}
}
export class getPlayerInputDataJump extends ObjectNamedFunction0 {
static override type() {
return 'getPlayerInputDataJump';
}
func(object3D: Object3D): boolean {
return _findOrCreateHandler(object3D)._playerInputData.jump.value;
}
}