feat: updated music and background handling to support _form_x type background

This commit is contained in:
Haoyu Xu
2025-10-05 20:26:10 +08:00
parent 49a49e5210
commit 33c7553506
8 changed files with 39 additions and 32 deletions

View File

@@ -1,7 +1,6 @@
import path from 'node:path' import path from 'node:path'
import config from '@aklive2d/config' import config from '@aklive2d/config'
import { file } from '@aklive2d/libs' import { file } from '@aklive2d/libs'
import { mapping as musicMapping } from '@aklive2d/music'
import sharp from 'sharp' import sharp from 'sharp'
export const BACKGROUND_DIR = path.join( export const BACKGROUND_DIR = path.join(
@@ -35,7 +34,6 @@ const filesToBuild = file.readdirSync(EXTRACTED_DIR).filter((f) => {
}) })
export const build = async () => { export const build = async () => {
const err = []
file.mkdir(DIST_DIR) file.mkdir(DIST_DIR)
await Promise.all( await Promise.all(
filesToBuild.map(async (f) => { filesToBuild.map(async (f) => {
@@ -47,23 +45,6 @@ export const build = async () => {
DEFAULT_BACKGROUND_FILE, DEFAULT_BACKGROUND_FILE,
path.join(DIST_DIR, config.module.background.operator_bg_png) path.join(DIST_DIR, config.module.background.operator_bg_png)
) )
const { musicFiles, musicFileMapping } = musicMapping
for (const e of musicFiles) {
const musicPath = path.join(e.source, e.filename)
if (!file.exists(musicPath)) {
err.push(`Music file ${e.filename} is not found in music folder.`)
}
}
files = getFiles()
for (const e of Object.keys(musicFileMapping)) {
if (!files.includes(e)) {
err.push(`Background file ${e} is not found in background folder.`)
}
}
return err
} }
const composite = async (filenamePrefix: string, fileExt: string) => { const composite = async (filenamePrefix: string, fileExt: string) => {

View File

@@ -7,8 +7,7 @@
"dependencies": { "dependencies": {
"sharp": "^0.34.4", "sharp": "^0.34.4",
"@aklive2d/libs": "workspace:*", "@aklive2d/libs": "workspace:*",
"@aklive2d/config": "workspace:*", "@aklive2d/config": "workspace:*"
"@aklive2d/music": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=5.9.3" "typescript": ">=5.9.3"

View File

@@ -1,5 +1,5 @@
export const handle = (err: string[]) => { export const handle = (err: string[]) => {
if (err.length > 0) { if (err?.length > 0) {
const str = `${err.length} error${err.length > 1 ? 's were' : ' was'} found:\n${err.join('\n')}` const str = `${err.length} error${err.length > 1 ? 's were' : ' was'} found:\n${err.join('\n')}`
throw new Error(str) throw new Error(str)
} }

View File

@@ -1,6 +1,7 @@
import path from 'node:path' import path from 'node:path'
import config from '@aklive2d/config' import config from '@aklive2d/config'
import { githubDownload } from '@aklive2d/downloader' import { githubDownload } from '@aklive2d/downloader'
import {files as backgroundFiles} from "@aklive2d/background"
import { file } from '@aklive2d/libs' import { file } from '@aklive2d/libs'
import type { import type {
AudioDataTable, AudioDataTable,
@@ -85,6 +86,30 @@ const generateMapping = () => {
} }
} }
for (const e of musicFiles) {
const musicPath = path.join(e.source, e.filename)
if (!file.exists(musicPath)) {
throw new Error(`Music file ${e.filename} is not found in music folder.`)
}
}
for (const e of Object.keys(musicFileMapping)) {
if (!backgroundFiles.includes(e)) {
throw new Error(`Background file ${e} is not found in background folder.`)
}
}
for (const background of backgroundFiles) {
if (!musicFileMapping[background]) {
const alternativeMatch = background.replace(/_(form)(.*)(\.png)$/, "$3")
if (musicFileMapping[alternativeMatch]){
musicFileMapping[background] = structuredClone(musicFileMapping[alternativeMatch])
} else {
throw new Error(`Music mapping for background file ${background} is not found in music mapping.`)
}
}
}
return { return {
musicFiles, musicFiles,
musicFileMapping, musicFileMapping,

View File

@@ -7,7 +7,8 @@
"dependencies": { "dependencies": {
"@aklive2d/libs": "workspace:*", "@aklive2d/libs": "workspace:*",
"@aklive2d/config": "workspace:*", "@aklive2d/config": "workspace:*",
"@aklive2d/downloader": "workspace:*" "@aklive2d/downloader": "workspace:*",
"@aklive2d/background": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=5.9.3" "typescript": ">=5.9.3"

View File

@@ -158,10 +158,10 @@ const generateMapping = () => {
: operatorInfo.skinName['en-US'] : operatorInfo.skinName['en-US']
const skinEntry = findSkinEntry(skinTable, name, type) const skinEntry = findSkinEntry(skinTable, name, type)
operator.filename = skinEntry.dynIllustId.replace(/_2$/, '') operator.filename = skinEntry.dynIllustId.replace(/_2$/, '')
operator.fallback_name = operator.portrait_filename = type === 'skin'
type === 'skin' ? skinEntry.skinId.replace(/@/, '_')
? skinEntry.skinId.replace(/@/, '_') : `${skinEntry.charId}_2`
: `${skinEntry.charId}_2` operator.fallback_name = `${operator.portrait_filename}${operator.isSP ? '_sp' : ''}`
const regions = Object.keys( const regions = Object.keys(
operator.codename operator.codename

View File

@@ -73,9 +73,9 @@ const generateAssets = async (name: string) => {
) as string ) as string
if (!portraitHubContent) throw new Error('portrait_hub.json not found') if (!portraitHubContent) throw new Error('portrait_hub.json not found')
const portraitHub: PortraitHub = JSON.parse(portraitHubContent) const portraitHub: PortraitHub = JSON.parse(portraitHubContent)
const fallback_name_lowerCase = fallback_name.toLowerCase() const portrait_filename_lowerCase = operators[name].portrait_filename.toLowerCase()
const portraitItem = portraitHub._sprites.find( const portraitItem = portraitHub._sprites.find(
(item) => item.name.toLowerCase() === fallback_name_lowerCase (item) => item.name.toLowerCase() === portrait_filename_lowerCase
) )
if (!portraitItem) throw new Error(`portrait ${fallback_name} not found`) if (!portraitItem) throw new Error(`portrait ${fallback_name} not found`)
const portraitAtlas = portraitItem.atlas const portraitAtlas = portraitItem.atlas
@@ -90,7 +90,7 @@ const generateAssets = async (name: string) => {
throw new Error(`portrait ${fallback_name} json not found`) throw new Error(`portrait ${fallback_name} json not found`)
const portraitJson: PortraitJson = JSON.parse(portraitJsonText) const portraitJson: PortraitJson = JSON.parse(portraitJsonText)
const item = portraitJson._sprites.find( const item = portraitJson._sprites.find(
(item) => item.name.toLowerCase() === fallback_name_lowerCase (item) => item.name.toLowerCase() === portrait_filename_lowerCase
) )
if (!item) throw new Error(`portrait ${fallback_name} not found`) if (!item) throw new Error(`portrait ${fallback_name} not found`)
const rect = { const rect = {

View File

@@ -6,6 +6,7 @@ export interface OperatorConfig {
filename: string filename: string
logo: string logo: string
fallback_name: string fallback_name: string
portrait_filename: string
viewport_left: number // should be default to 0 in the future viewport_left: number // should be default to 0 in the future
viewport_right: number viewport_right: number
viewport_top: number viewport_top: number