Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

@croquet/worldcore-kernel

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@croquet/worldcore-kernel - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

24

CHANGELOG.md

@@ -7,2 +7,23 @@ # Changelog

## [1.3.0] - 2022-6-16
### Changed
- Parent/child relationships are included in the base functionality of Actors and Pawns
- Actors aren't required to have Pawns
- PM_Dynamic rolled into base Pawn class.
- Pawns have a throttle parameter in their say() method by default.
- The event published by Actor set() is "propertySet" instead of "_property".
- q_equals() defaults to epsilon = 0;
## Fixed
- InputManager generates pointerDelta events during a drag.
### Added
- Pawn set() -- you can set actor options from the Pawn.
- PlayerManager destroyPlayer() -- override to customize player destruction
- PM_Driver mixin
### Removed
- PM_MouselookAvatar mixin
## [1.2.0] - 2022-4-20

@@ -69,1 +90,4 @@ ### Added

## Pending

6

package.json
{
"name": "@croquet/worldcore-kernel",
"version": "1.2.0",
"version": "1.3.0",
"description": "3D World Engine for Croquet (minimal install)",

@@ -31,3 +31,3 @@ "keywords": [

"dependencies": {
"@croquet/croquet": "^1.1.0-9"
"@croquet/croquet": "^1.1.0-12"
},

@@ -37,3 +37,3 @@ "publishConfig": {

},
"gitHead": "7633b5da452e79cee2be15721d744e4cd9f9924c"
"gitHead": "d5e33664baaaa1a3a153e0aa3721ad3a17c25dc3"
}

@@ -38,7 +38,10 @@ import { Pawn } from "./Pawn";

export class Actor extends WorldcoreModel {
get pawn() {return Pawn}
get pawn() {return null;}
get doomed() {return this._doomed} // About to be destroyed. This is used to prevent creating new future messages.
get parent() { return this._parent; }
init(options) {
super.init();
this.listen("parentSet", this.onParent);
this.listen("_set", this.set);

@@ -51,2 +54,4 @@ this.set(options);

destroy() {
new Set(this.children).forEach(child => child.destroy());
this.set({parent: null});
this._doomed = true; // About to be destroyed. This is used to prevent creating new future messages.

@@ -58,20 +63,7 @@ this.say("destroyActor");

// Different implementations of javascript may store object properties in different orders, so we sort them
// so they are always processed alphabetically
// set(options = {}, prefix = '') {
// const sorted = Object.entries(options).sort((a,b) => { return b[0] < a[0] ? 1 : -1 } );
// for (const option of sorted) {
// const n = "_" + option[0];
// const v = option[1];
// const o = this[n];
// this[n] = v;
// this.say(prefix+n, {v, o}); // Publish a local message whenever a property changes with its old and new value.
// }
// }
set(options = {}) {
const sorted = Object.entries(options).sort((a,b) => { return b[0] < a[0] ? 1 : -1 } );
for (const option of sorted) {
const name = option[0];
const setEvent = name + "Set";
const n = "_" + option[0];

@@ -81,6 +73,20 @@ const v = option[1];

this[n] = v;
this.say(n, {v, o}); // Publish a local message whenever a property changes with its old and new value.
this.say(setEvent, {v, o}); // Publish a local message whenever a property changes with its old and new value.
}
}
addChild(child) {
if (!this.children) this.children = new Set();
this.children.add(child);
}
removeChild(child) {
if (this.children) this.children.delete(child);
}
onParent(d) {
if (d.o) d.o.removeChild(this);
if (d.v) d.v.addChild(this);
}
say(event, data) {

@@ -87,0 +93,0 @@ this.publish(this.id, event, data);

@@ -58,2 +58,3 @@ import { v2_sub, v2_add, v2_scale, v2_magnitude, TAU, toRad, toDeg } from "./Vector";

this.synthesizedModifierKeys = new Map();
}

@@ -215,2 +216,21 @@

modifierKeysFrom(event) {
let {altKey, ctrlKey, metaKey, shiftKey} = event;
altKey = !!(altKey || this.synthesizedModifierKeys.get("altKey"));
ctrlKey = !!(ctrlKey || this.synthesizedModifierKeys.get("ctrlKey"));
metaKey = !!(metaKey || this.synthesizedModifierKeys.get("metaKey"));
shiftKey = !!(shiftKey || this.synthesizedModifierKeys.get("shiftKey"));
return {altKey, ctrlKey, metaKey, shiftKey};
}
setModifierKeys(obj) {
for (let k in obj) {
this.synthesizedModifierKeys.set(k, !!obj[k])
}
}
modifierEqual(e1, e2) {
return !!e1.altKey === !!e2.altKey && !!e1.ctrlKey === !!e2.ctrlKey && !!e1.metaKey === !!e2.metaKey && !!e1.shiftKey === !!e2.shiftKey;
}
enterPointerLock() {

@@ -255,10 +275,11 @@ if (this.inPointerLock) return;

const key = event.key;
let modKeys = this.modifierKeysFrom(event);
keys.add(key);
if (event.repeat) {
this.publish("input", key + "Repeat", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", "keyRepeat", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", key + "Repeat", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, ...modKeys});
this.publish("input", "keyRepeat", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, ...modKeys});
// This can generate a lot of events! Don't subscribe to in model.
} else {
this.publish("input", key + "Down", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", "keyDown", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", key + "Down", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, ...modKeys});
this.publish("input", "keyDown", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, ...modKeys});
this.onChordDown(key);

@@ -271,5 +292,6 @@ }

const key = event.key;
let modKeys = this.modifierKeysFrom(event);
if (!KeyDown(key)) return;
this.publish("input", key + "Up", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", "keyUp", {key, shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey});
this.publish("input", key + "Up", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, ...modKeys});
this.publish("input", "keyUp", {key, shift: modKeys.shiftKey, alt: modKeys.altKey, ctrl: modKeys.ctrlKey, meta: modKeys.metaKey, modKeys});
keys.delete(key);

@@ -280,18 +302,20 @@ this.onChordUp(key);

onClick(event) {
let modKeys = this.modifierKeysFrom(event);
window.focus();
this.publish("input", "click", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "click", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
}
onPointerDown(event) {
this.presses.set(event.pointerId, {id: event.pointerId, time: event.timeStamp, start: [event.clientX, event.clientY], xy: [event.clientX, event.clientY]});
this.publish("input", "pointerDown", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
if (event.button === this.lastDown.button && event.timeStamp - this.lastDown.time < DOUBLE_DURATION) {
if (event.button === this.penultimateDown.button && event.timeStamp - this.penultimateDown.time < TRIPLE_DURATION) {
this.publish("input", "tripleDown", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
let modKeys = this.modifierKeysFrom(event);
this.presses.set(event.pointerId, {id: event.pointerId, time: event.timeStamp, start: [event.clientX, event.clientY], ...modKeys, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerDown", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
if (event.button === this.lastDown.button && event.timeStamp - this.lastDown.time < DOUBLE_DURATION && this.modifierEqual(event, this.lastDown)) {
if (event.button === this.penultimateDown.button && event.timeStamp - this.penultimateDown.time < TRIPLE_DURATION) {
this.publish("input", "tripleDown", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
} else {
this.publish("input", "doubleDown", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "doubleDown", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
}
}
this.penultimateDown = this.lastDown;
this.lastDown = {id: event.pointerId, button: event.button, time: event.timeStamp}
this.lastDown = {id: event.pointerId, button: event.button, buttons: event.buttons, ...modKeys, time: event.timeStamp};
this.zoomStart();

@@ -302,2 +326,3 @@ }

const press = this.presses.get(event.pointerId);
let modKeys = this.modifierKeysFrom(event);
if (press) {

@@ -311,9 +336,9 @@ press.xy = [event.clientX, event.clientY];

if (duration < TAP_DURATION && ax < TAP_DISTANCE && ay < TAP_DISTANCE) {
this.publish("input", "tap", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "tap", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
}
if (duration < SWIPE_DURATION && ax > SWIPE_DISTANCE) {
this.publish("input", "swipeX", {id: event.pointerId, type: event.pointerType, button: event.button, distance: dx});
this.publish("input", "swipeX", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, distance: dx, ...modKeys});
}
if (duration < SWIPE_DURATION && ay > SWIPE_DISTANCE) {
this.publish("input", "swipeY", {id: event.pointerId, type: event.pointerType, button: event.button, distance: dy});
this.publish("input", "swipeY", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, distance: dy, ...modKeys});
}

@@ -323,3 +348,3 @@ }

this.presses.delete(event.pointerId);
this.publish("input", "pointerUp", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerUp", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
this.zoomEnd();

@@ -330,2 +355,3 @@ }

const press = this.presses.get(event.pointerId);
let modKeys = this.modifierKeysFrom(event);
if (press) {

@@ -339,7 +365,8 @@ press.xy = [event.clientX, event.clientY];

if (duration > TAP_DURATION || ax > TAP_DISTANCE || ay > TAP_DISTANCE) { // Only publish pressed move events that aren't taps
this.publish("input", "pointerMove", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerMove", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerDelta", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.movementX, event.movementY]});
}
} else {
this.publish("input", "pointerMove", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerDelta", {id: event.pointerId, type: event.pointerType, button: event.button, xy: [event.movementX, event.movementY]});
this.publish("input", "pointerMove", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.clientX, event.clientY]});
this.publish("input", "pointerDelta", {id: event.pointerId, type: event.pointerType, button: event.button, buttons: event.buttons, ...modKeys, xy: [event.movementX, event.movementY]});
}

@@ -390,5 +417,6 @@ this.zoomUpdate();

onWheel(event) {
let modKeys = this.modifierKeysFrom(event);
event.preventDefault();
const y = event.deltaY;
this.publish("input", "wheel", {deltaY: y, xy: [event.clientX, event.clientY]});
this.publish("input", "wheel", {deltaY: y, ...modKeys, xy: [event.clientX, event.clientY]});
}

@@ -395,0 +423,0 @@

import { Constants } from "@croquet/croquet";
import { m4_identity } from "..";
// import { Constants } from "@croquet/worldcore-kernel";
import { PM_Dynamic, GetPawn } from "./Pawn";
// import { GetPawn } from "./Pawn";
import { v3_zero, q_identity, v3_unit, m4_scaleRotationTranslation, m4_translation, m4_rotationX, m4_multiply, v3_lerp, v3_equals,

@@ -103,96 +103,6 @@ q_slerp, q_equals, v3_isZero, q_isZero, q_normalize, q_multiply, v3_add, v3_scale, m4_rotationQ, v3_transform, q_euler, TAU, clampRad, q_axisAngle } from "./Vector";

//------------------------------------------------------------------------------------------
//-- Tree ----------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Tree actors can be put in a hierarchy with parents and children. The tree pawns maintain
// their own hierarchy that mirrors the actor hierarchy.
//-- Actor ---------------------------------------------------------------------------------
export const AM_Tree = superclass => class extends superclass {
init(...args) {
this.listen("_parent", this.onChangeParent);
super.init(...args);
}
destroy() {
new Set(this.children).forEach(child => child.destroy());
this.set({parent: null});
super.destroy();
}
onChangeParent(d) {
if (d.o) d.o.removeChild(this);
if (d.v) d.v.addChild(this);
}
get parent() { return this._parent; }
addChild(c) { // This should never be called directly, use set instead
if (!this.children) this.children = new Set();
this.children.add(c);
}
removeChild(c) { // This should never be called directly, use set instead
if (this.children) this.children.delete(c);
}
};
RegisterMixin(AM_Tree);
//-- Pawn ----------------------------------------------------------------------------------
export const PM_Tree = superclass => class extends superclass {
constructor(...args) {
super(...args);
if (this.actor.parent) {
const parent = GetPawn(this.actor.parent.id);
parent.addChild(this.actor.id);
}
this.listen("_parent", this.onChangeParent);
}
get parent() {
if (this.actor.parent && !this._parent) this._parent = GetPawn(this.actor.parent.id);
return this._parent;
}
get children() {
if (this.actor.children && !this._children) this.actor.children.forEach(child => { this.addChild(child.id); })
return this._children;
}
onChangeParent(d) {
if (d.o) {
GetPawn(d.o.id).removeChild(this.actor.id);
}
if (d.v) {
GetPawn(d.v.id).addChild(this.actor.id);
}
}
addChild(id) {
const child = GetPawn(id);
if (!child) return;
if (!this._children) this._children = new Set();
this._children.add(child);
child._parent = this;
}
removeChild(id) {
const child = GetPawn(id);
if (!child) return;
if (this._children) this._children.delete(child);
child._parent = null;
}
};
//------------------------------------------------------------------------------------------
//-- Spatial -------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Spatial actors have a translation, rotation and scale in 3D space. They inherit from Tree
// so they also maintain a hierarchy of transforms.
// Spatial actors have a translation, rotation and scale in 3D space.
//

@@ -204,9 +114,9 @@ // They don't have any view-side smoothing, so the pawn will change its transform to exactly

export const AM_Spatial = superclass => class extends AM_Tree(superclass) {
export const AM_Spatial = superclass => class extends superclass {
init(options) {
super.init(options);
this.listen("_scale", this.localChanged);
this.listen("_rotation", this.localChanged);
this.listen("_translation", this.localChanged);
this.listen("scaleSet", this.localChanged);
this.listen("rotationSet", this.localChanged);
this.listen("translationSet", this.localChanged);
}

@@ -255,3 +165,3 @@

export const PM_Spatial = superclass => class extends PM_Tree(superclass) {
export const PM_Spatial = superclass => class extends superclass {

@@ -288,2 +198,10 @@ constructor(...args) {

init(...args) {
super.init(...args);
this.listen("_scaleTo", this.scaleTo);
this.listen("_rotateTo", this.rotateTo);
this.listen("_translateTo", this.translateTo);
this.listen("_positionTo", this.positionTo);
}
scaleTo(v) {

@@ -293,3 +211,3 @@ this._scale = v;

this.$global = null;
this.say("scaling");
this.say("scaleTo", v);
}

@@ -301,3 +219,3 @@

this.$global = null;
this.say("rotating");
this.say("rotateTo", q);
}

@@ -309,5 +227,15 @@

this.$global = null;
this.say("translating");
this.say("translateTo", v);
}
positionTo(data) {
this._translation = data.v;
this._rotation = data.q;
this.$local = null;
this.$global = null;
this.say("rotateTo", data.q);
this.say("translateTo", data.v);
}
moveTo(v) { this.translateTo(v)}

@@ -327,6 +255,4 @@

const DynamicSpatial = superclass => PM_Dynamic(PM_Spatial(superclass)); // Merge dynamic and spatial base mixins
export const PM_Smoothed = superclass => class extends PM_Spatial(superclass) {
export const PM_Smoothed = superclass => class extends DynamicSpatial(superclass) {
constructor(...args) {

@@ -341,18 +267,18 @@ super(...args);

this.listenOnce("_scale", this.onScaleSet);
this.listenOnce("scaling", () => this.scaling = true)
this.listenOnce("scaleSet", this.onScaleSet);
this.listenOnce("rotationSet", this.onRotationSet);
this.listenOnce("translationSet", this.onTranslationSet);
this.listenOnce("_rotation", this.onRotationSet);
this.listenOnce("rotating", () => this.rotating = true)
this.listenOnce("_translation", this.onTranslationSet);
this.listenOnce("translating", () => this.translating = true)
this.listenOnce("scaleTo", this.onScaleTo);
this.listenOnce("rotateTo", this.onRotateTo);
this.listenOnce("translateTo", this.onTranslateTo);
}
set tug(t) {this._tug = t}
get tug() { return this._tug; }
get tug() { return this._tug; }
set localOffset(m4) {
this._localOffset = m4;
this.onLocalChanged();
this._local = null;
this._global = null;
}

@@ -365,2 +291,27 @@ get localOffset() { return this._localOffset; }

onLocalChanged(){
this._local = null;
this.onGlobalChanged();
}
onGlobalChanged(){
this._global = null;
}
scaleTo(v, throttle) {
this.say("_scaleTo", v, throttle)
}
rotateTo(q, throttle) {
this.say("_rotateTo", q, throttle)
}
translateTo(v, throttle) {
this.say("_translateTo", v, throttle)
}
positionTo(v, q, throttle) {
this.say("_positionTo", {v,q}, throttle)
}
onScaleSet() {

@@ -381,11 +332,6 @@ this._scale = this.actor.scale;

onLocalChanged() {
this._local = null;
this._global = null;
}
onScaleTo(q) { this.isScaling = true; }
onRotateTo(q) { this.isRotating = true; }
onTranslateTo(v) { this.isTranslating = true; }
onGlobalChanged() {
this._global = null;
}
get local() {

@@ -408,3 +354,2 @@ if (this._local) return this. _local;

}
this.say("viewGlobalChanged");
return this._global;

@@ -419,33 +364,48 @@ }

if (!this.scaling || v3_equals(this._scale, this.actor.scale, .0001)) {
this.scaling = false;
} else {
this._scale = v3_lerp(this._scale, this.actor.scale, tug);
if (this.isScaling) {
if (v3_equals(this._scale, this.actor.scale, .0001)) {
this._scale = this.actor.scale;
this.isScaling = false;
} else {
this._scale = v3_lerp(this._scale, this.actor.scale, tug);
}
this.onLocalChanged();
}
if (!this.rotating || q_equals(this._rotation, this.actor.rotation, 0.000001)) {
this.rotating = false;
} else {
this._rotation = q_slerp(this._rotation, this.actor.rotation, tug);
if (this.isRotating) {
if (q_equals(this._rotation, this.actor.rotation, 0.000001)) {
this._rotation = this.actor.rotation;
this.isRotating = false;
} else {
this._rotation = q_slerp(this._rotation, this.actor.rotation, tug);
}
this.onLocalChanged();
}
if (!this.translating || v3_equals(this._translation, this.actor.translation, .0001)) {
this.translating = false;
} else {
this._translation = v3_lerp(this._translation, this.actor.translation, tug);
if (this.isRotating) {
if (q_equals(this._rotation, this.actor.rotation, 0.000001)) {
this._rotation = this.actor.rotation;
this.isRotating = false;
} else {
this._rotation = q_slerp(this._rotation, this.actor.rotation, tug);
}
this.onLocalChanged();
}
if (this.isTranslating) {
if (v3_equals(this._translation, this.actor.translation, .0001)) {
this._translation = this.actor.translation;
this.isTranslating = false;
} else {
this._translation = v3_lerp(this._translation, this.actor.translation, tug);
}
this.onLocalChanged();
}
if (!this._global) {
this.global;
if (this.children) this.children.forEach(child => child._global = null); // If our global changes, so do the globals of our children
this.say("viewGlobalChanged");
if (this.children) this.children.forEach(child => child.onGlobalChanged()); // If our global changes, so do the globals of our children
}
}
postUpdate(time, delta) {
super.postUpdate(time, delta);
if (this.children) this.children.forEach(child => child.fullUpdate(time, delta));
}

@@ -456,2 +416,106 @@

//------------------------------------------------------------------------------------------
//-- PM_SmoothedDriver ---------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// This version of PM_Smoothed sets the transform values instantly on the local pawn and only implements smoothing on other clients.
// export const PM_SmoothedDriver = superclass => class extends PM_Smoothed(superclass) {
// constructor(...args) {
// super(...args);
// this.throttle = 100; //ms
// this.ignore("scaleSet");
// this.ignore("rotationSet");
// this.ignore("translationSet");
// this.ignore("positionSet");
// }
// positionTo(v, q, throttle) {
// throttle = throttle || this.throttle;
// this._translation = v;
// this._rotation = q;
// this.isTranslating = false;
// this.isRotating = false;
// this.onLocalChanged();
// super.positionTo(v, q, throttle);
// }
// scaleTo(v, throttle) {
// throttle = throttle || this.throttle;
// this._scale = v;
// this.isScaling = false;
// this.onLocalChanged();
// super.scaleTo(v, throttle);
// }
// rotateTo(q, throttle) {
// throttle = throttle || this.throttle;
// this._rotation = q;
// this.isRotating = false;
// this.onLocalChanged();
// super.rotateTo(q, throttle);
// }
// translateTo(v, throttle) {
// throttle = throttle || this.throttle;
// this._translation = v;
// this.isTranslating = false;
// this.onLocalChanged();
// super.translateTo(v, throttle);
// }
// }
//------------------------------------------------------------------------------------------
//-- PM_Driver -----------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// You can add this to a PM_Smoothed pawn to make it more responsive to direct user input.
// Transform values are set instantly on the local pawn and smoothing only happens on remote instances.
export const PM_Driver = superclass => class extends superclass {
constructor(...args) {
super(...args);
this.throttle = 100; //ms
}
positionTo(v, q, throttle) {
throttle = throttle || this.throttle;
this._translation = v;
this._rotation = q;
this.isTranslating = false;
this.isRotating = false;
this.onLocalChanged();
super.positionTo(v, q, throttle);
}
scaleTo(v, throttle) {
throttle = throttle || this.throttle;
this._scale = v;
this.isScaling = false;
this.onLocalChanged();
super.scaleTo(v, throttle);
}
rotateTo(q, throttle) {
throttle = throttle || this.throttle;
this._rotation = q;
this.isRotating = false;
this.onLocalChanged();
super.rotateTo(q, throttle);
}
translateTo(v, throttle) {
throttle = throttle || this.throttle;
this._translation = v;
this.isTranslating = false;
this.onLocalChanged();
super.translateTo(v, throttle);
}
}
//------------------------------------------------------------------------------------------
//-- Predictive ----------------------------------------------------------------------------

@@ -480,9 +544,2 @@ //------------------------------------------------------------------------------------------

super.init(...args);
this.listen("scaleTo", this.scaleTo);
this.listen("rotateTo", this.rotateTo);
this.listen("translateTo", this.translateTo);
this.listen("setVelocity", this.setVelocity);
this.listen("setSpin", this.setSpin);
this.listen("setVelocitySpin", this.setVelocitySpin);
this.future(0).tick(0);

@@ -503,11 +560,2 @@ }

setVelocity(v) { this._velocity = v; }
setSpin(q) { this._spin = q; }
setVelocitySpin(vq){
this._velocity = vq[0];
this._spin = vq[1];
}
};

@@ -526,35 +574,12 @@ RegisterMixin(AM_Predictive);

scaleTo(v, throttle) {
this.say("scaleTo", v, throttle)
this.onLocalChanged();
}
rotateTo(q, throttle) {
this.say("rotateTo", q, throttle)
this.onLocalChanged();
}
translateTo(v, throttle) {
this.say("translateTo", v, throttle)
this.onLocalChanged();
}
moveTo(v, throttle) {this.translateTo(v,throttle); }
setVelocity(v, throttle) {
this.say("setVelocity", v, throttle)
this.onLocalChanged();
this.set({velocity: v}, throttle)
}
setSpin(q, throttle) {
this.say("setSpin", q, throttle)
this.onLocalChanged();
this.set({spin: q}, throttle)
}
setVelocitySpin(vq, throttle){
this.say("setVelocitySpin", vq, throttle);
this.onLocalChanged();
}
update(time, delta) {

@@ -564,4 +589,3 @@

this._rotation = q_normalize(q_slerp(this._rotation, q_multiply(this._rotation, this.spin), delta));
this._local = null;
this._global = null;
this.onLocalChanged();
}

@@ -573,4 +597,3 @@

this._translation = v3_add(this._translation, move);
this._local = null;
this._global = null;
this.onLocalChanged();
}

@@ -597,93 +620,93 @@ super.update(time, delta);

//-- Actor ---------------------------------------------------------------------------------
// //-- Actor ---------------------------------------------------------------------------------
export const AM_MouselookAvatar = superclass => class extends AM_Avatar(superclass) {
// export const AM_MouselookAvatar = superclass => class extends AM_Avatar(superclass) {
init(...args) {
this.listen("avatarLookTo", this.onLookTo);
super.init(...args);
this.set({rotation: q_euler(0, this.lookYaw, 0)});
}
// init(...args) {
// this.listen("avatarLookTo", this.onLookTo);
// super.init(...args);
// this.set({rotation: q_euler(0, this.lookYaw, 0)});
// }
get lookPitch() { return this._lookPitch || 0 };
get lookYaw() { return this._lookYaw || 0 };
// get lookPitch() { return this._lookPitch || 0 };
// get lookYaw() { return this._lookYaw || 0 };
onLookTo(e) {
this.set({lookPitch: e[0], lookYaw: e[1]});
this.rotateTo(q_euler(0, this.lookYaw, 0));
}
// onLookTo(e) {
// this.set({lookPitch: e[0], lookYaw: e[1]});
// this.rotateTo(q_euler(0, this.lookYaw, 0));
// }
}
RegisterMixin(AM_MouselookAvatar);
// }
// RegisterMixin(AM_MouselookAvatar);
//-- Pawn ---------------------------------------------------------------------------------
// //-- Pawn ---------------------------------------------------------------------------------
export const PM_MouselookAvatar = superclass => class extends PM_Avatar(superclass) {
// export const PM_MouselookAvatar = superclass => class extends PM_Avatar(superclass) {
constructor(...args) {
super(...args);
// constructor(...args) {
// super(...args);
this._lookPitch = this.actor.lookPitch;
this._lookYaw = this.actor.lookYaw;
// this._lookPitch = this.actor.lookPitch;
// this._lookYaw = this.actor.lookYaw;
this.lookThrottle = 50; // MS between throttled lookTo events
this.lastlookTime = this.time;
// this.lookThrottle = 50; // MS between throttled lookTo events
// this.lastlookTime = this.time;
this.lookOffset = [0,0,0]; // Vector displacing the camera from the avatar origin.
}
// this.lookOffset = [0,0,0]; // Vector displacing the camera from the avatar origin.
// }
get lookPitch() { return this._lookPitch}
get lookYaw() { return this._lookYaw}
// get lookPitch() { return this._lookPitch}
// get lookYaw() { return this._lookYaw}
lookTo(pitch, yaw) {
this.setLookAngles(pitch, yaw);
this.lastLookTime = this.time;
this.lastLookCache = null;
this.say("avatarLookTo", [pitch, yaw]);
this.say("lookGlobalChanged");
}
// lookTo(pitch, yaw) {
// this.setLookAngles(pitch, yaw);
// this.lastLookTime = this.time;
// this.lastLookCache = null;
// this.say("avatarLookTo", [pitch, yaw]);
// this.say("lookGlobalChanged");
// }
throttledLookTo(pitch, yaw) {
pitch = Math.min(Math.PI/2, Math.max(-Math.PI/2, pitch));
yaw = clampRad(yaw);
if (this.time < this.lastLookTime + this.lookThrottle) {
this.setLookAngles(pitch, yaw);
this.lastLookCache = {pitch, yaw};
} else {
this.lookTo(pitch,yaw);
}
}
// throttledLookTo(pitch, yaw) {
// pitch = Math.min(Math.PI/2, Math.max(-Math.PI/2, pitch));
// yaw = clampRad(yaw);
// if (this.time < this.lastLookTime + this.lookThrottle) {
// this.setLookAngles(pitch, yaw);
// this.lastLookCache = {pitch, yaw};
// } else {
// this.lookTo(pitch,yaw);
// }
// }
setLookAngles(pitch, yaw) {
this._lookPitch = pitch;
this._lookYaw = yaw;
this._rotation = q_euler(0, yaw, 0);
}
// setLookAngles(pitch, yaw) {
// this._lookPitch = pitch;
// this._lookYaw = yaw;
// this._rotation = q_euler(0, yaw, 0);
// }
get lookGlobal() {
const pitchRotation = q_axisAngle([1,0,0], this.lookPitch);
const yawRotation = q_axisAngle([0,1,0], this.lookYaw);
// get lookGlobal() {
// const pitchRotation = q_axisAngle([1,0,0], this.lookPitch);
// const yawRotation = q_axisAngle([0,1,0], this.lookYaw);
const modelLocal = m4_scaleRotationTranslation(this.scale, yawRotation, this.translation)
let modelGlobal = modelLocal;
if (this.parent) modelGlobal = m4_multiply(modelLocal, this.parent.global);
// const modelLocal = m4_scaleRotationTranslation(this.scale, yawRotation, this.translation)
// let modelGlobal = modelLocal;
// if (this.parent) modelGlobal = m4_multiply(modelLocal, this.parent.global);
const m0 = m4_translation(this.lookOffset);
const m1 = m4_rotationQ(pitchRotation);
const m2 = m4_multiply(m1, m0);
return m4_multiply(m2, modelGlobal);
}
// const m0 = m4_translation(this.lookOffset);
// const m1 = m4_rotationQ(pitchRotation);
// const m2 = m4_multiply(m1, m0);
// return m4_multiply(m2, modelGlobal);
// }
update(time, delta) {
super.update(time, delta);
// update(time, delta) {
// super.update(time, delta);
if (this.lastLookCache && this.time > this.lastLookTime + this.lookThrottle) {
this.lookTo(this.lastLookCache.pitch, this.lastLookCache.yaw);
}
// if (this.lastLookCache && this.time > this.lastLookTime + this.lookThrottle) {
// this.lookTo(this.lastLookCache.pitch, this.lastLookCache.yaw);
// }
}
// }
}
// }

@@ -15,3 +15,3 @@ /* eslint-disable new-cap */

this.pawns = new Map();
this.dynamic = new Set();
// this.dynamic = new Set();

@@ -31,41 +31,15 @@ const actorManager = this.modelService("ActorManager");

spawnPawn(actor) {
new actor.pawn(actor);
}
spawnPawn(actor) { if (actor.pawn) new actor.pawn(actor); }
add(pawn) { this.pawns.set(pawn.actor.id, pawn); }
has(id) { return this.pawns.has(id); }
get(id) { return this.pawns.get(id); }
delete(pawn) { this.pawns.delete(pawn.actor.id); }
add(pawn) {
this.pawns.set(pawn.actor.id, pawn);
}
has(id) {
return this.pawns.has(id);
}
get(id) {
return this.pawns.get(id);
}
delete(pawn) {
this.pawns.delete(pawn.actor.id);
}
addDynamic(pawn) {
this.dynamic.add(pawn);
}
deleteDynamic(pawn) {
this.dynamic.delete(pawn);
}
update(time, delta) {
this.dynamic.forEach( pawn => {
if (pawn.parent) return; // Child pawns get updated in their parent's postUpdate
pawn.fullUpdate(time, delta);
});
for(const pawn of this.pawns.values()) { if (!pawn.parent) pawn.fullUpdate(time, delta); };
}
}
export function GetPawn(actorId) { return pm.get(actorId); }
//------------------------------------------------------------------------------------------

@@ -79,5 +53,8 @@ //-- Pawn ----------------------------------------------------------------------------------

super(actor);
this._sayNext = {};
this._sayCache = {};
this._actor = actor;
pm.add(this);
this.listen("destroyActor", this.destroy);
this.listen("parentSet", this.onParent);
this.init();

@@ -96,5 +73,40 @@ }

get parent() {
if (this.actor.parent && !this._parent) this._parent = GetPawn(this.actor.parent.id);
return this._parent;
}
get children() {
if (this.actor.children && !this._children) this.actor.children.forEach(child => { this.addChild(child.id); })
return this._children;
}
addChild(id) {
const child = GetPawn(id);
if (!child) return;
if (!this._children) this._children = new Set();
this._children.add(child);
child._parent = this;
}
removeChild(id) {
const child = GetPawn(id);
if (!child) return;
if (this._children) this._children.delete(child);
child._parent = null;
}
onParent(d) {
if (d.o) GetPawn(d.o.id).removeChild(this.actor.id);
if (d.v) GetPawn(d.v.id).addChild(this.actor.id);
}
say(event, data, throttle = 0) {
if (throttle) console.warn("Only dynamic pawns can throttle 'say'!");
this.publish(this.actor.id, event, data);
if (this.time < this._sayNext[event]) {
this._sayCache[event] = data;
} else {
this._sayNext[event] = this.time + throttle;
this._sayCache[event] = null;
this.publish(this.actor.id, event, data);
}
}

@@ -118,57 +130,15 @@

// Creates a property in the pawn that will access a matching property in the actor.
// When the property is set in the actor, the pawn with set its matching property and call the onSet method
// definePawnProperty(name, onSet) {
// const ul = '_' + name;
// const v = this.actor[name];
// this[ul] = v;
// Object.defineProperty(this, name, { get: function() {return this[ul]} });
// if (onSet) onSet(v,null);
// this.listenOnce(ul, () => {
// const o = this[ul];
// const v = this.actor[name];
// this[ul] = this.actor[name];
// if (onSet) onSet(v,o);
// });
// }
}
//------------------------------------------------------------------------------------------
//-- PM_Dynamic ----------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Dynamic pawns get their update called every frame. Most stuff should go in update, but if there are operations
// that need to occur before or after everything else, you can overload pre- and post- update.
export const PM_Dynamic = superclass => class extends superclass {
constructor(...args) {
super(...args);
pm.addDynamic(this);
this._sayNext = {};
this._sayCache = {};
set(options, throttle = 0) {
this.say("_set", options, throttle);
}
destroy() {
pm.deleteDynamic(this);
super.destroy();
}
say(event, data, throttle = 0) {
if (this.time < this._sayNext[event]) {
this._sayCache[event] = data;
} else {
this._sayNext[event] = this.time + throttle;
this._sayCache[event] = null;
this.publish(this.actor.id, event, data);
}
}
preUpdate(time, delta) {} // Called immediately before the main update
update(time, delta) {}
postUpdate(time, delta){ // Called immediately after the main update.
postUpdate(time, delta){} // Called immediately after the main update.
fullUpdate(time, delta) {
this.preUpdate(time, delta);
this.update(time, delta);
this.postUpdate(time, delta);
for (const event in this._sayCache) { // Flushes expired cached events from throttled says

@@ -181,14 +151,9 @@ const data = this._sayCache[event];

}
}
fullUpdate(time, delta) {
this.preUpdate(time, delta);
this.update(time, delta);
this.postUpdate(time, delta);
if (this.children) this.children.forEach(child => child.fullUpdate(time, delta));
}
}
export function GetPawn(actorId) {
return pm.get(actorId);
}

@@ -36,7 +36,11 @@ import { Actor } from "./Actor";

destroyPlayer(player) {
this.publish("playerManager", "destroy", player);
player.destroy();
}
onExit(viewId) {
const player = this.player(viewId);
if (!player) return;
this.publish("playerManager", "destroy", player);
player.destroy();
this.destroyPlayer(player);
this.players.delete(viewId);

@@ -43,0 +47,0 @@ }

@@ -172,3 +172,3 @@ // Vector and matrix math

export function v2_isZero(v) {
return !(v[0] || v[1] );
return v[0] === 0 && v[1] === 0;
}

@@ -348,3 +348,3 @@

export function v3_isZero(v) {
return !(v[0] || v[1] || v[2]);
return v[0] === 0 && v[1] === 0 && v[2] === 0;
}

@@ -1166,8 +1166,9 @@

export function q_equals(a,b,e = 0.0001) { // e is an epsilon
return Math.abs(q_dot(a,b)) + e >= 1;
export function q_equals(a,b,e = 0) { // e is an epsilon
if (e) return Math.abs(q_dot(a,b)) + e >= 1;
return (a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]);
}
export function q_isZero(q) {
return !(q[0] || q[1] || q[2]);
return q[0] === 0 && q[1] === 0 && q[2] === 0;
}

@@ -1174,0 +1175,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc