Merge pull request #835 from pyrater/staging

Live2d Changes
This commit is contained in:
Cohee
2023-07-31 20:53:45 +03:00
committed by GitHub
2 changed files with 130 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ const MODULE_NAME = 'expressions';
const UPDATE_INTERVAL = 2000; const UPDATE_INTERVAL = 2000;
const FALLBACK_EXPRESSION = 'joy'; const FALLBACK_EXPRESSION = 'joy';
const DEFAULT_EXPRESSIONS = [ const DEFAULT_EXPRESSIONS = [
"live2d",
"admiration", "admiration",
"amusement", "amusement",
"anger", "anger",
@@ -44,6 +45,9 @@ let lastCharacter = undefined;
let lastMessage = null; let lastMessage = null;
let spriteCache = {}; let spriteCache = {};
let inApiCall = false; let inApiCall = false;
let live2d_var = false;
let previousSrc = null;
function isVisualNovelMode() { function isVisualNovelMode() {
return Boolean(!isMobile() && power_user.waifuMode && getContext().groupId); return Boolean(!isMobile() && power_user.waifuMode && getContext().groupId);
@@ -392,6 +396,56 @@ function onExpressionsShowDefaultInput() {
} }
} }
function loadLiveChar(value_name) {
let url = `${getApiUrl()}/api/live2d/load?loadchar=${location.origin}/characters/${value_name}`;
doExtrasFetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Bypass-Tunnel-Reminder': 'bypass',
},
})
.then(response => response.text())
.then(data => console.log(data))
.catch((error) => console.error('Error:', error));
}
function handleImageChange(isChecked) {
const imgElement = document.querySelector('img#expression-image.expression');
if (!imgElement) {
console.log("Cannot find addExpressionImage()");
return;
}
if (isChecked) {
// Method get IP of endpoint
if (imgElement.src !== getApiUrl() + '/api/live2d/result_feed') {
const expressionListItemElement = document.querySelector('#live2d');
const expressionImageElement = expressionListItemElement.querySelector('.expression_list_image');
const newSrc = expressionImageElement.src;
doExtrasFetch(newSrc, {
method: 'HEAD',
})
.then(response => {
if (response.ok) {
imgElement.src = getApiUrl() + '/api/live2d/result_feed';
}
})
.catch(error => {
console.error(error); // Log the error if necessary
});
} else if (previousSrc) {
imgElement.src = previousSrc; // Revert the src to its previous value
}
} else if (previousSrc !== null) {
imgElement.src = previousSrc; // Revert the src to its previous value
}
live2d_var = isChecked;
}
async function moduleWorker() { async function moduleWorker() {
const context = getContext(); const context = getContext();
@@ -405,6 +459,21 @@ async function moduleWorker() {
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) { if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
removeExpression(); removeExpression();
spriteCache = {}; spriteCache = {};
previousSrc = null;
//uncheck live image
let checkbox = document.getElementById('image_type_toggle');
if (checkbox.checked) {
checkbox.click();
}
//clear expression
let imgElement = document.getElementById('expression-image');
imgElement.src = "";
//Load new char
loadLiveChar(context.name2 + ".png");
} }
const vnMode = isVisualNovelMode(); const vnMode = isVisualNovelMode();
@@ -654,7 +723,6 @@ async function getSpritesList(name) {
try { try {
const result = await fetch(`/get_sprites?name=${encodeURIComponent(name)}`); const result = await fetch(`/get_sprites?name=${encodeURIComponent(name)}`);
let sprites = result.ok ? (await result.json()) : []; let sprites = result.ok ? (await result.json()) : [];
return sprites; return sprites;
} }
@@ -697,6 +765,8 @@ async function getExpressionsList() {
} }
async function setExpression(character, expression, force) { async function setExpression(character, expression, force) {
if (live2d_var == false) {
console.debug('entered setExpressions'); console.debug('entered setExpressions');
await validateImages(character); await validateImages(character);
const img = $('img.expression'); const img = $('img.expression');
@@ -725,8 +795,8 @@ async function setExpression(character, expression, force) {
} }
} }
} }
//only swap expressions when necessary //only swap expressions when necessary
if (prevExpressionSrc !== sprite.path if (prevExpressionSrc !== sprite.path
&& !img.hasClass('expression-animating')) { && !img.hasClass('expression-animating')) {
//clone expression //clone expression
expressionClone.addClass('expression-clone') expressionClone.addClass('expression-clone')
@@ -789,23 +859,32 @@ async function setExpression(character, expression, force) {
setDefault(); setDefault();
} }
}); });
} } else {
if (extension_settings.expressions.showDefault) {
} else { setDefault();
if (extension_settings.expressions.showDefault) { }
setDefault();
} }
} }
function setDefault() { function setDefault() {
console.debug('setting default'); console.debug('setting default');
const defImgUrl = `/img/default-expressions/${expression}.png`; const defImgUrl = `/img/default-expressions/${expression}.png`;
console.log(defImgUrl); //console.log(defImgUrl);
img.attr('src', defImgUrl); img.attr('src', defImgUrl);
img.addClass('default'); img.addClass('default');
} }
document.getElementById("expression-holder").style.display = ''; document.getElementById("expression-holder").style.display = '';
}
if (live2d_var == true) {
// Find the <img> element with id="expression-image" and class="expression"
const imgElement = document.querySelector('img#expression-image.expression');
//console.log("searching");
if (imgElement) {
console.log("setting value");
imgElement.src = getApiUrl() + '/api/live2d/result_feed';
}}
}
}
function onClickExpressionImage() { function onClickExpressionImage() {
// online mode doesn't need force set // online mode doesn't need force set
@@ -1052,7 +1131,6 @@ function setExpressionOverrideHtml(forceClear = false) {
$('body').append(element); $('body').append(element);
} }
function addSettings() { function addSettings() {
const html = ` const html = `
<div class="expression_settings"> <div class="expression_settings">
<div class="inline-drawer"> <div class="inline-drawer">
@@ -1060,8 +1138,16 @@ function setExpressionOverrideHtml(forceClear = false) {
<b>Character Expressions</b> <b>Character Expressions</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div> <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div> </div>
<div class="inline-drawer-content"> <div class="inline-drawer-content">
<div class="offline_mode"> <!-- Toggle button for aituber/static images -->
<div class="toggle_button">
<label class="switch">
<input id="image_type_toggle" type="checkbox">
<span class="slider round"></span>
<label for="image_type_toggle">Image Type - Live2d (extras)</label>
</div>
<div class="offline_mode">
<small>You are in offline mode. Click on the image below to set the expression.</small> <small>You are in offline mode. Click on the image below to set the expression.</small>
</div> </div>
<div class="flex-container flexnowrap"> <div class="flex-container flexnowrap">
@@ -1090,6 +1176,7 @@ function setExpressionOverrideHtml(forceClear = false) {
</form> </form>
</div> </div>
`; `;
$('#extensions_settings').append(html); $('#extensions_settings').append(html);
$('#expression_override_button').on('click', onClickExpressionOverrideButton); $('#expression_override_button').on('click', onClickExpressionOverrideButton);
$('#expressions_show_default').on('input', onExpressionsShowDefaultInput); $('#expressions_show_default').on('input', onExpressionsShowDefaultInput);
@@ -1105,7 +1192,19 @@ function setExpressionOverrideHtml(forceClear = false) {
$(document).on('click', '.expression_list_delete', onClickExpressionDelete); $(document).on('click', '.expression_list_delete', onClickExpressionDelete);
$(window).on("resize", updateVisualNovelModeDebounced); $(window).on("resize", updateVisualNovelModeDebounced);
$('.expression_settings').hide(); $('.expression_settings').hide();
$('#image_type_toggle').on('change', function() {
const isChecked = this.checked;
const inputElement = document.querySelector('input[name="avatar_url"]');
const value_name = inputElement ? inputElement.value : '';
if (isChecked) {
loadLiveChar(value_name);
}
handleImageChange(isChecked);
});
} }
addExpressionImage(); addExpressionImage();
addVisualNovelMode(); addVisualNovelMode();
@@ -1116,6 +1215,7 @@ function setExpressionOverrideHtml(forceClear = false) {
moduleWorker(); moduleWorker();
dragElement($("#expression-holder")) dragElement($("#expression-holder"))
eventSource.on(event_types.CHAT_CHANGED, () => { eventSource.on(event_types.CHAT_CHANGED, () => {
//console.log("checked: " + live2d_var);
setExpressionOverrideHtml(); setExpressionOverrideHtml();
if (isVisualNovelMode()) { if (isVisualNovelMode()) {

View File

@@ -14,7 +14,7 @@ const UPDATE_INTERVAL = 1000
let voiceMap = {} // {charName:voiceid, charName2:voiceid2} let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
let audioControl let audioControl
let storedvalue = false;
let lastCharacterId = null let lastCharacterId = null
let lastGroupId = null let lastGroupId = null
let lastChatId = null let lastChatId = null
@@ -164,6 +164,20 @@ async function moduleWorker() {
ttsJobQueue.push(message) ttsJobQueue.push(message)
} }
function talkingAnimation(switchValue) {
const apiKeyValue = document.getElementById("extensions_url").value;
const animationType = switchValue ? "start" : "stop";
if (switchValue !== storedvalue) {
try {
console.log(animationType + " Talking Animation");
fetch(`${apiKeyValue}/api/live2d/${animationType}_talking`);
storedvalue = switchValue; // Update the storedvalue to the current switchValue
} catch (error) {
// Handle the error here or simply ignore it to prevent logging
}
}
}
function resetTtsPlayback() { function resetTtsPlayback() {
// Stop system TTS utterance // Stop system TTS utterance
@@ -291,8 +305,10 @@ function updateUiAudioPlayState() {
// Give user feedback that TTS is active by setting the stop icon if processing or playing // Give user feedback that TTS is active by setting the stop icon if processing or playing
if (!audioElement.paused || isTtsProcessing()) { if (!audioElement.paused || isTtsProcessing()) {
img = 'fa-solid fa-stop-circle extensionsMenuExtensionButton' img = 'fa-solid fa-stop-circle extensionsMenuExtensionButton'
talkingAnimation(true)
} else { } else {
img = 'fa-solid fa-circle-play extensionsMenuExtensionButton' img = 'fa-solid fa-circle-play extensionsMenuExtensionButton'
talkingAnimation(false)
} }
$('#tts_media_control').attr('class', img); $('#tts_media_control').attr('class', img);
} else { } else {
@@ -354,6 +370,7 @@ async function processAudioJobQueue() {
audioQueueProcessorReady = false audioQueueProcessorReady = false
currentAudioJob = audioJobQueue.pop() currentAudioJob = audioJobQueue.pop()
playAudioData(currentAudioJob) playAudioData(currentAudioJob)
talkingAnimation(true)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
audioQueueProcessorReady = true audioQueueProcessorReady = true