Expressions offline mode

This commit is contained in:
SillyLossy
2023-03-26 16:29:55 +03:00
parent f14a1cb7e9
commit 9944d729f8
5 changed files with 381 additions and 14 deletions

View File

@ -0,0 +1,309 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="No-Image-Placeholder.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
version="1.1"
id="svg2"
viewBox="0 0 329.77792 406.00738"
height="406.00739"
width="329.77792">
<defs
id="defs4">
<linearGradient
id="linearGradient967"
inkscape:collect="always">
<stop
id="stop963"
offset="0"
style="stop-color:#c2c2c2;stop-opacity:1" />
<stop
id="stop965"
offset="1"
style="stop-color:#9f9f9f;stop-opacity:1" />
</linearGradient>
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3414"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
effect="spiro"
id="path-effect3410"
is_visible="true" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3406"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
effect="spiro"
id="path-effect3402"
is_visible="true" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3398"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
effect="spiro"
id="path-effect3392"
is_visible="true" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3388"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3372"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3368"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3364"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
effect="spiro"
id="path-effect3360"
is_visible="true" />
<inkscape:path-effect
lpeversion="0"
is_visible="true"
id="path-effect3346"
effect="spiro" />
<inkscape:path-effect
lpeversion="0"
effect="spiro"
id="path-effect3392-8"
is_visible="true" />
<linearGradient
gradientTransform="translate(-45.254833,0.35355338)"
gradientUnits="userSpaceOnUse"
y2="108.77648"
x2="658.45801"
y1="6.5995569"
x1="660.06653"
id="linearGradient969"
xlink:href="#linearGradient967"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
inkscape:document-rotation="0"
inkscape:window-maximized="1"
inkscape:window-y="42"
inkscape:window-x="0"
inkscape:window-height="1004"
inkscape:window-width="1920"
units="px"
fit-margin-bottom="0"
fit-margin-right="0"
fit-margin-left="0"
fit-margin-top="0"
inkscape:guide-bbox="true"
inkscape:snap-smooth-nodes="true"
showguides="false"
inkscape:object-nodes="true"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="109.10202"
inkscape:cx="148.40044"
inkscape:zoom="0.7071068"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base">
<inkscape:grid
originy="-510.42818"
originx="-399.13435"
id="grid3336"
type="xygrid" />
<sodipodi:guide
id="guide3375"
orientation="0,1"
position="-117.13437,-25.564321" />
<sodipodi:guide
id="guide3377"
orientation="0,1"
position="-114.13437,-23.564321" />
<sodipodi:guide
id="guide3380"
orientation="0,1"
position="-121.13437,-27.564321" />
<sodipodi:guide
id="guide3382"
orientation="0,1"
position="-114.13437,-22.564321" />
<sodipodi:guide
id="guide3384"
orientation="0,1"
position="-114.13437,-21.564321" />
<sodipodi:guide
id="guide3416"
orientation="-2,0.5"
position="-115.13437,-25.564311" />
<sodipodi:guide
id="guide3420"
orientation="-2,0.5"
position="-115.13437,-25.564311" />
<sodipodi:guide
id="guide4180"
orientation="0.24382204,-0.96981999"
position="206.80442,220.41193" />
<sodipodi:guide
id="guide4182"
orientation="1,0"
position="86.804424,280.52227" />
<sodipodi:guide
id="guide4186"
orientation="1,0"
position="206.80442,250.52231" />
<sodipodi:guide
id="guide4188"
orientation="-0.24382199,0.96982"
position="206.80442,190.30156" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-399.13437,-122.79051)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<rect
ry="7.0136137"
y="122.79051"
x="399.13437"
height="406.00739"
width="329.77792"
id="rect1017"
style="fill:#eeeeee;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.59331;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
transform="translate(43.778173,191.04163)"
id="g1015">
<rect
style="fill:#9f9f9f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.2995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1002"
width="82.489967"
height="90.470001"
x="398.75827"
y="178.74706"
ry="8.3970251"
transform="rotate(-16.342822)" />
<g
id="g1000"
transform="rotate(16.320529,538.13563,-184.89727)">
<rect
ry="4.5961938"
y="1.6498091"
x="547.18585"
height="115.96551"
width="107.83378"
id="rect961"
style="fill:url(#linearGradient969);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:5.398;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<g
style="stroke:#ffffff;stroke-width:13.0708;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(0.17265471,0,0,0.17265471,512.49324,-6.3296456)"
id="g875">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect3338"
width="491.10556"
height="449.99814"
x="270"
y="107.36227" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect3342"
width="491.10559"
height="209.99976"
x="270"
y="107.36227" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 300,317.36255 38.46147,-53.53818 60.53097,-45.16084 15.88277,18.57394 13.61285,-38.68356 8.20133,-2.98188 13.3106,-28.2093 180,179.99979"
id="path3344"
inkscape:path-effect="#path-effect3346"
inkscape:original-d="m 300,317.36255 38.46147,-53.53818 60.53097,-45.16084 15.88277,18.57394 13.61285,-38.68356 8.20133,-2.98188 13.3106,-28.2093 180,179.99979"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 180,60 c 4.09311,16.474688 7.71219,33.067277 10.85156,49.75 2.38256,12.66097 4.48857,25.37408 6.31641,38.12695 l -22.06445,-7.16015 -46.11133,-29.41602 5.32422,46.42578 -1.61524,24.78711 10.05274,30.37695 73.18554,-11.75585 L 300,180 252.19922,102.56641 242.5,117.5 215.375,95.375 Z"
transform="translate(270,107.36227)"
id="path3390-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscccccccccccc" />
<path
inkscape:connector-curvature="0"
inkscape:original-d="m 419.99999,347.36252 81.89918,-74.42959 18.50574,-9.68009 23.6512,-44.18894 25.94388,-21.70121 179.99999,179.99979"
inkscape:path-effect="#path-effect3360"
id="path3358"
d="m 419.99999,347.36252 81.89918,-74.42959 18.50574,-9.68009 23.6512,-44.18894 25.94388,-21.70121 179.99999,179.99979"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
sodipodi:nodetypes="cccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 569.99999,197.36269 35.9388,80.91289 v 30.11038 30.11038 l 22.45864,19.46652 c 6.52453,-6.45031 14.14893,-11.78526 22.44431,-15.70477 14.8245,-7.00447 31.33823,-9.35959 47.17057,-13.6217 6.42776,-1.73037 12.90672,-3.85419 18.21343,-7.87277 1.35174,-1.02362 2.61592,-2.16281 3.77424,-3.40107 h -30 l -40.52149,-40.55006 -29.85645,-48.91972 -10.25307,8.83886 z"
id="path3386"
inkscape:path-effect="#path-effect3388"
inkscape:original-d="m 569.99999,197.36269 35.9388,80.91289 v 30.11038 30.11038 l 22.45864,19.46652 c 5.77311,-6.36416 13.54339,-11.40815 22.44431,-15.70477 13.00316,-6.27685 32.0432,-8.74899 47.17057,-13.6217 6.8762,-2.21491 12.68001,-4.81998 18.21343,-7.87277 1.55883,-0.86001 1.99765,-2.671 3.77424,-3.40107 h -30 l -40.52149,-40.55006 -29.85645,-48.91972 -10.25307,8.83886 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccssscccccc" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.0708;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 419.99999,557.36227 c -0.41699,-9.60089 -8.81759,-17.60878 17.1252,-30.66806 31.8318,-16.02389 125.895,-35.88836 152.1537,-59.98434 19.42709,-17.82687 -70.4154,-37.66945 -55.0191,-59.07323 6.981,-9.70528 59.037,-19.96947 82.1463,-30.27386 21.90569,-9.76799 15.14129,-19.80328 31.4046,-29.97507 15.7092,-9.82558 68.3499,-19.77358 72.18929,-30.02516 -10.41359,10.52188 -68.83379,20.40327 -89.99999,30.00026 -22.3377,10.128 -21.4689,19.93018 -49.4313,29.48367 -30.1245,10.29239 -89.142,20.55268 -102.7077,30.51626 -28.4133,20.86858 46.863,42.59995 16.2024,59.99993 C 452.54309,490.92554 344.7219,510.65712 300,527.3626 c -30.9039,11.54369 -28.4079,17.74799 -30,29.99967"
id="path3370"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssscsssssc" />
</g>
</g>
</g>
<text
id="text1021"
y="412.12527"
x="562.00677"
style="font-style:normal;font-weight:normal;font-size:32px;line-height:1.25;font-family:sans-serif;fill:#767676;fill-opacity:1;stroke:none"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:32px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle"
y="412.12527"
x="562.00677"
id="tspan1019"
sodipodi:role="line">NO IMAGE</tspan><tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:32px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle"
id="tspan1023"
y="452.12527"
x="562.00677"
sodipodi:role="line">AVAILABLE</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -4,6 +4,7 @@ export {
getContext, getContext,
getApiUrl, getApiUrl,
defaultRequestArgs, defaultRequestArgs,
modules,
}; };
const extensionNames = ['caption', 'dice', 'expressions', 'floating-prompt', 'memory']; const extensionNames = ['caption', 'dice', 'expressions', 'floating-prompt', 'memory'];

