-
-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat:The first version of text system (#686)
* feat(text): init TextRenderer
- Loading branch information
1 parent
afa176a
commit c0ea1a2
Showing
15 changed files
with
1,193 additions
and
2 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
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,95 @@ | ||
import { Rect } from "@oasis-engine/math"; | ||
import { Engine } from "../../Engine"; | ||
import { Texture2D } from "../../texture/Texture2D"; | ||
import { Sprite } from "../sprite/Sprite"; | ||
|
||
/** | ||
* Dynamic atlas for text. | ||
*/ | ||
export class DynamicTextAtlas { | ||
private static _region: Rect = new Rect(); | ||
|
||
private _texture: Texture2D; | ||
private _width: number; | ||
private _height: number; | ||
|
||
private _space: number = 1; | ||
private _curX: number = 1; | ||
private _curY: number = 1; | ||
private _nextY: number = 1; | ||
|
||
private _sprites: Record<number, Sprite> = {}; | ||
|
||
constructor(engine: Engine, width: number, height: number) { | ||
this._width = width; | ||
this._height = height; | ||
this._texture = new Texture2D(engine, width, height); | ||
this._texture._addRefCount(1); | ||
} | ||
|
||
/** | ||
* Destroy atlas, it will release the texture. | ||
*/ | ||
public destroy() { | ||
this._sprites = {}; | ||
this._texture.destroy(true); | ||
} | ||
|
||
/** | ||
* Add a sprite. | ||
* @param sprite - the sprite to add | ||
* @param imageSource - The source of texture | ||
* @returns true if add sprite success, otherwise false | ||
*/ | ||
public addSprite(sprite: Sprite, imageSource: TexImageSource | OffscreenCanvas): boolean { | ||
const { _space: space, _texture: texture } = this; | ||
const { width, height } = imageSource; | ||
|
||
const endX = this._curX + width + space; | ||
if (endX >= this._width) { | ||
this._curX = space; | ||
this._curY = this._nextY + space; | ||
} | ||
|
||
const endY = this._curY + height + space; | ||
if (endY > this._nextY) { | ||
this._nextY = endY; | ||
} | ||
|
||
if (this._nextY >= this._height) { | ||
return false; | ||
} | ||
|
||
texture.setImageSource(imageSource, 0, false, false, this._curX, this._curY); | ||
texture.generateMipmaps(); | ||
|
||
const { _width, _height } = this; | ||
const region = DynamicTextAtlas._region; | ||
region.setValue(this._curX / _width, this._curY / _height, width / _width, height / _height); | ||
|
||
// destroy origin texture. | ||
sprite.texture && sprite.texture.destroy(); | ||
// Update atlas texture. | ||
sprite.atlasRegion = region; | ||
sprite.texture = texture; | ||
this._curX = endX + space; | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Remove a sprite. | ||
* @param sprite - the sprite to remove | ||
* @returns true if remove sprite success, otherwise false | ||
*/ | ||
public removeSprite(sprite: Sprite): boolean { | ||
const id = sprite.instanceId; | ||
const { _sprites } = this; | ||
if (_sprites[id]) { | ||
delete _sprites[id]; | ||
return true; | ||
} | ||
return false; | ||
} | ||
} | ||
|
126 changes: 126 additions & 0 deletions
126
packages/core/src/2d/dynamic-atlas/DynamicTextAtlasManager.ts
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,126 @@ | ||
import { Sprite } from "../sprite/Sprite"; | ||
import { Engine } from "../../Engine"; | ||
import { DynamicTextAtlas } from "./DynamicTextAtlas"; | ||
|
||
/** | ||
* Dynamic atlas manager for text. | ||
*/ | ||
export class DynamicTextAtlasManager { | ||
private _maxAtlasCount: number = 2; | ||
private _textureSize: number = 1024; | ||
private _atlases: Array<DynamicTextAtlas> = []; | ||
private _atlasIndex: number = -1; | ||
private _spritesInAtlasIndex: Record<number, number> = {}; | ||
|
||
/** | ||
* Indicates how many atlases should be created. | ||
*/ | ||
get maxAtlasCount(): number { | ||
return this._maxAtlasCount; | ||
} | ||
|
||
set maxAtlasCount(val: number) { | ||
this._maxAtlasCount = val; | ||
} | ||
|
||
/** | ||
* Indicates the size of the texture. | ||
*/ | ||
get textureSize(): number { | ||
return this._textureSize; | ||
} | ||
|
||
set textureSize(val: number) { | ||
this._textureSize = Math.min(val, 2048); | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
constructor(public readonly engine: Engine) {} | ||
|
||
/** | ||
* Add a sprite to atlas. | ||
* @param sprite - the sprite to add | ||
* @param imageSource - The source of texture | ||
* @returns true if add sprite success, otherwise false | ||
*/ | ||
public addSprite(sprite: Sprite, imageSource: TexImageSource | OffscreenCanvas): boolean { | ||
// Remove sprite if the sprite has been add. | ||
const { _spritesInAtlasIndex, _atlases } = this; | ||
const id = sprite.instanceId; | ||
const atlasIndex = _spritesInAtlasIndex[id]; | ||
if (atlasIndex) { | ||
_atlases[atlasIndex].removeSprite(sprite); | ||
delete _spritesInAtlasIndex[id]; | ||
} | ||
|
||
if (this._atlasIndex >= this._maxAtlasCount) { | ||
return false; | ||
} | ||
|
||
let atlas = _atlases[this._atlasIndex]; | ||
if (!atlas) { | ||
atlas = this._createAtlas(); | ||
} | ||
|
||
if (atlas.addSprite(sprite, imageSource)) { | ||
_spritesInAtlasIndex[id] = this._atlasIndex; | ||
return true; | ||
} | ||
|
||
if (this._atlasIndex + 1 >= this._maxAtlasCount) { | ||
this._atlasIndex = this._maxAtlasCount; | ||
return false; | ||
} | ||
|
||
atlas = this._createAtlas(); | ||
if (atlas.addSprite(sprite, imageSource)) { | ||
_spritesInAtlasIndex[id] = this._atlasIndex; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Remove a sprite from atlas. | ||
* @param sprite - the sprite to remove | ||
* @returns true if remove sprite success, otherwise false | ||
*/ | ||
public removeSprite(sprite: Sprite): boolean { | ||
if (!sprite) return false; | ||
|
||
const { _atlases } = this; | ||
for (let i = _atlases.length - 1; i >= 0; --i) { | ||
const atlas = _atlases[i]; | ||
if(atlas.removeSprite(sprite)) { | ||
delete this._spritesInAtlasIndex[i]; | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Reset all atlases. | ||
*/ | ||
public reset() { | ||
const { _atlases } = this; | ||
for (let i = 0, l = _atlases.length; i < l; ++i) { | ||
_atlases[i].destroy(); | ||
} | ||
|
||
_atlases.length = 0; | ||
this._atlasIndex = -1; | ||
this._spritesInAtlasIndex = {}; | ||
} | ||
|
||
private _createAtlas(): DynamicTextAtlas { | ||
this._atlasIndex++; | ||
const { _textureSize } = this; | ||
const atlas = new DynamicTextAtlas(this.engine, _textureSize, _textureSize); | ||
this._atlases.push(atlas); | ||
return atlas; | ||
} | ||
} |
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,11 @@ | ||
/** | ||
* The style of the font. | ||
*/ | ||
export enum FontStyle { | ||
/** Set font without style */ | ||
None = 0x0, | ||
/** Set font bold */ | ||
Bold = 0x1, | ||
/** Set font italic */ | ||
Italic = 0x2 | ||
} |
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,23 @@ | ||
/** | ||
* The horizontal alignment of the text. | ||
*/ | ||
export enum TextHorizontalAlignment { | ||
/** Align left horizontally */ | ||
Left = 0, | ||
/** Align center horizontally */ | ||
Center = 1, | ||
/** Align right horizontally */ | ||
Right = 2 | ||
} | ||
|
||
/** | ||
* The vertical alignment of the text. | ||
*/ | ||
export enum TextVerticalAlignment { | ||
/** Align top vertically */ | ||
Top = 0, | ||
/** Align center vertically */ | ||
Center = 1, | ||
/** Align bottom vertically */ | ||
Bottom = 2 | ||
} |
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,9 @@ | ||
/** | ||
* The way to handle the situation where wrapped text is too tall to fit in the height. | ||
*/ | ||
export enum OverflowMode { | ||
/** Overflow when the text is too tall */ | ||
Overflow = 0, | ||
/** Truncate with height when the text is too tall */ | ||
Truncate = 1 | ||
} |
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 |
---|---|---|
@@ -1,4 +1,8 @@ | ||
export { SpriteMaskInteraction } from "./enums/SpriteMaskInteraction"; | ||
export { SpriteMaskLayer } from "./enums/SpriteMaskLayer"; | ||
export { TextHorizontalAlignment, TextVerticalAlignment } from "./enums/TextAlignment"; | ||
export { OverflowMode } from "./enums/TextOverflow"; | ||
export { FontStyle } from "./enums/FontStyle"; | ||
export { SpriteAtlas } from "./atlas/SpriteAtlas"; | ||
export * from "./sprite/index"; | ||
export * from "./text/index"; |
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,45 @@ | ||
import { RefObject } from "../../asset/RefObject"; | ||
import { Engine } from "../../Engine"; | ||
|
||
/** | ||
* Font. | ||
*/ | ||
export class Font extends RefObject { | ||
private static _fontMap: Record<string, Font> = {}; | ||
|
||
/** | ||
* Create a font from OS. | ||
* @param engine - Engine to which the font belongs | ||
* @param fontName - The name of font | ||
* @returns The font object has been create | ||
*/ | ||
static createFromOS(engine: Engine, fontName: string = ""): Font { | ||
const fontMap = Font._fontMap; | ||
let font = fontMap[fontName]; | ||
if (font) { | ||
return font; | ||
} | ||
font = new Font(engine, fontName); | ||
fontMap[fontName] = font; | ||
return font; | ||
} | ||
|
||
private _name: string = ""; | ||
|
||
/** | ||
* The name of the font object. | ||
*/ | ||
get name(): string { | ||
return this._name; | ||
} | ||
|
||
private constructor(engine: Engine, name: string = "") { | ||
super(engine); | ||
this._name = name; | ||
} | ||
|
||
/** | ||
* @override | ||
*/ | ||
protected _onDestroy(): void {} | ||
} |
Oops, something went wrong.