@osbjs/osbjs
Version:
a minimalist osu! storyboarding framework
207 lines (206 loc) • 8.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAudioFilename = exports.parseTimingPoints = exports.parseDifficulty = exports.parseHitObjects = exports.parseColors = exports.parseMetadata = void 0;
const Core_1 = require("../../Core");
const Math_1 = require("../../Math");
const HitObjects_1 = require("../HitObjects");
function parseMetadata(raw) {
const title = raw.match(/(?<=Title:)(.*)/);
const artist = raw.match(/(?<=Artist:)(.*)/);
const creator = raw.match(/(?<=Creator:)(.*)/);
const difficulty = raw.match(/(?<=Version:)(.*)/);
return {
title: title[0],
artist: artist[0],
creator: creator[0],
difficulty: difficulty[0],
};
}
exports.parseMetadata = parseMetadata;
function parseColors(raw) {
if (raw.match(/\[Colours\]/)) {
let colors = [];
const matches = raw.match(/(?<=Combo[0-9]+ : )(.*)/g);
if (matches) {
for (let i = 0; i < matches.length; i++) {
const c = matches[i].split(',');
colors.push(new Core_1.OsbColor(parseInt(c[0]), parseInt(c[1]), parseInt(c[2])));
}
return colors;
}
}
return [new Core_1.OsbColor(255, 192, 0), new Core_1.OsbColor(0, 202, 0), new Core_1.OsbColor(18, 124, 255), new Core_1.OsbColor(242, 24, 57)];
}
exports.parseColors = parseColors;
function parseHitObjects(raw) {
let a = raw
.match(/(?<=\[HitObjects]\r*\n)(.+\r*\n)+/g)
?.toString()
.trim();
if (!a)
return { spinners: [], sliders: [], circles: [] };
let spinners = parseSpinner(a).sort((a, b) => a.startTime - b.startTime);
let sliders = parseSlider(a, raw).sort((a, b) => a.startTime - b.startTime);
let circles = parseCircle(a).sort((a, b) => a.startTime - b.startTime);
return { spinners, sliders, circles };
}
exports.parseHitObjects = parseHitObjects;
function parseSlider(rawHitObjects, raw) {
let sliders = [];
let sliderPattern = /-*\d+,-*\d+,-*\d+,\d+,\d+,(L|B|C|P)(\|-*\d+:-*\d+)+,\d+,\d+\.*\d*(,\d+(\|\d*)*,\d+:\d+(\|\d+:\d+)*,\d+:\d+:\d+:\d+:\w*)*/g;
let sArr = rawHitObjects.match(sliderPattern);
if (sArr) {
for (const sLine of sArr) {
let sAttr = sLine.split(',');
let x = parseInt(sAttr[0]);
let y = parseInt(sAttr[1]);
let startTime = parseInt(sAttr[2]);
let hitsound = parseInt(sAttr[4]);
let curves = sAttr[5].split('|');
let curveType = curves[0];
let curvePoints = curves.slice(1).map((cp) => new Math_1.Vector2(parseInt(cp.split(':')[0]), parseInt(cp.split(':')[1])));
let slides = parseInt(sAttr[6]);
let length = parseInt(sAttr[7]);
let edgeSounds = sAttr[8] ? sAttr[8].split('|').map((es) => parseInt(es)) : [];
let edgeSets = sAttr[9]
? sAttr[9].split('|').map((es) => {
let hs = es.split(':');
return {
normalSet: parseInt(hs[0]),
additionSet: parseInt(hs[1]),
index: undefined,
volume: undefined,
filename: undefined,
};
})
: [];
let params = {
curveType,
curvePoints,
slides,
length,
edgeSounds,
edgeSets,
};
let hs = sAttr[10] ? sAttr[10].split(':') : ['0', '0', '0', '0', ''];
let hitSample = {
normalSet: parseInt(hs[0]),
additionSet: parseInt(hs[1]),
index: parseInt(hs[2]),
volume: parseInt(hs[3]),
filename: hs[4],
};
const timingPoints = parseTimingPoints(raw);
const { sliderMultiplier } = parseDifficulty(raw);
let currentTimingPoint = timingPoints
.filter((tPoint) => tPoint.time <= startTime && tPoint.uninherited)
.sort((t1, t2) => t2.time - t1.time)[0];
let currentMultipliers = timingPoints
.filter((tPoint) => tPoint.time <= startTime && !tPoint.uninherited && tPoint.time >= currentTimingPoint.time)
.sort((t1, t2) => t2.time - t1.time);
let currentMultiplier = currentMultipliers.length ? -currentMultipliers[0].beatLength / 100 : 1;
let slider = new HitObjects_1.Slider(x, y, startTime, hitsound, hitSample, params, sliderMultiplier, currentTimingPoint, currentMultiplier);
sliders.push(slider);
}
}
return sliders;
}
function parseSpinner(raw) {
let spinners = [];
let spinnerPattern = /(?<=,)(-*\d+,-*\d+,-*\d+,\d+,\d+,\d+:\d+:\d+:\d+:\w*)/g;
let sArr = raw.match(spinnerPattern);
if (sArr) {
for (const sLine of sArr) {
let sAttr = sLine.split(',');
let startTime = parseInt(sAttr[2]);
let endTime = parseInt(sAttr[5]);
let hitsound = parseInt(sAttr[4]);
let hs = sAttr[6] ? sAttr[6].split(':') : ['0', '0', '0', '0', ''];
let hitSample = {
normalSet: parseInt(hs[0]),
additionSet: parseInt(hs[1]),
index: parseInt(hs[2]),
volume: parseInt(hs[3]),
filename: hs[4],
};
let spinner = new HitObjects_1.Spinner(startTime, endTime, hitsound, hitSample);
spinners.push(spinner);
}
}
return spinners;
}
function parseCircle(raw) {
let circles = [];
let circlePattern = /-*\d+,-*\d+,-*\d+,\d+,\d+,\d+:\d+:\d+:\d+:\w*/g;
let cArr = raw.match(circlePattern);
if (cArr) {
for (const cLine of cArr) {
let cAttr = cLine.split(',');
let x = parseInt(cAttr[0]);
let y = parseInt(cAttr[1]);
let startTime = parseInt(cAttr[2]);
let hitsound = parseInt(cAttr[4]);
let hs = cAttr[5].split(':');
let hitSample = {
normalSet: parseInt(hs[0]),
additionSet: parseInt(hs[1]),
index: parseInt(hs[2]),
volume: parseInt(hs[3]),
filename: hs[4],
};
let circle = new HitObjects_1.Circle(x, y, startTime, hitsound, hitSample);
circles.push(circle);
}
}
return circles;
}
function parseDifficulty(raw) {
const hp = raw.match(/(?<=HPDrainRate:)(.*)/);
const circleSize = raw.match(/(?<=CircleSize:)(.*)/);
const overallDifficulty = raw.match(/(?<=OverallDifficulty:)(.*)/);
const approachRate = raw.match(/(?<=ApproachRate:)(.*)/);
const sliderMultiplier = raw.match(/(?<=SliderMultiplier:)(.*)/);
const sliderTickRate = raw.match(/(?<=SliderTickRate:)(.*)/);
return {
hp: parseFloat(hp[0]),
circleSize: parseFloat(circleSize[0]),
overallDifficulty: parseFloat(overallDifficulty[0]),
approachRate: parseFloat(approachRate[0]),
sliderMultiplier: parseFloat(sliderMultiplier[0]),
sliderTickRate: parseFloat(sliderTickRate[0]),
};
}
exports.parseDifficulty = parseDifficulty;
function parseTimingPoints(raw) {
let tArr = raw
.match(/(?<=\[TimingPoints]\r*\n)(.+\r*\n)+/g)
?.toString()
.trim()
.match(/-*\d+,-*\d+\.*\d*,\d+,\d+,\d+,\d+,\d+,\d+/g);
let timingPoints = [];
if (tArr) {
for (const tLine of tArr) {
let tAttr = tLine.split(',');
let timingPoint = {
time: parseInt(tAttr[0]),
beatLength: parseFloat(tAttr[1]),
meter: parseInt(tAttr[2]),
sampleSet: parseInt(tAttr[3]),
sampleIndex: parseInt(tAttr[4]),
volume: parseInt(tAttr[5]),
uninherited: tAttr[6] === '1',
kiai: parseInt(tAttr[7], 10).toString(2) == '1',
};
timingPoints.push(timingPoint);
}
}
return timingPoints;
}
exports.parseTimingPoints = parseTimingPoints;
function getAudioFilename(raw) {
let res = raw.match(/AudioFilename: .+/g);
if (!res)
return '';
return res.toString().replace('AudioFilename: ', '');
}
exports.getAudioFilename = getAudioFilename;