migrate
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<h3>
|
||||
Enter a name for the custom expression:
|
||||
</h3>
|
||||
<h4>
|
||||
Requirements:
|
||||
</h4>
|
||||
<ol class="justifyLeft">
|
||||
<li>
|
||||
The name must be unique and not already in use by the default expression.
|
||||
</li>
|
||||
<li>
|
||||
The name must contain only letters, numbers, dashes and underscores. Don't include any file extensions.
|
||||
</li>
|
||||
</ol>
|
2458
public/scripts/extensions/expressions/index.js
Normal file
2458
public/scripts/extensions/expressions/index.js
Normal file
File diff suppressed because it is too large
Load Diff
21
public/scripts/extensions/expressions/list-item.html
Normal file
21
public/scripts/extensions/expressions/list-item.html
Normal file
@@ -0,0 +1,21 @@
|
||||
{{#each images}}
|
||||
<div class="expression_list_item interactable" data-expression="{{../expression}}" data-expression-type="{{this.type}}" data-filename="{{this.fileName}}">
|
||||
<div class="expression_list_buttons">
|
||||
<div class="menu_button expression_list_upload" title="Upload image">
|
||||
<i class="fa-solid fa-upload"></i>
|
||||
</div>
|
||||
<div class="menu_button expression_list_delete" title="Delete image">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="expression_list_title">
|
||||
<span>{{../expression}}</span>
|
||||
{{#if ../isCustom}}
|
||||
<small class="expression_list_custom">(custom)</small>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="expression_list_image_container" title="{{this.title}}">
|
||||
<img class="expression_list_image" src="{{this.imageSrc}}" alt="{{this.title}}" data-epression="{{../expression}}" />
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
13
public/scripts/extensions/expressions/manifest.json
Normal file
13
public/scripts/extensions/expressions/manifest.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"display_name": "Character Expressions",
|
||||
"loading_order": 6,
|
||||
"requires": [],
|
||||
"optional": [
|
||||
"classify"
|
||||
],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/ChuQuadrant/ChuQuadrant"
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
<h3>
|
||||
Are you sure you want to remove the expression <tt>"{{expression}}"</tt>?
|
||||
</h3>
|
||||
<div>
|
||||
Uploaded images will not be deleted, but will no longer be used by the extension.
|
||||
</div>
|
||||
<br>
|
109
public/scripts/extensions/expressions/settings.html
Normal file
109
public/scripts/extensions/expressions/settings.html
Normal file
@@ -0,0 +1,109 @@
|
||||
<div class="expression_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b data-i18n="Character Expressions">Character Expressions</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
|
||||
<div class="inline-drawer-content">
|
||||
<label class="checkbox_label" for="expression_translate" title="Use the selected API from Chat Translation extension settings." data-i18n="[title]Use the selected API from Chat Translation extension settings.">
|
||||
<input id="expression_translate" type="checkbox">
|
||||
<span data-i18n="Translate text to English before classification">Translate text to English before classification</span>
|
||||
</label>
|
||||
<label class="checkbox_label" for="expressions_allow_multiple" title="A single expression can have multiple sprites. Whenever the expression is chosen, a random sprite for this expression will be selected." data-i18n="[title]A single expression can have multiple sprites. Whenever the expression is chosen, a random sprite for this expression will be selected.">
|
||||
<input id="expressions_allow_multiple" type="checkbox">
|
||||
<span data-i18n="Allow multiple sprites per expression">Allow multiple sprites per expression</span>
|
||||
</label>
|
||||
<label class="checkbox_label" for="expressions_reroll_if_same" title="If the same expression is used again, re-roll the sprite. This only applies to expressions that have multiple available sprites assigned." data-i18n="[title]If the same expression is used again, re-roll the sprite. This only applies to expressions that have multiple available sprites assigned.">
|
||||
<input id="expressions_reroll_if_same" type="checkbox">
|
||||
<span data-i18n="Re-roll if same expression is used again">Re-roll if same sprite is used again</span>
|
||||
</label>
|
||||
<div class="expression_api_block m-b-1 m-t-1">
|
||||
<label for="expression_api" data-i18n="Classifier API">Classifier API</label>
|
||||
<small data-i18n="Select the API for classifying expressions.">Select the API for classifying expressions.</small>
|
||||
<select id="expression_api" class="flex1 margin0">
|
||||
<option value="99" data-i18n="[ None ]">[ None ]</option>
|
||||
<option value="0" data-i18n="Local">Local</option>
|
||||
<option value="1" data-i18n="Extras">Extras (deprecated)</option>
|
||||
<option value="2" data-i18n="Main API">Main API</option>
|
||||
<option value="3" data-i18n="WebLLM Extension">WebLLM Extension</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="expression_llm_prompt_block m-b-1 m-t-1">
|
||||
<label class="checkbox_label" for="expressions_filter_available" title="When using LLM or WebLLM classifier, only show and use expressions that have sprites assigned to them." data-i18n="[title]When using LLM or WebLLM classifier, only show and use expressions that have sprites assigned to them.">
|
||||
<input id="expressions_filter_available" type="checkbox">
|
||||
<span data-i18n="Filter expressions for available sprites">Filter expressions for available sprites</span>
|
||||
</label>
|
||||
<label for="expression_llm_prompt" class="title_restorable m-t-1">
|
||||
<span data-i18n="LLM Prompt">LLM Prompt</span>
|
||||
<div id="expression_llm_prompt_restore" title="Restore default value" class="right_menu_button">
|
||||
<i class="fa-solid fa-clock-rotate-left fa-sm"></i>
|
||||
</div>
|
||||
</label>
|
||||
<small data-i18n="Will be used if the API doesn't support JSON schemas or function calling.">Will be used if the API doesn't support JSON schemas or function calling.</small>
|
||||
<textarea id="expression_llm_prompt" type="text" class="text_pole textarea_compact" rows="2" placeholder="Use {{labels}} special macro."></textarea>
|
||||
</div>
|
||||
<div class="expression_fallback_block m-b-1 m-t-1">
|
||||
<label for="expression_fallback" data-i18n="Default / Fallback Expression">Default / Fallback Expression</label>
|
||||
<small data-i18n="Set the default and fallback expression being used when no matching expression is found.">Set the default and fallback expression being used when no matching expression is found.</small>
|
||||
<select id="expression_fallback" class="flex1 margin0"></select>
|
||||
</div>
|
||||
<div class="expression_custom_block m-b-1 m-t-1">
|
||||
<label for="expression_custom" data-i18n="Custom Expressions">Custom Expressions</label>
|
||||
<small><span data-i18n="Can be set manually or with an _space">Can be set manually or with an </span><tt>/emote</tt><span data-i18n="space_ slash command."> slash command.</span></small>
|
||||
<div class="flex-container">
|
||||
<select id="expression_custom" class="flex1 margin0"><select>
|
||||
<i id="expression_custom_add" class="menu_button fa-solid fa-plus margin0" title="Add"></i>
|
||||
<i id="expression_custom_remove" class="menu_button fa-solid fa-xmark margin0" title="Remove"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div id="no_chat_expressions" data-i18n="Open a chat to see the character expressions.">
|
||||
Open a chat to see the character expressions.
|
||||
</div>
|
||||
<div id="open_chat_expressions">
|
||||
<div class="offline_mode">
|
||||
<small data-i18n="You are in offline mode. Click on the image below to set the expression.">You are in offline mode. Click on the image below to set the expression.</small>
|
||||
</div>
|
||||
<label for="expression_override" data-i18n="Sprite Folder Override">Sprite Folder Override</label>
|
||||
<small><span data-i18n="Use a forward slash to specify a subfolder. Example: _space">Use a forward slash to specify a subfolder. Example: </span><tt>Bob/formal</tt></small>
|
||||
<div class="flex-container flexnowrap">
|
||||
<input id="expression_override" type="text" class="text_pole" placeholder="Override folder name" />
|
||||
<input id="expression_override_button" class="menu_button" type="submit" value="Submit" />
|
||||
</div>
|
||||
<div class="expression_buttons flex-container spaceEvenly">
|
||||
<div id="expression_upload_pack_button" class="menu_button">
|
||||
<i class="fa-solid fa-file-zipper"></i>
|
||||
<span data-i18n="Upload sprite pack (ZIP)">Upload sprite pack (ZIP)</span>
|
||||
</div>
|
||||
<div id="expression_override_cleanup_button" class="menu_button">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
<span data-i18n="Remove all image overrides">Remove all image overrides</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint">
|
||||
<b data-i18n="Hint:">Hint:</b>
|
||||
<i>
|
||||
<span data-i18n="Create new folder in the _space">Create new folder in the </span><b>/characters/</b> <span data-i18n="folder of your user data directory and name it as the name of the character.">folder of your user data directory and name it as the name of the character.</span>
|
||||
<span data-i18n="Put images with expressions there. File names should follow the pattern:">Put images with expressions there. File names should follow the pattern: </span><tt data-i18n="expression_label_pattern">[expression_label].[image_format]</tt>
|
||||
</i>
|
||||
</p>
|
||||
<p>
|
||||
<i>
|
||||
<span>In case of multiple files per expression, file names can contain a suffix, either separated by a dot or a
|
||||
dash.
|
||||
Examples: </span><tt>joy.png</tt>, <tt>joy-1.png</tt>, <tt>joy.expressive.png</tt>
|
||||
</i>
|
||||
</p>
|
||||
<h3 id="image_list_header">
|
||||
<strong data-i18n="Sprite set:">Sprite set:</strong> <span id="image_list_header_name"></span>
|
||||
</h3>
|
||||
<div id="image_list"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form>
|
||||
<input type="file" id="expression_upload_pack" name="expression_upload_pack" accept="application/zip" hidden>
|
||||
<input type="file" id="expression_upload" name="expression_upload" accept="image/*" hidden>
|
||||
</form>
|
||||
</div>
|
220
public/scripts/extensions/expressions/style.css
Normal file
220
public/scripts/extensions/expressions/style.css
Normal file
@@ -0,0 +1,220 @@
|
||||
.expression-helper {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#expression-wrapper {
|
||||
display: flex;
|
||||
height: calc(100vh - var(--topBarBlockSize));
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#visual-novel-wrapper {
|
||||
display: flex;
|
||||
height: calc(100vh - var(--topBarBlockSize));
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#visual-novel-wrapper .expression-holder {
|
||||
width: max-content;
|
||||
display: flex;
|
||||
left: unset;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
#visual-novel-wrapper .hidden {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/*#visual-novel-wrapper img.expression {
|
||||
object-fit: cover;
|
||||
}*/
|
||||
|
||||
.expression-holder {
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
max-height: 90vh;
|
||||
max-width: 90vh;
|
||||
width: calc((100vw - var(--sheldWidth)) /2);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
filter: drop-shadow(2px 2px 2px #51515199);
|
||||
z-index: 2;
|
||||
overflow: hidden;
|
||||
resize: both;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#no_chat_expressions {
|
||||
text-align: center;
|
||||
margin: 10px 0;
|
||||
font-weight: bold;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
#image_list_header_name {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
img.expression {
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
max-height: 90vh;
|
||||
max-width: 90vh;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
vertical-align: bottom;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
img.expression[src=""] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
img.expression.default {
|
||||
vertical-align: middle;
|
||||
max-height: 120px;
|
||||
object-fit: contain !important;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.expression-clone {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.debug-image {
|
||||
display: none;
|
||||
visibility: collapse;
|
||||
opacity: 0;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.expression_list_item {
|
||||
position: relative;
|
||||
max-width: 20%;
|
||||
min-width: 100px;
|
||||
max-height: 200px;
|
||||
background-color: #515151b0;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.expression_list_image_container {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.expression_list_title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
background-color: #000000a8;
|
||||
width: 100%;
|
||||
height: 20%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
}
|
||||
.expression_list_custom {
|
||||
font-size: 0.66rem;
|
||||
}
|
||||
|
||||
.expression_list_buttons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
/* height: 20%; */
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.menu_button.expression_list_delete,
|
||||
.menu_button.expression_list_upload {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.expression_list_image {
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
#image_list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 1rem;
|
||||
margin: 1rem;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
row-gap: 1rem;
|
||||
}
|
||||
|
||||
#image_list .expression_list_item[data-expression-type="success"] .expression_list_title {
|
||||
color: green;
|
||||
}
|
||||
|
||||
#image_list .expression_list_item[data-expression-type="additional"] .expression_list_title {
|
||||
color: darkolivegreen;
|
||||
}
|
||||
#image_list .expression_list_item[data-expression-type="additional"] .expression_list_title::before {
|
||||
content: '➕';
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: -9px;
|
||||
font-size: 14px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 darkolivegreen;
|
||||
}
|
||||
|
||||
#image_list .expression_list_item[data-expression-type="failure"] .expression_list_title {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.expression_settings label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.expression_settings label input {
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.expression_buttons .menu_button {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: baseline;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#expressions_container:has(#expressions_allow_multiple:not(:checked)) #image_list .expression_list_item[data-expression-type="additional"],
|
||||
#expressions_container:has(#expressions_allow_multiple:not(:checked)) label[for="expressions_reroll_if_same"] {
|
||||
opacity: 0.3;
|
||||
transition: opacity var(--animation-duration) ease;
|
||||
}
|
||||
#expressions_container:has(#expressions_allow_multiple:not(:checked)) #image_list .expression_list_item[data-expression-type="additional"]:hover,
|
||||
#expressions_container:has(#expressions_allow_multiple:not(:checked)) #image_list .expression_list_item[data-expression-type="additional"]:focus {
|
||||
opacity: unset;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
<div class="m-b-1" data-i18n="upload_expression_request">Please enter a name for the sprite (without extension).</div>
|
||||
<div class="m-b-1" data-i18n="upload_expression_naming_1">
|
||||
Sprite names must follow the naming schema for the selected expression: {{expression}}
|
||||
</div>
|
||||
<div data-i18n="upload_expression_naming_2">
|
||||
For multiple expressions, the name must follow the expression name and a valid suffix. Allowed separators are '-' or dot '.'.
|
||||
</div>
|
||||
<span class="m-b-1" data-i18n="Examples:">Examples:</span> <tt>{{expression}}.png</tt>, <tt>{{expression}}-1.png</tt>, <tt>{{expression}}.expressive.png</tt>
|
||||
{{#if clickedFileName}}
|
||||
<div class="m-t-1" data-i18n="upload_expression_replace">Click 'Replace' to replace the existing expression:</div>
|
||||
<tt>{{clickedFileName}}</tt>
|
||||
{{/if}}
|
Reference in New Issue
Block a user