View File

@ -1,5 +1,4 @@
import { getContext, getApiUrl } from "../../extensions.js"; import { getContext, getApiUrl, modules } from "../../extensions.js";
import { urlContentToDataUri } from "../../utils.js";
export { MODULE_NAME }; export { MODULE_NAME };
const MODULE_NAME = 'expressions'; const MODULE_NAME = 'expressions';
@ -67,6 +66,15 @@ async function moduleWorker() {
validateImages(); validateImages();
} }
if (!modules.includes('classify')) {
$('.expression_settings .offline_mode').css('display', 'block');
lastCharacter = context.characterId;
return;
}
else {
$('.expression_settings .offline_mode').css('display', 'none');
}
// check if last message changed // check if last message changed
const currentLastMessage = getLastCharacterMessage(); const currentLastMessage = getLastCharacterMessage();
if (lastCharacter === context.characterId && lastMessage === currentLastMessage) { if (lastCharacter === context.characterId && lastMessage === currentLastMessage) {
@ -139,16 +147,25 @@ async function validateImages() {
image.width = '0px'; image.width = '0px';
image.height = '0px'; image.height = '0px';
image.onload = function () { image.onload = function () {
$('#image_list').append(`<li id="${item}" class="success">${item} - OK</li>`); $('#image_list').append(getListItem(item, image.src, 'success'));
} }
image.onerror = function () { image.onerror = function () {
$('#image_list').append(`<li id="${item}" class="failure">${item} - Missing</li>`); $('#image_list').append(getListItem(item, '/img/No-Image-Placeholder.svg', 'failure'));
} }
$('#image_list').prepend(image); $('#image_list').prepend(image);
}); });
imagesValidating = false; imagesValidating = false;
} }
function getListItem(item, imageSrc, textClass) {
return `
<div id="${item}" class="expression_list_item">
<span class="expression_list_title ${textClass}">${item}</span>
<img class="expression_list_image" src="${imageSrc}" />
</div>
`;
}
async function getExpressionsList() { async function getExpressionsList() {
if (Array.isArray(expressionsList)) { if (Array.isArray(expressionsList)) {
return expressionsList; return expressionsList;
@ -175,11 +192,11 @@ async function getExpressionsList() {
} }
} }
async function setExpression(character, expression) { async function setExpression(character, expression, force) {
const filename = `${expression}.png`; const filename = `${expression}.png`;
const debugImageStatus = document.querySelector(`#image_list li[id="${filename}"]`); const debugImageStatus = document.querySelector(`#image_list div[id="${filename}"] span`);
if (debugImageStatus && !debugImageStatus.classList.contains('failure')) { if (force || (debugImageStatus && !debugImageStatus.classList.contains('failure'))) {
//console.log('setting expression from character images folder'); //console.log('setting expression from character images folder');
const imgUrl = `/characters/${character}/${filename}`; const imgUrl = `/characters/${character}/${filename}`;
$('img.expression').prop('src', imgUrl); $('img.expression').prop('src', imgUrl);
@ -193,6 +210,17 @@ async function setExpression(character, expression) {
} }
} }
function onClickExpressionImage() {
// online mode doesn't need force set
if (modules.includes('classify')) {
return;
}
const context = getContext();
const expression = $(this).attr('id').replace('.png', '');
setExpression(context.name2, expression, true);
}
(function () { (function () {
function addExpressionImage() { function addExpressionImage() {
const html = `<div class="expression-holder"><img class="expression"></div>`; const html = `<div class="expression-holder"><img class="expression"></div>`;
@ -208,7 +236,8 @@ async function setExpression(character, expression) {
<div class="inline-drawer-icon down"></div> <div class="inline-drawer-icon down"></div>
</div> </div>
<div class="inline-drawer-content"> <div class="inline-drawer-content">
<ul id="image_list"></ul> <p class="offline_mode">You are in offline mode. Click on the image below to set the expression.</p>
<div id="image_list"></div>
<p class="hint"><b>Hint:</b> <i>Create new folder in the <b>public/characters/</b> folder and name it as the name of the character. Put PNG images with expressions there.</i></p> <p class="hint"><b>Hint:</b> <i>Create new folder in the <b>public/characters/</b> folder and name it as the name of the character. Put PNG images with expressions there.</i></p>
</div> </div>
</div> </div>
@ -217,6 +246,7 @@ async function setExpression(character, expression) {
`; `;
$('#extensions_settings').append(html); $('#extensions_settings').append(html);
$('#expressions_show_default').on('input', onExpressionsShowDefaultInput); $('#expressions_show_default').on('input', onExpressionsShowDefaultInput);
$(document).on('click', '.expression_list_item', onClickExpressionImage);
$('.expression_settings').hide(); $('.expression_settings').hide();
} }

View File

@ -1,9 +1,7 @@
{ {
"display_name": "Character Expressions", "display_name": "Character Expressions",
"loading_order": 6, "loading_order": 6,
"requires": [ "requires": [],
"classify"
],
"js": "index.js", "js": "index.js",
"css": "style.css" "css": "style.css"
} }

View File

@ -31,10 +31,39 @@ img.expression {
height: 0px; height: 0px;
} }
#image_list { .expression_list_item {
margin-top: 0; position: relative;
margin-bottom: 0; max-width: 33%;
max-height: 200px;
background-color: #515151b0;
border-radius: 10px;
cursor: pointer;
}
.expression_list_title {
position: absolute;
bottom: 0;
left: 0;
text-align: center;
font-weight: 600; font-weight: 600;
background-color: #000000a8;
width: 100%;
height: 20%;
display: flex;
justify-content: center;
align-items: center;
}
.expression_list_image {
max-width: 100%;
height: 100%;
}
#image_list {
display: flex;
flex-direction: row;
column-gap: 1rem;
margin: 1rem;
} }
#image_list .success { #image_list .success {