Skip to content

Commit

Permalink
Merge pull request Hubs-Foundation#5701 from mozilla/cleanup-main-tick
Browse files Browse the repository at this point in the history
Cleanup main tick
  • Loading branch information
netpro2k authored Sep 21, 2022
2 parents 8d57224 + 0f03d94 commit bab932e
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 144 deletions.
10 changes: 6 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"linkify-it": "^2.0.3",
"markdown-it": "^8.4.2",
"moving-average": "^1.0.0",
"networked-aframe": "github:mozillareality/networked-aframe#master",
"networked-aframe": "github:mozillareality/networked-aframe#6093c3a0b2867a9e141cd5c19f7d13dfa7c38479",
"nipplejs": "github:mozillareality/nipplejs#mr-social-client/master",
"node-ensure": "0.0.0",
"normalize.css": "^8.0.1",
Expand Down
46 changes: 6 additions & 40 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import MediaDevicesManager from "./utils/media-devices-manager";
import {
Audio,
AudioListener,
Clock,
Object3D,
PerspectiveCamera,
PositionalAudio,
Expand All @@ -23,6 +22,7 @@ import {
} from "three";
import { AudioSettings, SourceType } from "./components/audio-params";
import { DialogAdapter } from "./naf-dialog-adapter";
import { mainTick } from "./systems/hubs-systems";
import { waitForPreloads } from "./utils/preload";

declare global {
Expand All @@ -46,22 +46,11 @@ export interface HubsWorld extends IWorld {
deletedNids: Set<number>;
nid2eid: Map<number, number>;
eid2obj: Map<number, Object3D>;
time: { delta: number; elapsed: number; tick: number; then: number };
time: { delta: number; elapsed: number; tick: number };
}

window.$B = bitecs;

const timeSystem = (world: HubsWorld) => {
const { time } = world;
const now = performance.now();
const delta = now - time.then;
time.delta = delta;
time.elapsed += delta;
time.then = now;
time.tick++;
return world;
};

export class App {
scene?: AScene;
hubChannel?: HubChannel;
Expand Down Expand Up @@ -183,44 +172,21 @@ export class App {
this.audioListener = audioListener;
camera.add(audioListener);

const renderClock = new Clock();

// TODO NAF currently depends on this, it should not
sceneEl.clock = renderClock;

// TODO we should have 1 source of truth for time
this.world.time = {
delta: 0,
elapsed: 0,
then: performance.now(),
tick: 0
};

this.world.scene = sceneEl.object3D;

// Main RAF loop
const mainTick = (_rafTime: number, xrFrame: XRFrame) => {
// TODO we should probably be using time from the raf loop itself
const delta = renderClock.getDelta() * 1000;
const time = renderClock.elapsedTime * 1000;

// TODO pass this into systems that care about it (like input) once they are moved into this loop
sceneEl.frame = xrFrame;

timeSystem(this.world);

// Tick AFrame systems and components
if (sceneEl.isPlaying) {
sceneEl.tick(time, delta);
}

renderer.render(sceneEl.object3D, camera);
};

// This gets called after all system and component init functions
sceneEl.addEventListener("loaded", () => {
waitForPreloads().then(() => {
renderer.setAnimationLoop(mainTick);
this.world.time.elapsed = performance.now();
renderer.setAnimationLoop(function (_rafTime, xrFrame) {
mainTick(xrFrame, renderer, sceneEl.object3D, camera);
});
sceneEl.renderStarted = true;
});
});
Expand Down
3 changes: 1 addition & 2 deletions src/systems/bit-constraints-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ function remove(world, offersConstraint, constraintComponent, physicsSystem, int
}
}

export function constraintsSystem(world) {
const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem;
export function constraintsSystem(world, physicsSystem) {
add(world, physicsSystem, anyEntityWith(world, RemoteRight), ConstraintRemoteRight, queryEnterRemoteRight(world));
add(world, physicsSystem, anyEntityWith(world, RemoteLeft), ConstraintRemoteLeft, queryEnterRemoteLeft(world));
add(world, physicsSystem, anyEntityWith(world, HandRight), ConstraintHandRight, queryEnterHandRight(world));
Expand Down
8 changes: 4 additions & 4 deletions src/systems/bit-interaction-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { handHoverSystem } from "./bit-hand-hover-system";
import { holdSystem } from "./hold-system";
import { dontHoldWithHandAndRemote, dontHoverAndHold } from "./not-hovered-if-held";

export function interactionSystem(world, cursorTargettingSystem, t, systems) {
export function interactionSystem(world, cursorTargettingSystem, t, aframeSystems) {
cursorTargettingSystem.tick(t); // handles hovers for cursors
handHoverSystem(world, systems.interaction);
holdSystem(world, systems.userinput);
handHoverSystem(world, aframeSystems.interaction);
holdSystem(world, aframeSystems.userinput);
dontHoldWithHandAndRemote(world);
dontHoverAndHold(world);
// Copies hovered/held state (only for aframe entities) for querying by legacy systems/components
systems.interaction.updateLegacyState();
aframeSystems.interaction.updateLegacyState();
}
213 changes: 137 additions & 76 deletions src/systems/hubs-systems.js → src/systems/hubs-systems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,26 @@ import { physicsCompatSystem } from "./bit-physics";
import { destroyAtExtremeDistanceSystem } from "./bit-destroy-at-extreme-distances";
import { videoMenuSystem } from "../bit-systems/video-menu-system";
import { deleteEntitySystem } from "../bit-systems/delete-entity-system";
import type { HubsSystems } from "aframe";
import { Camera, Scene, WebGLRenderer } from "three";
import { HubsWorld } from "../app";

declare global {
interface Window {
$S: HubsSystems;
}
}

const timeSystem = (world: HubsWorld) => {
const { time } = world;
const now = performance.now();
time.delta = now - time.elapsed;
time.elapsed = now;
time.tick++;
};

// NOTE keeping this around since many things index into it to get a reference to a system. This will
// naturally burn down as we migrate things, so it is not worth going through and changing all of them.
AFRAME.registerSystem("hubs-systems", {
init() {
waitForDOMContentLoaded().then(() => {
Expand Down Expand Up @@ -92,83 +111,125 @@ AFRAME.registerSystem("hubs-systems", {
window.$S = this;
},

tick(t, dt) {
if (!this.DOMContentDidLoad) return;
const world = APP.world;

networkReceiveSystem(world);
onOwnershipLost(world);
mediaLoadingSystem(world);

physicsCompatSystem(world);

networkedTransformSystem(world);

const systems = AFRAME.scenes[0].systems;
systems.userinput.tick2();

interactionSystem(world, this.cursorTargettingSystem, t, systems);

buttonSystems(world);
constraintsSystem(world, systems.userinput);

// We run this earlier in the frame so things have a chance to override properties run by animations
this.animationMixerSystem.tick(dt);

this.characterController.tick(t, dt);
this.cursorTogglingSystem.tick(systems.interaction, systems.userinput, this.el);
this.interactionSfxSystem.tick(systems.interaction, systems.userinput, this.soundEffectsSystem);
this.superSpawnerSystem.tick();
this.emojiSystem.tick(t, systems.userinput);
this.cursorPoseTrackingSystem.tick();
this.hoverMenuSystem.tick();
this.positionAtBorderSystem.tick();
// this.constraintsSystem.tick();
this.twoPointStretchingSystem.tick();

floatyObjectSystem(world);

this.holdableButtonSystem.tick();
this.hoverButtonSystem.tick();
this.drawingMenuSystem.tick();
this.hapticFeedbackSystem.tick(
this.twoPointStretchingSystem,
false,
false
// TODO: didInteractLeftThisFrame doesn't exist?
// this.singleActionButtonSystem.didInteractLeftThisFrame,
// this.singleActionButtonSystem.didInteractRightThisFrame
);
this.soundEffectsSystem.tick();
this.scenePreviewCameraSystem.tick();
this.physicsSystem.tick(dt);
this.inspectYourselfSystem.tick(this.el, systems.userinput, this.cameraSystem);
this.cameraSystem.tick(this.el, dt);
cameraToolSystem(world);
this.waypointSystem.tick(t, dt);
this.menuAnimationSystem.tick(t);
this.spriteSystem.tick(t, dt);
this.uvScrollSystem.tick(dt);
this.shadowSystem.tick();
videoMenuSystem(world, systems.userinput);
videoSystem(world, this.audioSystem);
mediaFramesSystem(world);
this.audioZonesSystem.tick(this.el);
this.gainSystem.tick();
this.nameTagSystem.tick();

deleteEntitySystem(world, systems.userinput);
destroyAtExtremeDistanceSystem(world);
removeNetworkedObjectButtonSystem(world);
removeObject3DSystem(world);

// We run this late in the frame so that its the last thing to have an opinion about the scale of an object
this.boneVisibilitySystem.tick();

networkSendSystem(world);
},

remove() {
this.cursorTargettingSystem.remove();
}
});

export function mainTick(xrFrame: XRFrame, renderer: WebGLRenderer, scene: Scene, camera: Camera) {
const world = APP.world;
const sceneEl = AFRAME.scenes[0];
const aframeSystems = sceneEl.systems;
const hubsSystems = aframeSystems["hubs-systems"];

// TODO does anything actually ever pause the scene?
if (!sceneEl.isPlaying && !hubsSystems.DOMContentDidLoad) return;

timeSystem(world);
const t = world.time.elapsed;
const dt = world.time.delta;

// Tick AFrame components
const tickComponents = sceneEl.behaviors.tick;
for (let i = 0; i < tickComponents.length; i++) {
if (!tickComponents[i].el.isPlaying) continue;
tickComponents[i].tick(t, dt);
}

// Run order of this loop, based on module load order
// NOTE these could be inlined instead of looping but that would be a breakings change
// to third part devs. This will also just naturally burndown as we migrate.
// aframeSystems["networked"].tick(t, dt);
// aframeSystems["local-audio-analyser"].tick(t, dt);
// aframeSystems["transform-selected-object"].tick(t, dt);
// aframeSystems["frame-scheduler"].tick(t, dt);
// aframeSystems["personal-space-bubble"].tick(t, dt);
// aframeSystems["exit-on-blur"].tick(t, dt);
// aframeSystems["auto-pixel-ratio"].tick(t, dt);
// aframeSystems["idle-detector"].tick(t, dt);
// aframeSystems["userinput-debug"].tick(t, dt);
// aframeSystems["ui-hotkeys"].tick(t, dt);
// aframeSystems["tips"].tick(t, dt);
const systemNames = sceneEl.systemNames;
for (let i = 0; i < systemNames.length; i++) {
if (!aframeSystems[systemNames[i]].tick) continue;
aframeSystems[systemNames[i]].tick(t, dt);
}

networkReceiveSystem(world);
onOwnershipLost(world);
mediaLoadingSystem(world);

physicsCompatSystem(world);

networkedTransformSystem(world);

aframeSystems.userinput.tick2(xrFrame);

interactionSystem(world, hubsSystems.cursorTargettingSystem, t, aframeSystems);

buttonSystems(world);
constraintsSystem(world, hubsSystems.physicsSystem);

// We run this earlier in the frame so things have a chance to override properties run by animations
hubsSystems.animationMixerSystem.tick(dt);

hubsSystems.characterController.tick(t, dt);
hubsSystems.cursorTogglingSystem.tick(aframeSystems.interaction, aframeSystems.userinput, hubsSystems.el);
hubsSystems.interactionSfxSystem.tick(
aframeSystems.interaction,
aframeSystems.userinput,
hubsSystems.soundEffectsSystem
);
hubsSystems.superSpawnerSystem.tick();
hubsSystems.emojiSystem.tick(t, aframeSystems.userinput);
hubsSystems.cursorPoseTrackingSystem.tick();
hubsSystems.hoverMenuSystem.tick();
hubsSystems.positionAtBorderSystem.tick();
hubsSystems.twoPointStretchingSystem.tick();

floatyObjectSystem(world);

hubsSystems.holdableButtonSystem.tick();
hubsSystems.hoverButtonSystem.tick();
hubsSystems.drawingMenuSystem.tick();
hubsSystems.hapticFeedbackSystem.tick(
hubsSystems.twoPointStretchingSystem,
false,
false
// TODO: didInteractLeftHubsSystemsFrame doesn't exist?
// hubsSystems.singleActionButtonSystem.didInteractLeftHubsSystemsFrame,
// hubsSystems.singleActionButtonSystem.didInteractRightHubsSystemsFrame
);
hubsSystems.soundEffectsSystem.tick();
hubsSystems.scenePreviewCameraSystem.tick();
hubsSystems.physicsSystem.tick(dt);
hubsSystems.inspectYourselfSystem.tick(hubsSystems.el, aframeSystems.userinput, hubsSystems.cameraSystem);
hubsSystems.cameraSystem.tick(hubsSystems.el, dt);
cameraToolSystem(world);
hubsSystems.waypointSystem.tick(t, dt);
hubsSystems.menuAnimationSystem.tick(t);
hubsSystems.spriteSystem.tick(t, dt);
hubsSystems.uvScrollSystem.tick(dt);
hubsSystems.shadowSystem.tick();
videoMenuSystem(world, aframeSystems.userinput);
videoSystem(world, hubsSystems.audioSystem);
mediaFramesSystem(world);
hubsSystems.audioZonesSystem.tick(hubsSystems.el);
hubsSystems.gainSystem.tick();
hubsSystems.nameTagSystem.tick();

deleteEntitySystem(world, aframeSystems.userinput);
destroyAtExtremeDistanceSystem(world);
removeNetworkedObjectButtonSystem(world);
removeObject3DSystem(world);

// We run this late in the frame so that its the last thing to have an opinion about the scale of an object
hubsSystems.boneVisibilitySystem.tick();

networkSendSystem(world);

renderer.render(scene, camera);
// tock()s on components and system will fire here. (As well as any other time render() is called without unbinding onAfterRender)
// TODO inline invoking tocks instead of using onAfterRender registered in a-scene
}
Loading

0 comments on commit bab932e

Please sign in to comment.