UNPKG

@osbjs/osbjs

Version:

a minimalist osu! storyboarding framework

93 lines (92 loc) 4.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Lyrics = void 0; const Core_1 = require("../Core"); const TxtGen_1 = require("../TxtGen"); class Lyrics extends Core_1.Component { /** * Generate lyrics from a .srt/.vtt/.json file. * @param folderPath full path to beatmap folder. * @param osbFolderPath relative path to the folder that will be used to save generated text images. For example: `sb/lyrics`. * @param subtitlePath full path to the subtitle file. For example, `./lyrics.srt` if your lyrics file is same folder with your script file. * @param options Additional options. * @param registerFontOptions In case you want to use a non-system font. */ constructor(folderPath, osbFolderPath, subtitlePath, options, registerFontOptions) { super(); this.name = 'Lyrics'; this.options = { fadeDuration: 200, opacity: 1, fontName: 'Arial', fontSize: 72, fontScale: 1, perCharacter: false, y: 400, additive: true, color: { r: 255, g: 255, b: 255, }, }; this.folderPath = folderPath; this.osbFolderPath = osbFolderPath; this.options = { ...this.options, ...options }; this._textureGenerator = new TxtGen_1.TextureGenerator(folderPath, osbFolderPath, { fontName: this.options.fontName, fontSize: this.options.fontSize }); if (registerFontOptions) this._textureGenerator.registerFont(registerFontOptions.fontPath, registerFontOptions.family); this._subtitleCollection = new Core_1.SubtitleCollection(subtitlePath); } generate() { if (this.options.perCharacter) { this._generatePerChar(); } else { this._generatePerLine(); } } _generatePerChar() { this._subtitleCollection.subtitles.forEach((subtitle) => { let letterY = this.options.y; subtitle.text.split('\n').forEach((line) => { let lineWidth = 0, lineHeight = 0; for (let i = 0; i < line.length; i++) { const letter = line[i]; let { width, height } = this._textureGenerator.getTextDimensions(letter, {}, true); lineWidth += width * this.options.fontScale; lineHeight = Math.max(lineHeight, height * this.options.fontScale); } let letterX = 320 - lineWidth * 0.5; for (let i = 0; i < line.length; i++) { const letter = line[i]; let texture = this._textureGenerator.generateTexture(letter, this.options.color, {}, true); let position = new Core_1.OsbVector2(letterX, letterY); let sprite = new Core_1.Sprite(texture.osbPath, Core_1.Layer.Background, Core_1.Origin.TopLeft, position); sprite.ScaleAtTime(subtitle.startTime, this.options.fontScale); sprite.Fade(subtitle.startTime - this.options.fadeDuration, subtitle.startTime, 0, this.options.opacity); sprite.Fade(subtitle.endTime - this.options.fadeDuration, subtitle.endTime, this.options.opacity, 0); if (this.options.additive) sprite.Parameter(subtitle.startTime - this.options.fadeDuration, subtitle.endTime, Core_1.Parameter.AdditiveBlending); this.registerComponents(sprite); letterX += texture.width * this.options.fontScale; } letterY += lineHeight; }); }); } _generatePerLine() { this._subtitleCollection.subtitles.forEach((line) => { let texture = this._textureGenerator.generateTexture(line.text, this.options.color); let position = new Core_1.OsbVector2(320, this.options.y); let sprite = new Core_1.Sprite(texture.osbPath, Core_1.Layer.Background, Core_1.Origin.Center, position); sprite.ScaleAtTime(line.startTime, this.options.fontScale); sprite.Fade(line.startTime - this.options.fadeDuration, line.startTime, 0, this.options.opacity); sprite.Fade(line.endTime - this.options.fadeDuration, line.endTime, this.options.opacity, 0); if (this.options.additive) sprite.Parameter(line.startTime - this.options.fadeDuration, line.endTime, Core_1.Parameter.AdditiveBlending); this.registerComponents(sprite); }); } } exports.Lyrics = Lyrics;