diff --git a/index.js b/index.js
index dfba6bb..5131fc2 100644
--- a/index.js
+++ b/index.js
@@ -139,6 +139,7 @@ import {
initExpressionSync,
queueExpressionCaptureForSpeaker,
onExpressionSyncSettingChanged,
+ onAlternatePresentCharactersVisibilityChanged,
onHideDefaultExpressionDisplaySettingChanged,
clearExpressionSyncCache,
onExpressionSyncChatChanged
@@ -358,6 +359,7 @@ async function initUI() {
extensionSettings.showAlternatePresentCharactersPanel = $(this).prop('checked');
saveSettings();
renderThoughts();
+ onAlternatePresentCharactersVisibilityChanged();
});
$('#rpg-toggle-sync-expressions').on('change', function() {
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 8f3a16e..bfe8c85 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -50,6 +50,8 @@
"template.settingsModal.display.showLockIconsNote": "Display lock/unlock icons on tracker items to prevent AI from modifying them.",
"template.settingsModal.display.showThoughtsInChat": "Show Thoughts",
"template.settingsModal.display.showThoughtsInChatNote": "Display character thoughts as overlay bubbles next to their messages.",
+ "template.settingsModal.display.showInlineThoughts": "Show Thoughts Below Message Text",
+ "template.settingsModal.display.showInlineThoughtsNote": "Switch between the default corner thought bubbles and thought cards below the message text.",
"template.settingsModal.display.alwaysShowThoughtBubble": "Always Show Thought Bubble",
"template.settingsModal.display.alwaysShowThoughtBubbleNote": "Auto-expand thought bubble without clicking the icon first",
"template.settingsModal.display.enableAnimations": "Enable Animations",
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index 193cf21..31cee3f 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -51,6 +51,8 @@
"template.settingsModal.display.showLockIconsNote": "Afficher les icônes de verrouillage/déverrouillage sur les éléments de suivi pour empêcher l'IA de les modifier.",
"template.settingsModal.display.showThoughtsInChat": "Afficher Pensées",
"template.settingsModal.display.showThoughtsInChatNote": "Afficher les pensées des personnages sous forme de bulles superposées à côté de leurs messages.",
+ "template.settingsModal.display.showInlineThoughts": "Afficher les pensées sous le texte du message",
+ "template.settingsModal.display.showInlineThoughtsNote": "Basculer entre les bulles de pensée dans le coin par défaut et des cartes de pensée sous le texte du message.",
"template.settingsModal.display.alwaysShowThoughtBubble": "Toujours Afficher Bulle Pensée",
"template.settingsModal.display.alwaysShowThoughtBubbleNote": "Développer automatiquement la bulle de pensée sans cliquer sur l'icône d'abord",
"template.settingsModal.display.enableAnimations": "Activer Animations",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index f5a6399..447cfdd 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -50,6 +50,8 @@
"template.settingsModal.display.showLockIconsNote": "Отображать значки блокировки/разблокировки на элементах трекера, чтобы предотвратить их изменение ИИ.",
"template.settingsModal.display.showThoughtsInChat": "Показывать мысли",
"template.settingsModal.display.showThoughtsInChatNote": "Отображать мысли персонажей в виде всплывающих пузырьков рядом с их сообщениями.",
+ "template.settingsModal.display.showInlineThoughts": "Показывать мысли под текстом сообщения",
+ "template.settingsModal.display.showInlineThoughtsNote": "Переключает между стандартными угловыми пузырями мыслей и карточками мыслей под текстом сообщения.",
"template.settingsModal.display.alwaysShowThoughtBubble": "Всегда показывать пузырь мыслей",
"template.settingsModal.display.alwaysShowThoughtBubbleNote": "Автоматически раскрывать пузырь мыслей без предварительного нажатия на значок",
"template.settingsModal.display.enableAnimations": "Включить анимации",
diff --git a/src/i18n/zh-tw.json b/src/i18n/zh-tw.json
index 92c2e32..07b2900 100644
--- a/src/i18n/zh-tw.json
+++ b/src/i18n/zh-tw.json
@@ -41,6 +41,8 @@
"template.settingsModal.display.showLockIconsNote": "在追蹤器項目上顯示鎖定/解鎖圖示,以防止 AI 修改它們。",
"template.settingsModal.display.showThoughtsInChat": "在聊天中顯示想法",
"template.settingsModal.display.showThoughtsInChatNote": "將角色想法顯示為其訊息旁的泡泡",
+ "template.settingsModal.display.showInlineThoughts": "在訊息文字下方顯示想法",
+ "template.settingsModal.display.showInlineThoughtsNote": "在預設角落想法泡泡與顯示在訊息文字下方的想法卡片之間切換。",
"template.settingsModal.display.alwaysShowThoughtBubble": "始終顯示想法泡泡",
"template.settingsModal.display.alwaysShowThoughtBubbleNote": "自動展開想法泡泡",
"template.settingsModal.display.enableAnimations": "啟用動畫",
diff --git a/src/systems/integration/expressionSync.js b/src/systems/integration/expressionSync.js
index a700687..da25730 100644
--- a/src/systems/integration/expressionSync.js
+++ b/src/systems/integration/expressionSync.js
@@ -139,11 +139,14 @@ function shouldHideNativeExpressionDisplay() {
return extensionSettings.enabled === true && extensionSettings.hideDefaultExpressionDisplay === true;
}
+function shouldSyncExpressionPortraits() {
+ return extensionSettings.enabled === true
+ && extensionSettings.syncExpressionsToPresentCharacters === true
+ && extensionSettings.showAlternatePresentCharactersPanel === true;
+}
+
function shouldRunExpressionObservers() {
- return extensionSettings.enabled === true && (
- extensionSettings.syncExpressionsToPresentCharacters === true
- || extensionSettings.hideDefaultExpressionDisplay === true
- );
+ return shouldSyncExpressionPortraits() || shouldHideNativeExpressionDisplay();
}
function isExpressionContainerNode(node) {
@@ -392,8 +395,17 @@ function teardownExpressionObservers() {
observedExpressionImage = null;
}
+function resetPendingExpressionCaptureState() {
+ clearScheduledCaptures();
+ pendingCaptureRequestId += 1;
+ pendingSpeakerName = null;
+ pendingSpeakerBaselineSignature = null;
+ pendingSpeakerQueuedAt = 0;
+ lastCapturedExpressionSrc = null;
+}
+
function captureExpressionForSpeaker(speakerName, expectedRequestId = null) {
- if (!extensionSettings.enabled || !extensionSettings.syncExpressionsToPresentCharacters) {
+ if (!shouldSyncExpressionPortraits()) {
return false;
}
if (expectedRequestId !== null && expectedRequestId !== pendingCaptureRequestId) {
@@ -466,7 +478,8 @@ function ensureExpressionObservers() {
if (!shouldRunExpressionObservers()) {
teardownExpressionObservers();
- return;
+ resetPendingExpressionCaptureState();
+ return false;
}
const currentImg = findExpressionImageElement(pendingSpeakerName);
@@ -506,6 +519,8 @@ function ensureExpressionObservers() {
childList: true,
subtree: true
});
+
+ return true;
}
function clearScheduledCaptures() {
@@ -517,7 +532,7 @@ function clearScheduledCaptures() {
}
export function queueExpressionCaptureForSpeaker(speakerName) {
- if (!extensionSettings.enabled || !extensionSettings.syncExpressionsToPresentCharacters) {
+ if (!shouldSyncExpressionPortraits()) {
return;
}
@@ -543,7 +558,7 @@ export function queueExpressionCaptureForSpeaker(speakerName) {
}
export function syncExpressionFromLatestMessage() {
- if (!extensionSettings.enabled || !extensionSettings.syncExpressionsToPresentCharacters) {
+ if (!shouldSyncExpressionPortraits()) {
return;
}
@@ -557,7 +572,7 @@ export function initExpressionSync() {
ensureExpressionObservers();
- if (extensionSettings.syncExpressionsToPresentCharacters) {
+ if (shouldSyncExpressionPortraits()) {
syncExpressionFromLatestMessage();
}
}
@@ -578,7 +593,7 @@ export function onExpressionSyncChatChanged() {
setTimeout(() => {
ensureExpressionObservers();
syncNativeExpressionDisplayVisibility();
- if (extensionSettings.syncExpressionsToPresentCharacters) {
+ if (shouldSyncExpressionPortraits()) {
syncExpressionFromLatestMessage();
} else {
refreshExpressionConsumers();
@@ -594,18 +609,31 @@ export function onExpressionSyncSettingChanged(enabled) {
if (!purged) {
refreshExpressionConsumers();
}
+ if (shouldSyncExpressionPortraits()) {
+ syncExpressionFromLatestMessage();
+ }
+ return;
+ }
+
+ const observersActive = ensureExpressionObservers();
+ if (observersActive) {
+ resetPendingExpressionCaptureState();
+ }
+ refreshExpressionConsumers();
+}
+
+export function onAlternatePresentCharactersVisibilityChanged() {
+ const shouldSyncPortraits = shouldSyncExpressionPortraits();
+ const observersActive = ensureExpressionObservers();
+
+ if (shouldSyncPortraits) {
syncExpressionFromLatestMessage();
return;
}
- ensureExpressionObservers();
- clearScheduledCaptures();
- pendingCaptureRequestId += 1;
- pendingSpeakerName = null;
- pendingSpeakerBaselineSignature = null;
- pendingSpeakerQueuedAt = 0;
- lastCapturedExpressionSrc = null;
- refreshExpressionConsumers();
+ if (observersActive) {
+ resetPendingExpressionCaptureState();
+ }
}
export function onHideDefaultExpressionDisplaySettingChanged(enabled) {
@@ -617,12 +645,7 @@ export function onHideDefaultExpressionDisplaySettingChanged(enabled) {
}
export function clearExpressionSyncCache() {
- clearScheduledCaptures();
- pendingCaptureRequestId += 1;
- pendingSpeakerName = null;
- pendingSpeakerBaselineSignature = null;
- pendingSpeakerQueuedAt = 0;
- lastCapturedExpressionSrc = null;
+ resetPendingExpressionCaptureState();
teardownExpressionObservers();
showNativeExpressionDisplay();
}
diff --git a/template.html b/template.html
index 7a49a1b..13d22af 100644
--- a/template.html
+++ b/template.html
@@ -396,9 +396,10 @@
-
+
Switch between the default corner thought bubbles and thought cards below the message text.