forked from Orillusion/orillusion
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sample): GUI text barrage (Orillusion#333)
add a GUI text barrage sample --------- Co-authored-by: hellmor <[email protected]> Co-authored-by: ShuangLiu <[email protected]>
- Loading branch information
1 parent
03529da
commit ea2ed66
Showing
1 changed file
with
142 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { Engine3D, Scene3D, CameraUtil, HoverCameraController, Object3D, View3D, Color, Camera3D, ViewPanel, UITextField, TextAnchor, ComponentBase, AtmosphericComponent, webGPUContext, CResizeEvent } from "@orillusion/core"; | ||
|
||
class Sample_TextBarrage { | ||
private scene: Scene3D; | ||
private camera: Camera3D; | ||
|
||
async run() { | ||
// init engine | ||
await Engine3D.init(); | ||
// create new Scene | ||
let scene = new Scene3D(); | ||
this.scene = scene; | ||
|
||
// load base font | ||
await Engine3D.res.loadFont("https://cdn.orillusion.com/fnt/0.fnt"); | ||
|
||
// add an Atmospheric sky enviroment | ||
let sky = scene.addComponent(AtmosphericComponent); | ||
sky.sunY = 0.6; | ||
|
||
// init camera3D | ||
let mainCamera = CameraUtil.createCamera3D(null, scene); | ||
mainCamera.perspective(60, Engine3D.aspect, 1, 2000.0); | ||
this.camera = mainCamera; | ||
|
||
// add a basic camera controller | ||
const hoverCameraController = mainCamera.object3D.addComponent(HoverCameraController); | ||
hoverCameraController.setCamera(0, 0, 20); | ||
|
||
// create a view with target scene and camera | ||
let view = new View3D(); | ||
view.scene = scene; | ||
view.camera = mainCamera; | ||
|
||
// create UIpanel root | ||
let panelRoot: Object3D = new Object3D(); | ||
const panel = panelRoot.addComponent(ViewPanel); | ||
// resize panel radio | ||
webGPUContext.addEventListener(CResizeEvent.RESIZE, () => panel.uiTransform.resize(Engine3D.width, Engine3D.height), this); | ||
|
||
// add to UIcanvas | ||
let canvas = view.enableUICanvas(); | ||
canvas.addChild(panel.object3D); | ||
|
||
// Create text barrage | ||
const textCount = 100; | ||
for (let i = 0; i < textCount; ++i) { | ||
const textQuad = new Object3D(); | ||
panelRoot.addChild(textQuad); | ||
const text = textQuad.addComponent(UITextField); | ||
text.color = new Color(1, 1, 1); | ||
text.fontSize = 32; | ||
text.alignment = TextAnchor.MiddleCenter; | ||
text.uiTransform.resize(300, 12); | ||
|
||
// Init and reset text barrage animation | ||
const barrage = textQuad.addComponent(TextBarrageAnimation); | ||
barrage.camera = this.camera; | ||
barrage.priorityOffset = textCount; | ||
barrage.play(); | ||
} | ||
|
||
// start render | ||
Engine3D.startRenderView(view); | ||
} | ||
} | ||
|
||
class TextBarrageAnimation extends ComponentBase { | ||
// prettier-ignore | ||
static words = [ "GALACEAN", "galacean", "HELLO", "hello", "WORLD", "world", "TEXT", "text", "PEACE", "peace", "LOVE", "love", "abcdefg", "hijklmn", "opqrst", "uvwxyz", "ABCDEFG", "HIJKLMN", "OPQRST", "UVWXYZ", "~!@#$", "%^&*", "()_+" ]; | ||
static colors = new Array(10).fill(1).map(() => Color.random()); | ||
|
||
public camera: Camera3D; | ||
public priorityOffset: number = 0; | ||
|
||
private _speed: number = 0; | ||
private _isPlaying: boolean = false; | ||
private _text: UITextField; | ||
private lastTime: number = 0; | ||
|
||
play() { | ||
this._isPlaying = true; | ||
} | ||
|
||
start(): void { | ||
this._text = this.object3D.getComponent(UITextField); | ||
this.lastTime = Date.now(); | ||
this._reset(true); | ||
} | ||
|
||
onUpdate(): void { | ||
if (this._isPlaying) { | ||
const now = Date.now(); | ||
const dt = now - this.lastTime; | ||
this.lastTime = now; | ||
let halfWidth = Engine3D.width * 0.5, | ||
halfHeight = Engine3D.height * 0.5; | ||
let { x, y, width, height } = this._text.uiTransform; | ||
|
||
// move text to left | ||
this._text.uiTransform.x += this._speed * dt; | ||
// reset text position after pass the left side of the screen | ||
if (x < -halfWidth - width) { | ||
this._reset(false); | ||
} | ||
// limit y position in view port | ||
if (y < -halfHeight + height) this._text.uiTransform.y = -halfHeight + height; | ||
else if (y > halfHeight - height) this._text.uiTransform.y = halfHeight - height; | ||
} | ||
} | ||
|
||
private _reset(isFirst: boolean) { | ||
const text = this._text; | ||
const { words, colors } = TextBarrageAnimation; | ||
|
||
// Reset the text to render | ||
const wordLastIndex = words.length - 1; | ||
text.text = `${words[getRandomNum(0, wordLastIndex)]} ${words[getRandomNum(0, wordLastIndex)]}`; | ||
// Reset color | ||
text.color = colors[getRandomNum(0, colors.length - 1)]; | ||
const halfWidth = Engine3D.width * 0.5; | ||
const halfHeight = Engine3D.height * 0.5; | ||
// Reset position | ||
this._text.uiTransform.x = isFirst ? getRandomNum(halfWidth, halfWidth * 3) : halfWidth + this._text.uiTransform.width; | ||
this._text.uiTransform.y = getRandomNum(-halfHeight + this._text.uiTransform.height, halfHeight - this._text.uiTransform.height); | ||
// Reset speed | ||
this._speed = getRandomNum(-500, -200) * 0.0003; | ||
} | ||
} | ||
|
||
/** | ||
* Get a random number between min and max | ||
* @param min | ||
* @param max | ||
*/ | ||
function getRandomNum(min: number, max: number): number { | ||
const range = max - min; | ||
const rand = Math.random(); | ||
return min + Math.round(rand * range); | ||
} | ||
|
||
new Sample_TextBarrage().run(); |