Skip to content

Commit

Permalink
BGs initial support
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo committed May 8, 2024
1 parent f3d12c4 commit 2240897
Show file tree
Hide file tree
Showing 46 changed files with 1,251 additions and 186 deletions.
3 changes: 2 additions & 1 deletion addons.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"addons": [
"hubs-duck-addon",
"hubs-portals-addon"
"hubs-portals-addon",
"hubs-behavior-graphs-addon"
]
}
76 changes: 56 additions & 20 deletions src/addons.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { App } from "./app";
import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
import { App, HubsWorld } from "./app";
import { prefabs } from "./prefabs/prefabs";

import {
Expand All @@ -12,6 +13,11 @@ import {
import configs from "./utils/configs";
import { commonInflators, gltfInflators, jsxInflators } from "./utils/jsx-entity";
import { networkableComponents, schemas } from "./utils/network-schemas";
import { gltfPluginsExtra } from "./components/gltf-model-plus";
import { GLTFLinkResolverFn, gltfLinkResolvers } from "./inflators/model";
import { Object3D } from "three";
import { extraSections } from "./react-components/debug-panel/ECSSidebar";
import { shouldUseNewLoader } from "./hubs";

function getNextIdx(slot: Array<SystemConfigT>, system: SystemConfigT) {
return slot.findIndex(item => {
Expand All @@ -25,16 +31,14 @@ function registerSystem(system: SystemConfigT) {
slot = APP.addon_systems.setup;
} else if (system.order < SystemOrderE.PostPhysics) {
slot = APP.addon_systems.prePhysics;
} else if (system.order < SystemOrderE.MatricesUpdate) {
} else if (system.order < SystemOrderE.BeforeMatricesUpdate) {
slot = APP.addon_systems.postPhysics;
} else if (system.order < SystemOrderE.BeforeRender) {
slot = APP.addon_systems.beforeRender;
slot = APP.addon_systems.postPhysics;
} else if (system.order < SystemOrderE.AfterRender) {
slot = APP.addon_systems.afterRender;
} else if (system.order < SystemOrderE.PostProcessing) {
slot = APP.addon_systems.postProcessing;
slot = APP.addon_systems.beforeRender;
} else {
slot = APP.addon_systems.tearDown;
slot = APP.addon_systems.afterRender;
}
const nextIdx = getNextIdx(slot, system);
slot.splice(nextIdx, 0, system);
Expand Down Expand Up @@ -92,6 +96,10 @@ export interface InternalAddonConfigT {
config?: JSON | undefined;
}
type AddonConfigT = Omit<InternalAddonConfigT, "enabled" | "config">;
export type AdminAddonConfig = {
enabled: boolean;
config: JSON;
};

const pendingAddons = new Map<AddonIdT, InternalAddonConfigT>();
export const addons = new Map<AddonIdT, AddonConfigT>();
Expand All @@ -101,6 +109,44 @@ export function registerAddon(id: AddonIdT, config: AddonConfigT) {
pendingAddons.set(id, config);
}

export type GLTFParserCallbackFn = (parser: GLTFParser) => GLTFLoaderPlugin;
export function registerGLTFLoaderPlugin(callback: GLTFParserCallbackFn): void {
gltfPluginsExtra.push(callback);
}
export function registerGLTFLinkResolver(resolver: GLTFLinkResolverFn): void {
gltfLinkResolvers.push(resolver);
}
export function registerECSSidebarSection(section: (world: HubsWorld, selectedObj: Object3D) => React.JSX.Element) {
extraSections.push(section);
}

export function getAddonConfig(id: string): AdminAddonConfig {
const adminAddonsConfig = configs.feature("addons_config");
let adminAddonConfig = {
enabled: false,
config: {} as JSON
};
if (adminAddonsConfig && id in adminAddonsConfig) {
adminAddonConfig = adminAddonsConfig[id];
}
return adminAddonConfig;
}

export function isAddonEnabled(app: App, id: string): boolean {
let enabled = false;
if (shouldUseNewLoader()) {
if (app.hub?.user_data && "addons" in app.hub?.user_data && id in app.hub.user_data["addons"]) {
enabled = app.hub.user_data.addons[id];
} else {
const adminAddonsConfig = getAddonConfig(id);
if (adminAddonsConfig) {
enabled = adminAddonsConfig.enabled;
}
}
}
return enabled;
}

export function onAddonsInit(app: App) {
app.scene?.addEventListener("hub_updated", () => {
for (const [id, addon] of pendingAddons) {
Expand All @@ -110,13 +156,7 @@ export function onAddonsInit(app: App) {
addons.set(id, addon);
}

if (app.hub?.user_data && `addon_${id}` in app.hub.user_data) {
addon.enabled = app.hub.user_data[`addon_${id}`];
} else {
addon.enabled = false;
}

if (!addon.enabled) {
if (!isAddonEnabled(app, id)) {
continue;
}

Expand Down Expand Up @@ -171,12 +211,8 @@ export function onAddonsInit(app: App) {
}

if (addon.onReady) {
let config;
const addonsConfig = configs.feature("addons_config");
if (addonsConfig && id in addonsConfig) {
config = addonsConfig[id];
}
addon.onReady(app, config);
const adminAddonConfig = getAddonConfig(id);
addon.onReady(app, adminAddonConfig.config);
}
}
pendingAddons.clear();
Expand Down
10 changes: 5 additions & 5 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
PositionalAudio,
Scene,
sRGBEncoding,
Texture,
WebGLRenderer
} from "three";
import { AudioSettings, SourceType } from "./components/audio-params";
Expand Down Expand Up @@ -54,6 +55,7 @@ export interface HubsWorld extends IWorld {
nid2eid: Map<number, number>;
eid2obj: Map<number, Object3D>;
eid2mat: Map<number, Material>;
eid2tex: Map<number, Texture>;
time: { delta: number; elapsed: number; tick: number };
}

Expand Down Expand Up @@ -110,12 +112,9 @@ export class App {
setup: new Array<{ order: number; system: SystemT }>(),
prePhysics: new Array<{ order: number; system: SystemT }>(),
postPhysics: new Array<{ order: number; system: SystemT }>(),
matricesUpdate: new Array<{ order: number; system: SystemT }>(),
beforeMatricesUpdate: new Array<{ order: number; system: SystemT }>(),
beforeRender: new Array<{ order: number; system: SystemT }>(),
render: new Array<{ order: number; system: SystemT }>(),
afterRender: new Array<{ order: number; system: SystemT }>(),
postProcessing: new Array<{ order: number; system: SystemT }>(),
tearDown: new Array<{ order: number; system: SystemT }>()
afterRender: new Array<{ order: number; system: SystemT }>()
};

RENDER_ORDER = {
Expand All @@ -135,6 +134,7 @@ export class App {
// TODO: Create accessor / update methods for these maps / set
this.world.eid2obj = new Map();
this.world.eid2mat = new Map();
this.world.eid2tex = new Map();

this.world.nid2eid = new Map();
this.world.deletedNids = new Set();
Expand Down
47 changes: 45 additions & 2 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,43 @@ export const MediaFrame = defineComponent({
previewingNid: Types.eid,
flags: Types.ui8
});
export const MediaRoot = defineComponent();
export const NetworkedText = defineComponent({
text: Types.ui8,
anchorX: Types.ui8,
anchorY: Types.ui8,
color: Types.ui32,
curveRadius: Types.f32,
direction: Types.ui8,
fillOpacity: Types.f32,
fontUrl: Types.ui8,
fontSize: Types.f32,
letterSpacing: Types.f32,
lineHeight: Types.ui8,
textAlign: Types.ui8,
outlineWidth: Types.ui8,
outlineColor: Types.ui32,
outlineBlur: Types.ui8,
outlineOffsetX: Types.ui8,
outlineOffsetY: Types.ui8,
outlineOpacity: Types.f32,
strokeWidth: Types.ui8,
strokeColor: Types.ui32,
strokeOpacity: Types.ui32,
textIndent: Types.ui32,
whiteSpace: Types.ui8,
overflowWrap: Types.ui8,
opacity: Types.f32,
side: Types.ui8,
maxWidth: Types.f32
});
NetworkedText.text[$isStringType] = true;
NetworkedText.lineHeight[$isStringType] = true;
NetworkedText.outlineWidth[$isStringType] = true;
NetworkedText.outlineBlur[$isStringType] = true;
NetworkedText.outlineOffsetX[$isStringType] = true;
NetworkedText.outlineOffsetY[$isStringType] = true;
NetworkedText.strokeWidth[$isStringType] = true;
export const TextTag = defineComponent();
export const ReflectionProbe = defineComponent();
export const Slice9 = defineComponent({
Expand All @@ -61,7 +98,9 @@ export const SpotLightTag = defineComponent();
export const CursorRaycastable = defineComponent();
export const RemoteHoverTarget = defineComponent();
export const NotRemoteHoverTarget = defineComponent();
export const Holdable = defineComponent();
export const Holdable = defineComponent({
flags: Types.ui8
});
export const RemoveNetworkedEntityButton = defineComponent();
export const Interacted = defineComponent();
export const HandRight = defineComponent();
Expand Down Expand Up @@ -276,9 +315,12 @@ export const LoopAnimation = defineComponent();
*/
export const LoopAnimationData = new Map();
export const NetworkedVideo = defineComponent({
src: Types.ui8,
time: Types.f32,
flags: Types.ui8
flags: Types.ui8,
projection: Types.ui8
});
NetworkedVideo.src[$isStringType] = true;
export const VideoMenuItem = defineComponent();
export const VideoMenu = defineComponent({
videoRef: Types.eid,
Expand Down Expand Up @@ -393,6 +435,7 @@ export const Billboard = defineComponent({
onlyY: Types.ui8
});
export const MaterialTag = defineComponent();
export const TextureTag = defineComponent();
export const UVScroll = defineComponent({
speed: [Types.f32, 2],
increment: [Types.f32, 2],
Expand Down
8 changes: 8 additions & 0 deletions src/bit-systems/audio-emitter-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AudioType, SourceType } from "../components/audio-params";
import { AudioSystem } from "../systems/audio-system";
import { applySettings, getCurrentAudioSettings, updateAudioSettings } from "../update-audio-settings";
import { addObject3DComponent, swapObject3DComponent } from "../utils/jsx-entity";
import { EntityID } from "../utils/networking-types";

export type AudioObject3D = StereoAudio | PositionalAudio;
type AudioConstructor<T> = new (listener: ThreeAudioListener) => T;
Expand Down Expand Up @@ -55,6 +56,13 @@ function swapAudioType<T extends AudioObject3D>(
swapObject3DComponent(world, eid, newAudio);
}

export function swapAudioSrc(world: HubsWorld, videoEid: EntityID, audioEid: EntityID) {
const audio = world.eid2obj.get(audioEid)! as AudioObject3D;
const video = MediaVideoData.get(videoEid)!;
audio.setMediaElementSource(video);
video.volume = 1;
}

export function makeAudioEntity(world: HubsWorld, source: number, sourceType: SourceType, audioSystem: AudioSystem) {
const eid = addEntity(world);
APP.sourceType.set(eid, sourceType);
Expand Down
8 changes: 6 additions & 2 deletions src/bit-systems/loop-animation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { addComponent, defineQuery, enterQuery, exitQuery, hasComponent, removeComponent } from "bitecs";
import { AnimationAction, AnimationClip, AnimationMixer, LoopRepeat } from "three";
import { AnimationClip, LoopRepeat } from "three";
import {
MixerAnimatable,
MixerAnimatableData,
Expand Down Expand Up @@ -47,12 +47,16 @@ const getActiveClips = (

export function loopAnimationSystem(world: HubsWorld): void {
loopAnimationInitializeEnterQuery(world).forEach((eid: number): void => {
const params = LoopAnimationInitializeData.get(eid)!;
if (!params.length) {
return;
}

const object = world.eid2obj.get(eid)!;
const mixer = MixerAnimatableData.get(eid)!;

addComponent(world, LoopAnimation, eid);

const params = LoopAnimationInitializeData.get(eid)!;
const activeAnimations = [];

for (let i = 0; i < params.length; i++) {
Expand Down
6 changes: 4 additions & 2 deletions src/bit-systems/media-loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
Rigidbody,
MediaLoaderOffset,
MediaVideo,
NetworkedTransform
NetworkedTransform,
MediaRoot
} from "../bit-components";
import { inflatePhysicsShape, Shape } from "../inflators/physics-shape";
import { ErrorObject } from "../prefabs/error-object";
Expand Down Expand Up @@ -204,7 +205,7 @@ class UnsupportedMediaTypeError extends Error {
}
}

type MediaInfo = {
export type MediaInfo = {
accessibleUrl: string;
canonicalUrl: string;
canonicalAudioUrl: string | null;
Expand Down Expand Up @@ -283,6 +284,7 @@ function* loadMedia(world: HubsWorld, eid: EntityID) {
try {
const urlData = (yield resolveMediaInfo(src)) as MediaInfo;
media = yield* loadByMediaType(world, eid, urlData);
addComponent(world, MediaRoot, media);
addComponent(world, MediaLoaded, media);
addComponent(world, MediaInfo, media);
MediaInfo.accessibleUrl[media] = APP.getSid(urlData.accessibleUrl);
Expand Down
Loading

0 comments on commit 2240897

Please sign in to comment.