mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
@@ -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');
|
||||||
@@ -789,22 +859,31 @@ async function setExpression(character, expression, force) {
|
|||||||
setDefault();
|
setDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (extension_settings.expressions.showDefault) {
|
if (extension_settings.expressions.showDefault) {
|
||||||
setDefault();
|
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() {
|
||||||
@@ -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,7 +1138,15 @@ 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">
|
||||||
|
<!-- 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">
|
<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>
|
||||||
@@ -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()) {
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user