-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Polish text bitecs #5933
Polish text bitecs #5933
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { defineQuery } from "bitecs"; | ||
import { Text as TroikaText } from "troika-three-text"; | ||
import { HubsWorld } from "../app"; | ||
import { TextTag } from "../bit-components"; | ||
|
||
const textQuery = defineQuery([TextTag]); | ||
|
||
export function textSystem(world: HubsWorld) { | ||
textQuery(world).forEach(eid => { | ||
const text = world.eid2obj.get(eid)! as TroikaText; | ||
|
||
// sync() invokes async text processing in workers. | ||
// https://github.com/protectwise/troika/tree/main/packages/troika-three-text#handling-asynchronous-updates | ||
// | ||
// It is safe to call sync() every frame from the | ||
// performance and efficiency perspective because | ||
// sync() checks whether to invoke costly processing | ||
// inside. | ||
// | ||
// Ideally this system should run after any other systems | ||
// that can update text properties and we need to be careful | ||
// for the systems execution order. Otherwise sync() call | ||
// can happen one frame after. (But probably it may not be | ||
// a big deal even if it happens because what sync() invokes | ||
// is async processing, texture properties update will be | ||
// reflected some frames after in any case.) | ||
// | ||
// Assumes it is safe even if text object is | ||
// disposed before the async processing is done | ||
// because TroikaText properly handles | ||
text.sync(); | ||
}); | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { addComponent } from "bitecs"; | ||
import { BackSide, DoubleSide, FrontSide } from "three"; | ||
import { Text as TroikaText } from "troika-three-text"; | ||
import { HubsWorld } from "../app"; | ||
import { TextTag } from "../bit-components"; | ||
import { addObject3DComponent } from "../utils/jsx-entity"; | ||
|
||
export type TextParams = { | ||
value: string; | ||
anchorX?: "left" | "center" | "right"; | ||
anchorY?: "top" | "top-baseline" | "top-cap" | "top-ex" | "middle" | "bottom-baseline" | "bottom"; | ||
clipRect?: [number, number, number, number] | null; | ||
color?: string; | ||
curveRadius?: number; | ||
depthOffset?: number; | ||
direction?: "auto" | "ltr" | "trl"; | ||
fillOpacity?: number; | ||
fontUrl?: string | null; | ||
fontSize?: number; | ||
glyphGeometryDetail?: number; | ||
gpuAccelerateSDF?: boolean; | ||
letterSpacing?: number; | ||
lineHeight?: number | "normal"; | ||
maxWidth?: number; | ||
opacity?: number; | ||
outlineBlur?: number | `${number}%`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've never seen this type definition before. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be similar to regex. (If I understand correctly) https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html#handbook-content There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't know about this before. Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't know that was supported either. Neat! |
||
outlineColor?: string; | ||
outlineOffsetX?: number | `${number}%`; | ||
outlineOffsetY?: number | `${number}%`; | ||
outlineOpacity?: number; | ||
outlineWidth?: number | `${number}%`; | ||
overflowWrap?: "normal" | "break-word"; | ||
sdfGlyphSize?: number | null; | ||
side?: "front" | "back" | "double"; | ||
strokeColor?: string; | ||
strokeOpacity?: number; | ||
strokeWidth?: number | `${number}%`; | ||
textAlign?: "left" | "right" | "center" | "justify"; | ||
textIndent?: number; | ||
whiteSpace?: "normal" | "nowrap"; | ||
}; | ||
|
||
const THREE_SIDES = { | ||
front: FrontSide, | ||
back: BackSide, | ||
double: DoubleSide | ||
}; | ||
|
||
const DEFAULTS: Required<TextParams> = { | ||
anchorX: "center", | ||
anchorY: "middle", | ||
clipRect: null, | ||
color: "#ffffff", | ||
curveRadius: 0, | ||
depthOffset: 0, | ||
direction: "auto", | ||
fillOpacity: 1.0, | ||
fontUrl: null, | ||
fontSize: 0.075, | ||
glyphGeometryDetail: 1.0, | ||
gpuAccelerateSDF: true, | ||
letterSpacing: 0, | ||
lineHeight: "normal", | ||
maxWidth: Infinity, | ||
opacity: 1.0, | ||
outlineBlur: 0, | ||
outlineColor: "#000000", | ||
outlineOffsetX: 0, | ||
outlineOffsetY: 0, | ||
outlineOpacity: 1.0, | ||
outlineWidth: 0, | ||
overflowWrap: "normal", | ||
sdfGlyphSize: null, | ||
side: "front", | ||
strokeColor: "grey", | ||
strokeOpacity: 1.0, | ||
strokeWidth: 0, | ||
textAlign: "center", | ||
textIndent: 0, | ||
value: "", | ||
whiteSpace: "normal" | ||
}; | ||
|
||
export function inflateText(world: HubsWorld, eid: number, params: TextParams) { | ||
const requiredParams = Object.assign({}, DEFAULTS, params) as Required<TextParams>; | ||
const text = new TroikaText(); | ||
text.material!.toneMapped = false; | ||
|
||
text.text = requiredParams.value; | ||
text.material!.side = THREE_SIDES[requiredParams.side]; | ||
text.material!.opacity = requiredParams.opacity; | ||
text.font = requiredParams.fontUrl; | ||
|
||
text.anchorX = requiredParams.anchorX; | ||
text.anchorY = requiredParams.anchorY; | ||
text.clipRect = requiredParams.clipRect; | ||
text.color = requiredParams.color; | ||
text.curveRadius = requiredParams.curveRadius; | ||
text.depthOffset = requiredParams.depthOffset; | ||
text.direction = requiredParams.direction; | ||
text.fillOpacity = requiredParams.fillOpacity; | ||
text.fontSize = requiredParams.fontSize; | ||
text.glyphGeometryDetail = requiredParams.glyphGeometryDetail; | ||
text.gpuAccelerateSDF = requiredParams.gpuAccelerateSDF; | ||
text.letterSpacing = requiredParams.letterSpacing; | ||
text.lineHeight = requiredParams.lineHeight; | ||
text.maxWidth = requiredParams.maxWidth; | ||
text.outlineBlur = requiredParams.outlineBlur; | ||
text.outlineColor = requiredParams.outlineColor; | ||
text.outlineOffsetX = requiredParams.outlineOffsetX; | ||
text.outlineOffsetY = requiredParams.outlineOffsetY; | ||
text.outlineOpacity = requiredParams.outlineOpacity; | ||
text.outlineWidth = requiredParams.outlineWidth; | ||
text.overflowWrap = requiredParams.overflowWrap; | ||
text.sdfGlyphSize = requiredParams.sdfGlyphSize; | ||
text.strokeColor = requiredParams.strokeColor; | ||
text.strokeOpacity = requiredParams.strokeOpacity; | ||
text.strokeWidth = requiredParams.strokeWidth; | ||
text.textAlign = requiredParams.textAlign; | ||
text.textIndent = requiredParams.textIndent; | ||
text.whiteSpace = requiredParams.whiteSpace; | ||
|
||
text.sync(); | ||
|
||
addComponent(world, TextTag, eid); | ||
addObject3DComponent(world, eid, text); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,7 @@ import { particleEmitterSystem } from "../bit-systems/particle-emitter"; | |
import { audioEmitterSystem } from "../bit-systems/audio-emitter-system"; | ||
import { audioZoneSystem } from "../bit-systems/audio-zone-system"; | ||
import { audioDebugSystem } from "../bit-systems/audio-debug-system"; | ||
import { textSystem } from "../bit-systems/text"; | ||
|
||
declare global { | ||
interface Window { | ||
|
@@ -251,6 +252,9 @@ export function mainTick(xrFrame: XRFrame, renderer: WebGLRenderer, scene: Scene | |
hubsSystems.nameTagSystem.tick(); | ||
simpleWaterSystem(world); | ||
|
||
// All systems that update text properties should run before this | ||
textSystem(world); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its very crude but we may want to add a blank line above this system to make it clear its a bit "special". Or maybe better to just add a comment like |
||
|
||
videoTextureSystem(world); | ||
audioDebugSystem(world); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this need to support both null and undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't "?" imply that accepts
undeinfed
?