feat(showcase): init operator voices
This commit is contained in:
@@ -2,6 +2,7 @@ folder:
|
|||||||
operator: ./operator/
|
operator: ./operator/
|
||||||
release: ./release/
|
release: ./release/
|
||||||
background: background
|
background: background
|
||||||
|
voice: voice
|
||||||
directory: _assets
|
directory: _assets
|
||||||
share: _share
|
share: _share
|
||||||
operators:
|
operators:
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ export default class Settings {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="operator_logo">Operator Logo</label>
|
<label for="operator_logo">Operator Logo</label>
|
||||||
<input type="checkbox" id="operator_logo" name="operator_logo" checked data-checked="true"/>
|
<input type="checkbox" id="operator_logo" name="operator_logo" checked/>
|
||||||
<div id="operator_logo_realted">
|
<div id="operator_logo_realted">
|
||||||
<div>
|
<div>
|
||||||
<label for="logo_image">Logo Image (Store Locally)</label>
|
<label for="logo_image">Logo Image (Store Locally)</label>
|
||||||
@@ -311,9 +311,7 @@ export default class Settings {
|
|||||||
<div>
|
<div>
|
||||||
<label for="default_background_select">Choose a default background:</label>
|
<label for="default_background_select">Choose a default background:</label>
|
||||||
<select name="default_backgrounds" id="default_background_select">
|
<select name="default_backgrounds" id="default_background_select">
|
||||||
${JSON.parse(import.meta.env.VITE_BACKGROUND_FILES).map((b) => {
|
${this.#updateOptions(null, JSON.parse(import.meta.env.VITE_BACKGROUND_FILES))}
|
||||||
return `<option value="${b}">${b}</option>`
|
|
||||||
})}
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -322,6 +320,42 @@ export default class Settings {
|
|||||||
<button type="button" disabled id="custom_background_clear" disabled>Clear</button>
|
<button type="button" disabled id="custom_background_clear" disabled>Clear</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="voice">Voice</label>
|
||||||
|
<input type="checkbox" id="voice" name="voice" checked/>
|
||||||
|
<div id="voice_realted">
|
||||||
|
<div>
|
||||||
|
<label for="voice_lang_select">Choose the language of voice:</label>
|
||||||
|
<select name="voice_lang" id="voice_lang_select">
|
||||||
|
${this.#updateOptions("voice_lang_select", window.voice.languages)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="voice_idle_duration">Idle Duration (min)</label>
|
||||||
|
<input type="number" id="voice_idle_duration_input" min="0" name="voice_idle_duration" value="${window.voice.idleDuration}" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="voice_next_duration">Next Duration (min)</label>
|
||||||
|
<input type="number" id="voice_next_duration_input" name="voice_next_duration" value="${window.voice.nextDuration}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="subtitle">Subtitle</label>
|
||||||
|
<input type="checkbox" id="subtitle" name="subtitle" checked/>
|
||||||
|
<div id="subtitle_realted">
|
||||||
|
<div>
|
||||||
|
<label for="subtitle_lang_select">Choose the language of subtitle:</label>
|
||||||
|
<select name="subtitle_lang" id="subtitle_lang_select">
|
||||||
|
${this.#updateOptions("subtitle_lang_select", window.voice.subtitleLanguages)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="voice_actor">Voice Actor</label>
|
||||||
|
<input type="checkbox" id="voice_actor" name="voice_actor" checked/>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="position">Position</label>
|
<label for="position">Position</label>
|
||||||
<input type="checkbox" id="position" name="position" />
|
<input type="checkbox" id="position" name="position" />
|
||||||
@@ -372,123 +406,182 @@ export default class Settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#updateOptions(id, array) {
|
||||||
|
const e = document.getElementById(id);
|
||||||
|
const value = array.map(item => `<option value="${item}">${item}</option>`)
|
||||||
|
if (e) {
|
||||||
|
e.innerHTML = value.join("");
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
#addEventListeners() {
|
#addEventListeners() {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
const listeners = [
|
||||||
document.getElementById("fps_slider").addEventListener("change", e => {
|
{
|
||||||
|
id: "fps_slider", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "fps_input");
|
_this.#sync(e.currentTarget, "fps_input");
|
||||||
_this.setFPS(e.currentTarget.value);
|
_this.setFPS(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("fps_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "fps_slider", event: "input", handler: e => {
|
||||||
|
_this.#sync(e.currentTarget, "fps_input");
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "fps_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "fps_slider");
|
_this.#sync(e.currentTarget, "fps_slider");
|
||||||
_this.setFPS(e.currentTarget.value);
|
_this.setFPS(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("operator_logo").addEventListener("click", e => {
|
id: "operator_logo", event: "click", handler: e => {
|
||||||
_this.#showRelated(e.currentTarget, "operator_logo_realted");
|
_this.#showRelated(e.currentTarget, "operator_logo_realted");
|
||||||
_this.setLogoDisplay(!e.currentTarget.checked)
|
_this.setLogoDisplay(!e.currentTarget.checked)
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("logo_image").addEventListener("change", e => _this.setLogoImage(e))
|
id: "logo_image", event: "change", handler: e => _this.setLogoImage(e)
|
||||||
document.getElementById("logo_image_clear").addEventListener("click", e => this.resetLogoImage())
|
}, {
|
||||||
|
id: "logo_image_clear", event: "click", handler: e => _this.resetLogoImage()
|
||||||
document.getElementById("logo_ratio_slider").addEventListener("input", e => {
|
}, {
|
||||||
|
id: "logo_ratio_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_ratio_input");
|
_this.#sync(e.currentTarget, "logo_ratio_input");
|
||||||
_this.setLogoRatio(e.currentTarget.value);
|
_this.setLogoRatio(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("logo_ratio_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "logo_ratio_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_ratio_slider");
|
_this.#sync(e.currentTarget, "logo_ratio_slider");
|
||||||
_this.setLogoRatio(e.currentTarget.value);
|
_this.setLogoRatio(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("logo_opacity_slider").addEventListener("input", e => {
|
id: "logo_opacity_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_opacity_input");
|
_this.#sync(e.currentTarget, "logo_opacity_input");
|
||||||
_this.setLogoOpacity(e.currentTarget.value);
|
_this.setLogoOpacity(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("logo_opacity_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "logo_opacity_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_opacity_slider");
|
_this.#sync(e.currentTarget, "logo_opacity_slider");
|
||||||
_this.setLogoOpacity(e.currentTarget.value);
|
_this.setLogoOpacity(e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("logo_padding_x_slider").addEventListener("input", e => {
|
id: "logo_padding_x_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_padding_x_input");
|
_this.#sync(e.currentTarget, "logo_padding_x_input");
|
||||||
_this.logoPadding("x", e.currentTarget.value);
|
_this.logoPadding("x", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("logo_padding_x_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "logo_padding_x_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_padding_x_slider");
|
_this.#sync(e.currentTarget, "logo_padding_x_slider");
|
||||||
_this.logoPadding("x", e.currentTarget.value);
|
_this.logoPadding("x", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("logo_padding_y_slider").addEventListener("input", e => {
|
id: "logo_padding_y_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_padding_y_input");
|
_this.#sync(e.currentTarget, "logo_padding_y_input");
|
||||||
_this.logoPadding("y", e.currentTarget.value);
|
_this.logoPadding("y", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("logo_padding_y_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "logo_padding_y_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "logo_padding_y_slider");
|
_this.#sync(e.currentTarget, "logo_padding_y_slider");
|
||||||
_this.logoPadding("y", e.currentTarget.value);
|
_this.logoPadding("y", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById('default_background_select').addEventListener("change", e => _this.setDefaultBackground(e.currentTarget.value))
|
id: "default_background_select", event: "change", handler: e => _this.setDefaultBackground(e.currentTarget.value)
|
||||||
|
}, {
|
||||||
document.getElementById("custom_background").addEventListener("change", e => _this.setBackground(e))
|
id: "custom_background", event: "change", handler: e => _this.setBackground(e)
|
||||||
document.getElementById("custom_background_clear").addEventListener("click", e => _this.resetBackground())
|
}, {
|
||||||
|
id: "custom_background_clear", event: "click", handler: e => _this.resetBackground()
|
||||||
document.getElementById("position").addEventListener("click", e => {
|
}, {
|
||||||
|
id: "voice", event: "click", handler: e => {
|
||||||
|
_this.#showRelated(e.currentTarget, "voice_realted");
|
||||||
|
window.voice.useVoice = e.currentTarget.checked;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "voice_lang_select", event: "change", handler: e => {
|
||||||
|
window.voice.language = e.currentTarget.value
|
||||||
|
_this.#updateOptions("subtitle_lang_select", window.voice.subtitleLanguages)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "voice_idle_duration_input", event: "change", handler: e => {
|
||||||
|
window.voice.idleDuration = parseInt(e.currentTarget.value)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "voice_next_duration_input", event: "change", handler: e => {
|
||||||
|
window.voice.nextDuration = parseInt(e.currentTarget.value)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "subtitle", event: "click", handler: e => {
|
||||||
|
_this.#showRelated(e.currentTarget, "subtitle_realted");
|
||||||
|
window.voice.useSubtitle = e.currentTarget.checked;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "subtitle_lang_select", event: "change", handler: e => window.voice.subtitleLanguage = e.currentTarget.value
|
||||||
|
}, {
|
||||||
|
id: "voice_actor", event: "click", handler: e => {
|
||||||
|
window.voice.useVoiceActor = e.currentTarget.checked;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: "position", event: "click", handler: e => {
|
||||||
_this.#showRelated(e.currentTarget, "position_realted");
|
_this.#showRelated(e.currentTarget, "position_realted");
|
||||||
if (!e.currentTarget.checked) _this.positionReset();
|
if (!e.currentTarget.checked) _this.positionReset();
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("position_padding_left_slider").addEventListener("input", e => {
|
id: "position_padding_left_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_left_input");
|
_this.#sync(e.currentTarget, "position_padding_left_input");
|
||||||
_this.positionPadding("left", e.currentTarget.value);
|
_this.positionPadding("left", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("position_padding_left_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "position_padding_left_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_left_slider");
|
_this.#sync(e.currentTarget, "position_padding_left_slider");
|
||||||
_this.positionPadding("left", e.currentTarget.value);
|
_this.positionPadding("left", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("position_padding_right_slider").addEventListener("input", e => {
|
id: "position_padding_right_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_right_input");
|
_this.#sync(e.currentTarget, "position_padding_right_input");
|
||||||
_this.positionPadding("right", e.currentTarget.value);
|
_this.positionPadding("right", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("position_padding_right_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "position_padding_right_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_right_slider");
|
_this.#sync(e.currentTarget, "position_padding_right_slider");
|
||||||
_this.positionPadding("right", e.currentTarget.value);
|
_this.positionPadding("right", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("position_padding_top_slider").addEventListener("input", e => {
|
id: "position_padding_top_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_top_input");
|
_this.#sync(e.currentTarget, "position_padding_top_input");
|
||||||
_this.positionPadding("top", e.currentTarget.value);
|
_this.positionPadding("top", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("position_padding_top_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "position_padding_top_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_top_slider");
|
_this.#sync(e.currentTarget, "position_padding_top_slider");
|
||||||
_this.positionPadding("top", e.currentTarget.value);
|
_this.positionPadding("top", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("position_padding_bottom_slider").addEventListener("input", e => {
|
id: "position_padding_bottom_slider", event: "input", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_bottom_input");
|
_this.#sync(e.currentTarget, "position_padding_bottom_input");
|
||||||
_this.positionPadding("bottom", e.currentTarget.value);
|
_this.positionPadding("bottom", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
document.getElementById("position_padding_bottom_input").addEventListener("change", e => {
|
}, {
|
||||||
|
id: "position_padding_bottom_input", event: "change", handler: e => {
|
||||||
_this.#sync(e.currentTarget, "position_padding_bottom_slider");
|
_this.#sync(e.currentTarget, "position_padding_bottom_slider");
|
||||||
_this.positionPadding("bottom", e.currentTarget.value);
|
_this.positionPadding("bottom", e.currentTarget.value);
|
||||||
})
|
}
|
||||||
|
}, {
|
||||||
document.getElementById("settings_play").addEventListener("click", e => {
|
id: "settings_play", event: "click", handler: e => {
|
||||||
this.spinePlayer.play();
|
this.spinePlayer.play();
|
||||||
e.currentTarget.disabled = true;
|
e.currentTarget.disabled = true;
|
||||||
document.getElementById("settings_pause").disabled = false;
|
document.getElementById("settings_pause").disabled = false;
|
||||||
})
|
}
|
||||||
document.getElementById("settings_pause").addEventListener("click", e => {
|
}, {
|
||||||
|
id: "settings_pause", event: "click", handler: e => {
|
||||||
this.spinePlayer.pause();
|
this.spinePlayer.pause();
|
||||||
e.currentTarget.disabled = true;
|
e.currentTarget.disabled = true;
|
||||||
document.getElementById("settings_play").disabled = false;
|
document.getElementById("settings_play").disabled = false;
|
||||||
})
|
}
|
||||||
document.getElementById("settings_reset").addEventListener("click", e => {
|
}, {
|
||||||
_this.reset();
|
id: "settings_reset", event: "click", handler: e => _this.reset()
|
||||||
})
|
}, {
|
||||||
document.getElementById("settings_close").addEventListener("click", e => {
|
id: "settings_close", event: "click", handler: e => _this.close()
|
||||||
_this.close();
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
listeners.forEach(listener => {
|
||||||
|
document.getElementById(listener.id).addEventListener(listener.event, e => listener.handler(e))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,254 @@
|
|||||||
import charword_table from '!/charword_table.json'
|
import charword_table from '!/charword_table.json'
|
||||||
import '@/components/voice.css'
|
import '@/components/voice.css'
|
||||||
|
|
||||||
export default function Voice() {
|
export default class Voice {
|
||||||
|
#el
|
||||||
|
#defaultVoiceLang = "JP"
|
||||||
|
#defaultRegion = charword_table.config.default_region
|
||||||
|
#defaultIdleDuration = 10 * 60 * 1000
|
||||||
|
#defaultNextDuration = 3 * 60 * 1000
|
||||||
|
#voiceLang = this.#defaultVoiceLang
|
||||||
|
#subtitleLang = this.#defaultRegion
|
||||||
|
#useSubtitle = false
|
||||||
|
#useVoice = false
|
||||||
|
#useVoiceActor = false
|
||||||
|
#currentVoiceId = null
|
||||||
|
#lastVoiceId = null
|
||||||
|
#idleListener = -1
|
||||||
|
#idleDuration = this.#defaultIdleDuration
|
||||||
|
#nextListener = -1
|
||||||
|
#nextDuration = this.#defaultNextDuration
|
||||||
|
#lastClickToNext = false
|
||||||
|
|
||||||
|
constructor(el) {
|
||||||
|
this.#el = el
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.#playTitleVoice()
|
||||||
|
}
|
||||||
|
|
||||||
|
success() {
|
||||||
|
this.#playEntryVoice()
|
||||||
|
this.#initNextVoiceTimer()
|
||||||
|
document.addEventListener('click', e => {
|
||||||
|
this.#lastClickToNext = true
|
||||||
|
this.#nextVoice()
|
||||||
|
})
|
||||||
|
document.addEventListener('mousemove', e => {
|
||||||
|
if (this.#idleListener === -1) {
|
||||||
|
this.#initIdleVoiceTimer()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} show
|
||||||
|
*/
|
||||||
|
set useSubtitle(show) {
|
||||||
|
this.#useSubtitle = show
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} show
|
||||||
|
*/
|
||||||
|
set useVoice(show) {
|
||||||
|
this.#useVoice = show
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} show
|
||||||
|
*/
|
||||||
|
set useVoiceActor(show) {
|
||||||
|
this.#useVoiceActor = show
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} lang
|
||||||
|
*/
|
||||||
|
set subtitleLanguage(lang) {
|
||||||
|
if (this.#getSubtitleLanguages().includes(lang)) {
|
||||||
|
this.#subtitleLang = lang
|
||||||
|
} else {
|
||||||
|
this.#subtitleLang = this.#defaultRegion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get subtitleLanguage() {
|
||||||
|
return this.#subtitleLang
|
||||||
|
}
|
||||||
|
|
||||||
|
get subtitleLanguages() {
|
||||||
|
return this.#getSubtitleLanguages()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} lang
|
||||||
|
*/
|
||||||
|
set language(lang) {
|
||||||
|
if (this.#getVoiceLanguages().includes(lang)) {
|
||||||
|
this.#voiceLang = lang
|
||||||
|
} else {
|
||||||
|
this.#voiceLang = this.#defaultVoiceLang
|
||||||
|
}
|
||||||
|
const availableSubtitleLang = this.#getSubtitleLanguages()
|
||||||
|
if (!availableSubtitleLang.includes(this.#subtitleLang)) {
|
||||||
|
this.#subtitleLang = availableSubtitleLang[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get language() {
|
||||||
|
return this.#voiceLang
|
||||||
|
}
|
||||||
|
|
||||||
|
get languages() {
|
||||||
|
return this.#getVoiceLanguages()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {int} duration
|
||||||
|
*/
|
||||||
|
set idleDuration(duration) {
|
||||||
|
clearInterval(this.#idleListener)
|
||||||
|
if (duration !== 0) {
|
||||||
|
this.#idleDuration = duration * 60 * 1000
|
||||||
|
this.#initIdleVoiceTimer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get idleDuration() {
|
||||||
|
return this.#idleDuration / 60 / 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {int} duration
|
||||||
|
*/
|
||||||
|
set nextDuration(duration) {
|
||||||
|
clearInterval(this.#nextListener)
|
||||||
|
if (duration !== 0) {
|
||||||
|
this.#nextDuration = duration * 1000
|
||||||
|
this.#initNextVoiceTimer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get nextDuration() {
|
||||||
|
return this.#nextDuration / 60 / 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
#playTitleVoice() {
|
||||||
|
this.#playSpecialVoice("标题")
|
||||||
|
}
|
||||||
|
|
||||||
|
#initIdleVoiceTimer() {
|
||||||
|
this.#idleListener = setInterval(() => {
|
||||||
|
this.#playSpecialVoice("闲置")
|
||||||
|
clearInterval(this.#idleListener)
|
||||||
|
this.#idleListener = -1
|
||||||
|
}, this.#idleDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
#initNextVoiceTimer() {
|
||||||
|
this.#nextListener = setInterval(() => {
|
||||||
|
if (!this.#lastClickToNext) {
|
||||||
|
this.#nextVoice()
|
||||||
|
}
|
||||||
|
}, this.#nextDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
#nextVoice() {
|
||||||
|
this.#playVoice("CN_001")
|
||||||
|
}
|
||||||
|
|
||||||
|
#playEntryVoice() {
|
||||||
|
this.#playSpecialVoice("问候")
|
||||||
|
}
|
||||||
|
|
||||||
|
#setCurrentSubtitle(id) {
|
||||||
|
console.log(id, this.#getSubtitleById(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
#playVoice(id) {
|
||||||
|
this.#currentVoiceId = id
|
||||||
|
const audio = new Audio()
|
||||||
|
// audio.src = `https://cdn.jsdelivr.net/gh/Arondight/Adachi-BOT@master/src/assets/voice/${id}.mp3`
|
||||||
|
audio.play()
|
||||||
|
audio.addEventListener('ended', () => {
|
||||||
|
this.#lastVoiceId = this.#currentVoiceId
|
||||||
|
this.#currentVoiceId = null
|
||||||
|
this.#setCurrentSubtitle(null)
|
||||||
|
this.#lastClickToNext = false
|
||||||
|
})
|
||||||
|
this.#setCurrentSubtitle(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#playSpecialVoice(matcher) {
|
||||||
|
const voiceId = this.#getSpecialVoiceId(matcher)
|
||||||
|
this.#playVoice(voiceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
#getSpecialVoiceId(matcher) {
|
||||||
|
const voices = this.#getVoices()
|
||||||
|
const voiceId = Object.keys(voices).find(e => voices[e].title === matcher)
|
||||||
|
return voiceId
|
||||||
|
}
|
||||||
|
|
||||||
|
#getVoices() {
|
||||||
|
return charword_table.operator.voice[this.#defaultRegion][this.#getWordKeyByVoiceLang()[this.#defaultVoiceLang]]
|
||||||
|
}
|
||||||
|
|
||||||
|
#getSubtitleById(id) {
|
||||||
|
return charword_table.operator.voice[this.#subtitleLang][this.#getWordKeyByVoiceLang()[this.#voiceLang]][id]
|
||||||
|
}
|
||||||
|
|
||||||
|
#getVoiceLanguages() {
|
||||||
|
return Object.keys(this.#getCVInfo(this.#defaultRegion))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the cvInfo in the region's language
|
||||||
|
*/
|
||||||
|
#getCVInfo(region) {
|
||||||
|
const infoArray = Object.values(charword_table.operator.info[region])
|
||||||
|
// combine the infoArray
|
||||||
|
let output = {}
|
||||||
|
for (const info of infoArray) {
|
||||||
|
output = {
|
||||||
|
...output,
|
||||||
|
...info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the cvInfo corresponsing to the voice language
|
||||||
|
*/
|
||||||
|
#getCVInfoByVoiceLang() {
|
||||||
|
const languages = {}
|
||||||
|
for (const lang of Object.keys(charword_table.operator.info)) {
|
||||||
|
const cvInfo = this.#getCVInfo(lang)
|
||||||
|
for (const [voiceLanguage, cvArray] of Object.entries(cvInfo)) {
|
||||||
|
if (languages[voiceLanguage] === undefined) {
|
||||||
|
languages[voiceLanguage] = {}
|
||||||
|
}
|
||||||
|
languages[voiceLanguage][lang] = cvArray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return languages
|
||||||
|
}
|
||||||
|
|
||||||
|
#getWordKeyByVoiceLang() {
|
||||||
|
const output = {}
|
||||||
|
for (const [wordKey, wordKeyDict] of Object.entries(charword_table.operator.info[this.#defaultRegion])) {
|
||||||
|
for (const lang of Object.keys(wordKeyDict)) {
|
||||||
|
output[lang] = wordKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
#getSubtitleLanguages() {
|
||||||
|
return Object.keys(this.#getCVInfoByVoiceLang()[this.#voiceLang])
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import '@/index.css'
|
|||||||
import '@/libs/wallpaper_engine'
|
import '@/libs/wallpaper_engine'
|
||||||
import check_web_gl from '@/libs/check_web_gl'
|
import check_web_gl from '@/libs/check_web_gl'
|
||||||
import Settings from '@/components/settings'
|
import Settings from '@/components/settings'
|
||||||
|
import Voice from '@/components/voice'
|
||||||
|
|
||||||
document.querySelector('#app').innerHTML = `
|
document.querySelector('#app').innerHTML = `
|
||||||
<img src="./assets/${import.meta.env.VITE_LOGO_FILENAME}.png" class="logo invert-filter" id="logo" alt="operator logo" />
|
<img src="./assets/${import.meta.env.VITE_LOGO_FILENAME}.png" class="logo invert-filter" id="logo" alt="operator logo" />
|
||||||
@@ -12,9 +13,11 @@ document.querySelector('#app').innerHTML = `
|
|||||||
hidden
|
hidden
|
||||||
></div>
|
></div>
|
||||||
<div id="player" hidden></div>
|
<div id="player" hidden></div>
|
||||||
|
<div id="voice" hidden></div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
window.voice = new Voice(document.querySelector('#voice'))
|
||||||
|
window.voice.init()
|
||||||
window.settings = new Settings(document.querySelector('#settings'), document.querySelector('#logo'))
|
window.settings = new Settings(document.querySelector('#settings'), document.querySelector('#logo'))
|
||||||
document.title = import.meta.env.VITE_TITLE
|
document.title = import.meta.env.VITE_TITLE
|
||||||
console.log("All resources are extracted from Arknights. Github: https://github.com/Halyul/aklive2d")
|
console.log("All resources are extracted from Arknights. Github: https://github.com/Halyul/aklive2d")
|
||||||
|
|||||||
Reference in New Issue
Block a user