@osbjs/osbjs
Version:
a minimalist osu! storyboarding framework
93 lines (92 loc) • 4.76 kB
JavaScript
"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;