Compare commits
21 Commits
main
...
export-opt
Author | SHA1 | Date |
---|---|---|
Vftdan | 9d6f01a5e6 | |
ente | 477e2adb31 | |
fotoente | a7e4ce76d1 | |
fotoente | 26a17cd4b4 | |
Vftdan | 9631a7a61a | |
Vftdan | 16606663e9 | |
Johann150 | 90d156e3f2 | |
Johann150 | 2bd7ec3818 | |
Johann150 | 4cc1f0d7ca | |
Johann150 | 709d211297 | |
ente | f2382a3d00 | |
ente | 3c75ccb346 | |
ente | 0db1f26874 | |
ente | 6ed1d5df2b | |
ente | bbe8fdc753 | |
fotoente | d202a4f150 | |
fotoente | 1b58a70546 | |
Vftdan | d3033b8912 | |
Vftdan | ed6a9097ee | |
Vftdan | 8858549de3 | |
Vftdan | dfc0870fc1 |
13
README.md
|
@ -26,7 +26,7 @@ The colour of the arms is determined by the last of the three entries named `"co
|
|||
|
||||
The export works in a way that in the background all the parts are drawn onto a canvas and then exported into a PNG that is then displayed. Direct canvas download isn't supported on the most mobile browsers so I chosen to got that little bit longer route, to make it more easily to download any of the mixed neomojis.
|
||||
|
||||
## I dowoloaded it localy, but it doesn't work?!?
|
||||
## I downloaded it localy, but it doesn't work?!?
|
||||
|
||||
Welcome to the world of Javascript!
|
||||
Due to security reasons javascript that is displayed in a Brwoser can't access files diretly, so to speak on the PC the JavaScript si executed one. The solutions is relativly simple: Run a small http server locally.
|
||||
|
@ -58,5 +58,16 @@ YES! I actually do! creating the first 95 elements took me over six hours to mak
|
|||
- For creating the [neopossum emojis](https://yiff.life/@EeveeEuphoria/112039918021786980)
|
||||
- For letting me use them in this project!
|
||||
|
||||
[olivvybee](https://honeycomb.engineer/@olivvybee)
|
||||
- For creating the [neobread emojis](https://github.com/olivvybee/neobread) and [blobbee emojis](https://github.com/olivvybee/blobbee/releases/latest)
|
||||
- For letting me use them in this project!
|
||||
|
||||
[vftdan](https://mastodon.ml/@vftdan)
|
||||
- For completly rewriting the JavaScript
|
||||
- Adding drowpdown menus for the part selection
|
||||
|
||||
[Johann150](https://genau.qwertqwefsday.eu/@Johann150)
|
||||
- For the permalink functionality
|
||||
|
||||
You
|
||||
- For any feedback, bug report or pull request to improve this project!
|
||||
|
|
44
index.html
|
@ -5,7 +5,6 @@
|
|||
<title>Neomojimixer (BETA)</title>
|
||||
<link rel="shortcut icon" href="favicon.gif" type="image/gif" />
|
||||
<link rel="stylesheet" href="neomojimixer.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h2>Neomojimixer (BETA)</h2>
|
||||
|
@ -18,32 +17,49 @@
|
|||
<img class="arms" id="arms_img" src="" />
|
||||
</div>
|
||||
<div id="controls">
|
||||
<div class="body"><button id="body_left" onclick="onClick_body_prev();" disabled><</button><span class="name" id="body_name">name body</span><button id="body_right" onclick="onClick_body_next();" disabled>></button></div>
|
||||
<div class="eyes"><button id="eyes_left" onclick="onClick_eyes_prev();" disabled><</button><span class="name" id="eyes_name">name eyes</span><button id="eyes_right" onclick="onClick_eyes_next();" disabled>></button></div>
|
||||
<div class="mouth"><button id="mouth_left" onclick="onClick_mouth_prev();" disabled><</button><span class="name" id="mouth_name">name mouth</span><button id="mouth_right" onclick="onClick_mouth_next();" disabled>></button></div>
|
||||
<div class="arms"><button id="arms_left" onclick="onClick_arms_prev();" disabled><</button><span class="name" id="arms_name">name arms</span><button id="arms_right" onclick="onClick_arms_next();" disabled>></button></div>
|
||||
<div class="random"><button id="random" onclick="randomize();" disabled>Random</button></div>
|
||||
<div class="export"><button id="export" onclick="exportImage();" disabled>Export Image</button></div>
|
||||
<div class="body"><button id="body_left" onclick="NeomojiMixer.part_handlers.body.onClickPrev();" disabled><</button><select class="name" id="body_name" onchange="NeomojiMixer.part_handlers.body.onChangeDropdown();" disabled>name body</select><button id="body_right" onclick="NeomojiMixer.part_handlers.body.onClickNext();" disabled>></button></div>
|
||||
<div class="eyes"><button id="eyes_left" onclick="NeomojiMixer.part_handlers.eyes.onClickPrev();" disabled><</button><select class="name" id="eyes_name" onchange="NeomojiMixer.part_handlers.eyes.onChangeDropdown();" disabled>name eyes</select><button id="eyes_right" onclick="NeomojiMixer.part_handlers.eyes.onClickNext();" disabled>></button></div>
|
||||
<div class="mouth"><button id="mouth_left" onclick="NeomojiMixer.part_handlers.mouth.onClickPrev();" disabled><</button><select class="name" id="mouth_name" onchange="NeomojiMixer.part_handlers.mouth.onChangeDropdown();" disabled>name mouth</select><button id="mouth_right" onclick="NeomojiMixer.part_handlers.mouth.onClickNext();" disabled>></button></div>
|
||||
<div class="arms"><button id="arms_left" onclick="NeomojiMixer.part_handlers.arms.onClickPrev();" disabled><</button><select class="name" id="arms_name" onchange="NeomojiMixer.part_handlers.arms.onChangeDropdown();" disabled>name arms</select><button id="arms_right" onclick="NeomojiMixer.part_handlers.arms.onClickNext();" disabled>></button></div>
|
||||
<div class="random"><button id="random" onclick="NeomojiMixer.randomize();" disabled>Random</button></div>
|
||||
<div class="export">
|
||||
<button id="export" onclick="NeomojiMixer.exportImage();" disabled>Export Image</button>
|
||||
<label>
|
||||
Export type:
|
||||
<input type="text" id="export-mime" list="export-mime-list" value="image/png" />
|
||||
<datalist id="export-mime-list">
|
||||
<option value="image/png"></option>
|
||||
<option value="image/webp"></option>
|
||||
<option value="image/jpeg"></option>
|
||||
</datalist>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" id="export-quality-enabled" />Quality:<input type="number" id="export-quality" min="0.0" max="1.0" step="0.1" value="1.0" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="stats">stats</div>
|
||||
<canvas id="canvas_export" width="256" height="256" hidden name="test.png"></canvas>
|
||||
<img id="imageExport" src="" hidden/>
|
||||
<p id="exportSaveMessage" hidden>To save right click and choose "Save image as..."</p>
|
||||
<input type="text" id="fullNeomojiName" name="" value="" readonly hidden/>
|
||||
<p>
|
||||
<a id="imageExportLink" download href="" target="_blank" hidden>Download</a>
|
||||
</p>
|
||||
<p id="exportSaveMessage" hidden>To save right click and choose "Save image as..." or click the "Download" link</p>
|
||||
<a id="fullNeomojiName" hidden></a>
|
||||
<p>Neomojis are from the following sources: </p>
|
||||
<ul>
|
||||
<li><b><a href="https://volpeon.ink/emojis/neofox/" target="_blank" class="links">Neofox</a></b> by <a href="https://is-a.wyvern.rip/@volpeon" target="_blank" class="links">Volpeon</a></li>
|
||||
<li><b><a href="https://volpeon.ink/emojis/neocat/" target="_blank" class="links">Neocat</a></b> by Volpeon</li>
|
||||
<li><b><a href="https://emoji-repo.absturztau.be/repo/neorat.zip" target="_blank" class="links">Neorat</a></b> by <a href="https://onemuri.nl/" target="_blank" class="links">Justje</a></li>
|
||||
<li><b><a href="https://yiff.life/@EeveeEuphoria/112039918021786980" target="_blank" class="links">Neopossum</a></b> by <a href="https://yiff.life/@EeveeEuphoria" target="_blank" class="links">EeveeEuphoria</a></li>
|
||||
<li><b><a href="https://github.com/olivvybee/neobread" target="_blank" class="links">Neobread</a></b> by <a href="https://honeycomb.engineer/@olivvybee" target="_blank" class="links">Olivvybee</a></li>
|
||||
<li><b><a href="https://github.com/olivvybee/blobbee/releases/latest" target="_blank" class="links">Blobbee</a></b> by Olivvybee</li>
|
||||
<li><b>Neoredpanda</b> by <a href="https://hat-eine.entenbru.st/@Erpel" target="_blank" class="links">Ente</a></li>
|
||||
</ul>
|
||||
<p>Sourcecode on Codeberg: <a href="https://codeberg.org/fotoente/neomojimixer" target="_blank">Neomojimixer</a>
|
||||
<p xmlns:cc="http://creativecommons.org/ns#" >This work is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1" alt=""></a></p>
|
||||
|
||||
<p xmlns:cc="http://creativecommons.org/ns#" >This work is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1" alt=""></a></p>
|
||||
|
||||
<!-- Load in the JS as the last element or the DOM objects won't be there -->
|
||||
<script src="neomojimixer.js"></script>
|
||||
<script src="neomojimixer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -34,20 +34,37 @@ img.arms {
|
|||
width: 256px;
|
||||
}
|
||||
|
||||
input, button, select {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
button#random {
|
||||
input[type="checkbox"] {
|
||||
margin: 4px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
.export > label {
|
||||
display: block;
|
||||
width: 250px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.export > label > input:not([type="checkbox"]) {
|
||||
width: 125px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
button#random, button#export {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
button#export {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
span.name {
|
||||
#controls > div > .name {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
|
|
712
neomojimixer.js
|
@ -1,370 +1,364 @@
|
|||
//global variables
|
||||
const NeomojiMixer = (function(NeomojiMixer) {
|
||||
//global variables
|
||||
|
||||
//Arrays to hold the parts
|
||||
let eyes = [];
|
||||
let body = [];
|
||||
let mouth = [];
|
||||
let arms = [];
|
||||
const color_names = [
|
||||
"blue",
|
||||
"lightgrey",
|
||||
"orange",
|
||||
"red",
|
||||
"white",
|
||||
"yellow",
|
||||
"lightbrown",
|
||||
];
|
||||
let selected_color = "blue";
|
||||
let color_change_callbacks = [];
|
||||
|
||||
//FOr all the different colours of the arms there will be each a own arraz
|
||||
let arms_orange = [];
|
||||
let arms_blue = [];
|
||||
let arms_lightgrey = [];
|
||||
let arms_red = [];
|
||||
let arms_white = [];
|
||||
let arms_yellow = [];
|
||||
//shotnames for HTML elements to interact with
|
||||
|
||||
//Index to easily find when to roll back to the first/last element in the list
|
||||
let inex_eyes = 0;
|
||||
let index_body = 0;
|
||||
let index_mouth = 0;
|
||||
let index_arms = 0;
|
||||
let index_color = 0;
|
||||
const canvas = document.getElementById("canvas_export");
|
||||
const export_img = document.getElementById("imageExport");
|
||||
const export_img_download = document.getElementById("imageExportLink");
|
||||
const neomoji_name = document.getElementById("fullNeomojiName");
|
||||
|
||||
//shotnames for HTML elements to interact with
|
||||
//Stats
|
||||
const stats = document.getElementById("stats");
|
||||
|
||||
//images
|
||||
const body_image = document.getElementById("body_img");
|
||||
const eyes_image = document.getElementById("eyes_img");
|
||||
const mouth_image = document.getElementById("mouth_img");
|
||||
const arms_image = document.getElementById("arms_img");
|
||||
|
||||
const canvas = document.getElementById("canvas_export");
|
||||
const export_img = document.getElementById("imageExport");
|
||||
const neomoji_name = document.getElementById("fullNeomojiName");
|
||||
|
||||
//names
|
||||
const body_name = document.getElementById("body_name");
|
||||
const eyes_name = document.getElementById("eyes_name");
|
||||
const mouth_name = document.getElementById("mouth_name");
|
||||
const arms_name = document.getElementById("arms_name");
|
||||
|
||||
//Stats
|
||||
const stats = document.getElementById("stats");
|
||||
|
||||
|
||||
// Loading the JSON and getting all the available parts
|
||||
async function getData() {
|
||||
|
||||
fetch('./parts.json')
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
loadParts(data);
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.log('An error occurred:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function loadParts(parts) {
|
||||
//Load parts into Arrays
|
||||
parts.type.eyes.forEach(fillArrayEyes);
|
||||
parts.type.body.forEach(fillArrayBody);
|
||||
parts.type.mouth.forEach(fillArrayMouth);
|
||||
parts.type.arms.forEach(fillArrayArms);
|
||||
|
||||
//find the indexes of each part of the corresponding color and write those into the color arrays
|
||||
fillArraysArms();
|
||||
|
||||
//Randomize initial view
|
||||
randomize();
|
||||
|
||||
//Show little statistic
|
||||
var sum = body.length + eyes.length + mouth.length + arms.length;
|
||||
var variety = body.length * eyes.length * mouth.length * arms_orange.length;
|
||||
|
||||
stats.innerHTML = "There are " + sum + " Elements available,<br />with " + new Intl.NumberFormat("de-DE").format(variety) + " possible combinations.";
|
||||
|
||||
//Activate the buttons after everything is loaded in
|
||||
document.getElementById("body_left").disabled = false;
|
||||
document.getElementById("body_right").disabled = false;
|
||||
document.getElementById("eyes_left").disabled = false;
|
||||
document.getElementById("eyes_right").disabled = false;
|
||||
document.getElementById("mouth_left").disabled = false;
|
||||
document.getElementById("mouth_right").disabled = false;
|
||||
document.getElementById("arms_left").disabled = false;
|
||||
document.getElementById("arms_right").disabled = false;
|
||||
document.getElementById("random").disabled = false;
|
||||
document.getElementById("export").disabled = false;
|
||||
|
||||
}
|
||||
|
||||
function fillArrayEyes(item){
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
eyes.push ([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1
|
||||
}
|
||||
|
||||
function fillArrayBody(item){
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
let color = item.color;
|
||||
body.push ([name, url, color]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1
|
||||
}
|
||||
|
||||
function fillArrayMouth(item){
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
mouth.push ([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1
|
||||
}
|
||||
|
||||
function fillArrayArms(item){
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
let color = item.color;
|
||||
arms.push ([name, url, color]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1
|
||||
}
|
||||
|
||||
function fillArraysArms(){
|
||||
for (let i=0; i<arms.length; i++){
|
||||
if (arms[i][2] == "blue" || arms[i][2] == ""){
|
||||
arms_blue.push(i);
|
||||
}
|
||||
|
||||
if (arms[i][2] == "lightgrey" || arms[i][2] == ""){
|
||||
arms_lightgrey.push(i);
|
||||
}
|
||||
|
||||
if (arms[i][2] == "orange" || arms[i][2] == ""){
|
||||
arms_orange.push(i);
|
||||
}
|
||||
|
||||
if (arms[i][2] == "red" || arms[i][2] == ""){
|
||||
arms_red.push(i);
|
||||
}
|
||||
|
||||
if (arms[i][2] == "white" || arms[i][2] == ""){
|
||||
arms_white.push(i);
|
||||
}
|
||||
|
||||
if (arms[i][2] == "yellow" || arms[i][2] == ""){
|
||||
arms_yellow.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function onClick_body_next(){
|
||||
index_body++;
|
||||
|
||||
if (index_body == body.length) {index_body = 0;} //check if index is too big for the array
|
||||
|
||||
if (body[index_body][2] == "blue"){index_arms = arms_blue[index_color];}
|
||||
else if (body[index_body][2] == "lightgrey"){index_arms = arms_lightgrey[index_color];}
|
||||
else if (body[index_body][2] == "orange"){index_arms = arms_orange[index_color];}
|
||||
else if (body[index_body][2] == "red"){index_arms = arms_red[index_color];}
|
||||
else if (body[index_body][2] == "white"){index_arms = arms_white[index_color];}
|
||||
else if (body[index_body][2] == "yellow"){index_arms = arms_yellow[index_color];}
|
||||
|
||||
body_image.src = "." + body[index_body][1]; //Change URL of body picture
|
||||
body_name.innerHTML = body[index_body][0]; //Change body name in controls
|
||||
|
||||
arms_image.src = "." + arms[index_arms][1]; //Change URL of arms picture
|
||||
arms_name.innerHTML = arms[index_arms][0]; //Change arms name in controls
|
||||
}
|
||||
|
||||
function onClick_body_prev(){
|
||||
index_body--;
|
||||
|
||||
if (index_body < 0) {index_body = (body.length-1);} //check if index is too big for the array
|
||||
|
||||
if (body[index_body][2] == "blue"){index_arms = arms_blue[index_color];}
|
||||
else if (body[index_body][2] == "lightgrey"){index_arms = arms_lightgrey[index_color];}
|
||||
else if (body[index_body][2] == "orange"){index_arms = arms_orange[index_color];}
|
||||
else if (body[index_body][2] == "red"){index_arms = arms_red[index_color];}
|
||||
else if (body[index_body][2] == "white"){index_arms = arms_white[index_color];}
|
||||
else if (body[index_body][2] == "yellow"){index_arms = arms_yellow[index_color];}
|
||||
|
||||
body_image.src = "." + body[index_body][1]; //Change URL of body picture
|
||||
body_name.innerHTML = body[index_body][0]; //Change body name in controls
|
||||
|
||||
arms_image.src = "." + arms[index_arms][1]; //Change URL of arms picture
|
||||
arms_name.innerHTML = arms[index_arms][0]; //Change arms name in controls
|
||||
}
|
||||
|
||||
function onClick_eyes_next(){
|
||||
index_eyes++;
|
||||
|
||||
if (index_eyes == eyes.length) {index_eyes = 0;} //check if index is too big for the array
|
||||
|
||||
eyes_image.src = "." + eyes[index_eyes][1]; //Change URL of picture
|
||||
eyes_name.innerHTML = eyes[index_eyes][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function onClick_eyes_prev(){
|
||||
index_eyes--;
|
||||
|
||||
if (index_eyes < 0) {index_eyes = (eyes.length-1);} //check if index is too big for the array
|
||||
|
||||
eyes_image.src = "." + eyes[index_eyes][1]; //Change URL of picture
|
||||
eyes_name.innerHTML = eyes[index_eyes][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function onClick_mouth_next(){
|
||||
index_mouth++;
|
||||
|
||||
if (index_mouth == mouth.length) {index_mouth = 0;} //check if index is too big for the array
|
||||
|
||||
mouth_image.src = "." + mouth[index_mouth][1]; //Change URL of picture
|
||||
mouth_name.innerHTML = mouth[index_mouth][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function onClick_mouth_prev(){
|
||||
index_mouth--;
|
||||
|
||||
if (index_mouth < 0) {index_mouth = (mouth.length-1);} //check if index is too big for the array
|
||||
|
||||
mouth_image.src = "." + mouth[index_mouth][1]; //Change URL of picture
|
||||
mouth_name.innerHTML = mouth[index_mouth][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function onClick_arms_next(){
|
||||
index_color++;
|
||||
|
||||
if (body[index_body][2] == "blue"){
|
||||
if (index_color == arms_blue.length) {index_color = 0;}
|
||||
index_arms = arms_blue[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "lightgrey"){
|
||||
if (index_color == arms_lightgrey.length) {index_color = 0;}
|
||||
index_arms = arms_lightgrey[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "orange"){
|
||||
if (index_color == arms_orange.length) {index_color = 0;}
|
||||
index_arms = arms_orange[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "red"){
|
||||
if (index_color == arms_red.length) {index_color = 0;}
|
||||
index_arms = arms_red[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "white"){
|
||||
if (index_color == arms_white.length) {index_color = 0;}
|
||||
index_arms = arms_white[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "yellow"){
|
||||
if (index_color == arms_yellow.length) {index_color = 0;}
|
||||
index_arms = arms_yellow[index_color];
|
||||
}
|
||||
|
||||
arms_image.src = "." + arms[index_arms][1]; //Change URL of picture
|
||||
arms_name.innerHTML = arms[index_arms][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function onClick_arms_prev(){
|
||||
index_color--;
|
||||
|
||||
if (body[index_body][2] == "blue"){
|
||||
if (index_color < 0) {index_color = arms_blue.length-1;}
|
||||
index_arms = arms_blue[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "lightgrey"){
|
||||
if (index_color < 0) {index_color = arms_lightgrey.length-1;}
|
||||
index_arms = arms_lightgrey[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "orange"){
|
||||
if (index_color < 0) {index_color = arms_orange.length-1;}
|
||||
index_arms = arms_orange[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "red"){
|
||||
if (index_color < 0) {index_color = arms_red.length-1;}
|
||||
index_arms = arms_red[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "white"){
|
||||
if (index_color < 0) {index_color = arms_white.length-1;}
|
||||
index_arms = arms_white[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "yellow"){
|
||||
if (index_color < 0) {index_color = arms_yellow.length-1;}
|
||||
index_arms = arms_yellow[index_color];
|
||||
}
|
||||
|
||||
arms_image.src = "." + arms[index_arms][1]; //Change URL of picture
|
||||
arms_name.innerHTML = arms[index_arms][0]; //Change name in controls
|
||||
}
|
||||
|
||||
function randomize(){ //Randomize which parts are shown
|
||||
index_body = Math.floor(Math.random() * body.length);
|
||||
index_eyes = Math.floor(Math.random() * eyes.length);
|
||||
index_mouth = Math.floor(Math.random() * mouth.length);
|
||||
index_arms = 0;
|
||||
|
||||
//Determine what color the body has and chose the arms color in the same way
|
||||
//Basically it does a random on the arms array and returns an index number with the right color for that body
|
||||
if (body[index_body][2] == "blue"){
|
||||
index_color = Math.floor(Math.random() * arms_blue.length)
|
||||
index_arms = arms_blue[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "lightgrey"){
|
||||
index_color = Math.floor(Math.random() * arms_lightgrey.length)
|
||||
index_arms = arms_lightgrey[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "orange"){
|
||||
index_color = Math.floor(Math.random() * arms_orange.length)
|
||||
index_arms = arms_orange[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "red"){
|
||||
index_color = Math.floor(Math.random() * arms_red.length)
|
||||
index_arms = arms_red[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "white"){
|
||||
index_color = Math.floor(Math.random() * arms_white.length)
|
||||
index_arms = arms_white[index_color];
|
||||
}
|
||||
else if (body[index_body][2] == "yellow"){
|
||||
index_color = Math.floor(Math.random() * arms_yellow.length)
|
||||
index_arms = arms_yellow[index_color];
|
||||
}
|
||||
|
||||
body_image.src = "." + body[index_body][1];
|
||||
eyes_image.src = "." + eyes[index_eyes][1];
|
||||
mouth_image.src = "." + mouth[index_mouth][1];
|
||||
arms_image.src = "." + arms[index_arms][1];
|
||||
|
||||
body_name.innerHTML = body[index_body][0];
|
||||
eyes_name.innerHTML = eyes[index_eyes][0];
|
||||
mouth_name.innerHTML = mouth[index_mouth][0];
|
||||
arms_name.innerHTML = arms[index_arms][0];
|
||||
}
|
||||
|
||||
function exportImage(){ //Export image so it can be saved as one PNG
|
||||
let ctx=canvas.getContext("2d");
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
neomoji_name.value = body[index_body][0] + "_" + eyes[index_eyes][0] + "_" + mouth[index_mouth][0] + "_" + arms[index_arms][0]; //Set name for the emoji to use as the image name and to show as shortcode
|
||||
|
||||
let body_export = new Image();
|
||||
let eyes_export = new Image();
|
||||
let mouth_export = new Image();
|
||||
let arms_export = new Image();
|
||||
|
||||
body_export.src = "." + body[index_body][1];
|
||||
body_export.onload = function() {
|
||||
ctx.drawImage(body_export, 0, 0, 256, 256);
|
||||
eyes_export.src = "." + eyes[index_eyes][1];
|
||||
eyes_export.onload = function() {
|
||||
ctx.drawImage(eyes_export, 0, 0, 256, 256);
|
||||
mouth_export.src = "." + mouth[index_mouth][1];
|
||||
mouth_export.onload = function() {
|
||||
ctx.drawImage(mouth_export, 0, 0, 256, 256);
|
||||
arms_export.src = "." + arms[index_arms][1];
|
||||
arms_export.onload = function() {
|
||||
ctx.drawImage(arms_export, 0, 0, 256, 256);
|
||||
let img = canvas.toDataURL("image/png");
|
||||
export_img.src = img;
|
||||
}
|
||||
function onColorChange() {
|
||||
for (let i = 0; i < color_change_callbacks.length; i++) {
|
||||
if (color_change_callbacks[i]) {
|
||||
color_change_callbacks[i]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function PartHandler(name) {
|
||||
this.name = name;
|
||||
this.entries = []; //Arrays to hold the parts
|
||||
this.entry_indices = []; //Maps selected_index to entries index
|
||||
this.selected_index = 0; //index_color -> arms.selected_index; index_arms -> arms.entry_indices[arms.selected_index]
|
||||
this.image_element = document.getElementById(name + "_img");
|
||||
this.name_element = document.getElementById(name + "_name");
|
||||
this.button_left = document.getElementById(name + "_left");
|
||||
this.button_right = document.getElementById(name + "_right");
|
||||
}
|
||||
|
||||
PartHandler.prototype = {
|
||||
fillArray: function(item) {
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
this.entries.push([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1
|
||||
},
|
||||
fillIndices: function() {
|
||||
for (let i = 0; i < this.entries.length; i++) {
|
||||
this.entry_indices.push(i); //By default preserve index
|
||||
}
|
||||
},
|
||||
getSelectedEntry: function() {
|
||||
return this.entries[this.entry_indices[this.selected_index]];
|
||||
},
|
||||
setIndex: function(index) {
|
||||
const modulo = this.entry_indices.length; //Check if index is too big for the array
|
||||
if (!modulo) {
|
||||
this.selected_index = 0; //Error
|
||||
} else {
|
||||
index %= modulo;
|
||||
if (index < 0) {
|
||||
index += modulo;
|
||||
}
|
||||
this.selected_index = index;
|
||||
}
|
||||
this.redraw();
|
||||
},
|
||||
redraw: function() {
|
||||
const entry = this.getSelectedEntry();
|
||||
this.image_element.src = "." + entry[1]; //Change URL of picture
|
||||
//Change name in controls
|
||||
this.updateOptions();
|
||||
this.name_element.selectedIndex = this.selected_index;
|
||||
},
|
||||
onClickNext: function() {
|
||||
this.setIndex(this.selected_index + 1);
|
||||
},
|
||||
onClickPrev: function() {
|
||||
this.setIndex(this.selected_index - 1);
|
||||
},
|
||||
onChangeDropdown: function() {
|
||||
this.setIndex(this.name_element.selectedIndex);
|
||||
},
|
||||
activateControls: function() {
|
||||
this.button_left.disabled = false;
|
||||
this.button_right.disabled = false;
|
||||
this.name_element.disabled = false;
|
||||
},
|
||||
randomize: function() {
|
||||
this.setIndex(Math.floor(Math.random() * this.entry_indices.length));
|
||||
},
|
||||
createExportImage: function() {
|
||||
const entry = this.getSelectedEntry();
|
||||
let img = new Image();
|
||||
img.src = "." + entry[1];
|
||||
return img;
|
||||
},
|
||||
updateOptions: function() {
|
||||
const options = this.name_element.options;
|
||||
for (let i = 0; i < this.entry_indices.length; i++) {
|
||||
const index = this.entry_indices[i];
|
||||
const entry = this.entries[index];
|
||||
if (options.length > i && options[i].value == entry[0]) {
|
||||
continue;
|
||||
} else {
|
||||
const option = new Option(entry[0], entry[0], false, this.selected_index == i);
|
||||
if (this.name_element.length <= i) {
|
||||
this.name_element.add(option);
|
||||
} else {
|
||||
this.name_element.remove(i);
|
||||
this.name_element.add(option, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export_img.hidden = false;
|
||||
neomoji_name.hidden = false;
|
||||
document.getElementById("exportSaveMessage").hidden = false;
|
||||
}
|
||||
|
||||
function ColoredPartHandler(name) {
|
||||
PartHandler.call(this, name);
|
||||
//For all the different colours of the arms there will be each a own array
|
||||
this.colored_indices = Object.create(null);
|
||||
for (let i = 0; i < color_names.length; i++) {
|
||||
this.colored_indices[color_names[i]] = [];
|
||||
}
|
||||
this.entry_indices = this.colored_indices[selected_color];
|
||||
const that = this;
|
||||
color_change_callbacks.push(function() {
|
||||
that.onColorChange();
|
||||
});
|
||||
}
|
||||
|
||||
ColoredPartHandler.prototype = Object.assign(Object.create(PartHandler.prototype), {
|
||||
constructor: PartHandler,
|
||||
fillArray: function(item) {
|
||||
let name = item.name;
|
||||
let url = item.url;
|
||||
let color = item.color;
|
||||
this.entries.push([name, url, color]); //Two dimensional array, Second dimension holds name on index 0, url at index 1, and color at index 2
|
||||
},
|
||||
fillIndices: function() {
|
||||
for (let i = 0; i < this.entries.length; i++) {
|
||||
const color = this.entries[i][2];
|
||||
if (color == "") {
|
||||
//All colors
|
||||
for (let j in this.colored_indices) {
|
||||
this.colored_indices[j].push(i);
|
||||
}
|
||||
} else {
|
||||
const indices = this.colored_indices[color];
|
||||
if (indices == undefined) {
|
||||
console.log("Cannot register " + this.name + " with unknown color: " + color);
|
||||
} else {
|
||||
indices.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onColorChange: function() {
|
||||
this.entry_indices = this.colored_indices[selected_color];
|
||||
this.redraw();
|
||||
},
|
||||
});
|
||||
|
||||
function BodyPartHandler(name) {
|
||||
PartHandler.call(this, name);
|
||||
}
|
||||
|
||||
BodyPartHandler.prototype = Object.assign(Object.create(PartHandler.prototype), {
|
||||
constructor: PartHandler,
|
||||
fillArray: ColoredPartHandler.prototype.fillArray,
|
||||
setIndex: function(index) {
|
||||
const modulo = this.entry_indices.length; //Check if index is too big for the array
|
||||
if (!modulo) {
|
||||
this.selected_index = 0; //Error
|
||||
} else {
|
||||
index %= modulo;
|
||||
if (index < 0) {
|
||||
index += modulo;
|
||||
}
|
||||
this.selected_index = index;
|
||||
}
|
||||
this.redraw();
|
||||
const entry = this.getSelectedEntry();
|
||||
selected_color = entry[2]; //Global
|
||||
onColorChange(); //Global
|
||||
},
|
||||
});
|
||||
|
||||
const part_handlers = {
|
||||
body: new BodyPartHandler("body"),
|
||||
eyes: new PartHandler("eyes"),
|
||||
mouth: new PartHandler("mouth"),
|
||||
arms: new ColoredPartHandler("arms"),
|
||||
};
|
||||
|
||||
|
||||
// Loading the JSON and getting all the available parts
|
||||
async function getData() {
|
||||
fetch('./parts.json')
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
loadParts(data);
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.log('An error occurred:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function loadParts(parts) {
|
||||
//Load parts into Arrays
|
||||
for (const i in part_handlers) {
|
||||
parts.type[i].forEach(function(p) {part_handlers[i].fillArray(p);});
|
||||
}
|
||||
|
||||
//find the indexes of each part of the corresponding color and write those into the color arrays
|
||||
for (const i in part_handlers) {
|
||||
part_handlers[i].fillIndices();
|
||||
}
|
||||
|
||||
//Randomize initial view
|
||||
randomize();
|
||||
|
||||
// If there was a hash, restore as a direct permalink.
|
||||
if (document.location.hash != "") {
|
||||
loadFromHash(document.location.hash);
|
||||
}
|
||||
window.addEventListener("hashchange", () => {
|
||||
loadFromHash(document.location.hash);
|
||||
});
|
||||
|
||||
//Show little statistic
|
||||
var sum = 0;
|
||||
var variety = 1;
|
||||
for (const i in part_handlers) {
|
||||
sum += part_handlers[i].entries.length;
|
||||
variety *= part_handlers[i].entry_indices.length;
|
||||
}
|
||||
|
||||
stats.innerHTML = "There are " + sum + " Elements available,<br />with " + new Intl.NumberFormat("de-DE").format(variety) + " possible combinations.";
|
||||
|
||||
//Activate the buttons after everything is loaded in
|
||||
for (const i in part_handlers) {
|
||||
part_handlers[i].activateControls();
|
||||
}
|
||||
document.getElementById("random").disabled = false;
|
||||
document.getElementById("export").disabled = false;
|
||||
|
||||
}
|
||||
|
||||
function loadFromHash(hash) {
|
||||
let parts = hash
|
||||
.slice(1) // the first character is always the '#' sign
|
||||
.split('+');
|
||||
|
||||
// define a constant order for the parts to appear in the hash
|
||||
const parts_order = ["body", "eyes", "mouth", "arms"];
|
||||
|
||||
if (parts.length == parts_order.length) {
|
||||
// convert the part names to part indices
|
||||
parts = parts.map((name, i) =>
|
||||
Array.from(part_handlers[parts_order[i]].name_element.options).findIndex(x => x.value === name)
|
||||
);
|
||||
if (parts.every(x => x != -1)) {
|
||||
// all part names were found
|
||||
parts.forEach((part_index, i) => part_handlers[parts_order[i]].setIndex(part_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function randomize() { //Randomize which parts are shown
|
||||
for (const i in part_handlers) {
|
||||
part_handlers[i].randomize();
|
||||
}
|
||||
}
|
||||
|
||||
function exportImage() { //Export image so it can be saved as one PNG
|
||||
let ctx=canvas.getContext("2d");
|
||||
let export_mime = document.getElementById("export-mime").value;
|
||||
let export_options = undefined;
|
||||
if (document.getElementById("export-quality-enabled").checked) {
|
||||
export_options = +document.getElementById("export-quality").value;
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
//Set name for the emoji to use as the image name and to show as shortcode
|
||||
let name = part_handlers.body.getSelectedEntry()[0] + "_" + part_handlers.eyes.getSelectedEntry()[0] + "_" + part_handlers.mouth.getSelectedEntry()[0] + "_" + part_handlers.arms.getSelectedEntry()[0];
|
||||
neomoji_name.innerText = name;
|
||||
neomoji_name.href = new URL("#" + part_handlers.body.getSelectedEntry()[0] + "+" + part_handlers.eyes.getSelectedEntry()[0] + "+" + part_handlers.mouth.getSelectedEntry()[0] + "+" + part_handlers.arms.getSelectedEntry()[0], document.location.href)
|
||||
|
||||
let export_layers = [
|
||||
part_handlers.body.createExportImage(),
|
||||
part_handlers.eyes.createExportImage(),
|
||||
part_handlers.mouth.createExportImage(),
|
||||
part_handlers.arms.createExportImage(),
|
||||
];
|
||||
|
||||
function layerCallback() {
|
||||
while (export_layers.length) {
|
||||
const layer = export_layers[0];
|
||||
if (!layer.complete) {
|
||||
layer.onload = layerCallback;
|
||||
return; //Wait to load
|
||||
}
|
||||
//Finished waiting
|
||||
export_layers.shift()
|
||||
ctx.drawImage(layer, 0, 0, 256, 256);
|
||||
}
|
||||
let img = canvas.toDataURL(export_mime, export_options);
|
||||
export_img.src = img;
|
||||
export_img_download.href = img;
|
||||
export_img_download.download = name + "." + (export_mime.match(/\/(\w+)/) || ["", "png"])[1];
|
||||
}
|
||||
|
||||
setTimeout(layerCallback, 0); //Run asynchronously
|
||||
|
||||
export_img.hidden = false;
|
||||
export_img_download.hidden = false;
|
||||
neomoji_name.hidden = false;
|
||||
document.getElementById("exportSaveMessage").hidden = false;
|
||||
}
|
||||
|
||||
NeomojiMixer.PartHandler = PartHandler;
|
||||
NeomojiMixer.ColoredPartHandler = ColoredPartHandler;
|
||||
NeomojiMixer.BodyPartHandler = BodyPartHandler;
|
||||
|
||||
NeomojiMixer.color_names = color_names;
|
||||
NeomojiMixer.color_change_callbacks = color_change_callbacks;
|
||||
NeomojiMixer.part_handlers = part_handlers;
|
||||
NeomojiMixer.onColorChange = onColorChange;
|
||||
NeomojiMixer.getData = getData;
|
||||
NeomojiMixer.loadParts = loadParts;
|
||||
NeomojiMixer.randomize = randomize;
|
||||
NeomojiMixer.exportImage = exportImage;
|
||||
NeomojiMixer.canvas = canvas;
|
||||
NeomojiMixer.export_img = export_img;
|
||||
NeomojiMixer.neomoji_name = neomoji_name;
|
||||
NeomojiMixer.stats = stats;
|
||||
|
||||
Object.defineProperty(NeomojiMixer, 'selected_color', {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return selected_color;
|
||||
},
|
||||
set: function(value) {
|
||||
selected_color = value;
|
||||
onColorChange();
|
||||
},
|
||||
});
|
||||
|
||||
return NeomojiMixer;
|
||||
})(window.NeomojiMixer || {});
|
||||
|
||||
|
||||
//Main Programm
|
||||
document.getElementById("noJSmessage").hidden = true;
|
||||
getData();
|
||||
NeomojiMixer.getData();
|
||||
|
|
45
parts.json
|
@ -13,7 +13,7 @@
|
|||
{"name": "devil", "url": "/parts/eyes_devil.png"},
|
||||
{"name": "drowsy", "url": "/parts/eyes_drowsy.png"},
|
||||
{"name": "evil", "url": "/parts/eyes_evil.png"},
|
||||
{"name": ">_<", "url": "/parts/eyes_><.png"},
|
||||
{"name": ">_<", "url": "/parts/eyes_squint.png"},
|
||||
{"name": "cry", "url": "/parts/eyes_cry.png"},
|
||||
{"name": "owo", "url": "/parts/eyes_owo.png"},
|
||||
{"name": "sad", "url": "/parts/eyes_sad.png"},
|
||||
|
@ -56,6 +56,7 @@
|
|||
{"name": "neocat_mask","url": "/parts/neocat_mask.png", "color": "yellow"},
|
||||
{"name": "neoredpanda","url": "/parts/neoredpanda.png", "color": "orange"},
|
||||
{"name": "neopossum","url": "/parts/neopossum.png", "color": "lightgrey"},
|
||||
{"name": "neopossum_floof","url": "/parts/neopossum_floof.png", "color": "lightgrey"},
|
||||
{"name": "neopossum_angel","url": "/parts/neopossum_angel.png", "color": "lightgrey"},
|
||||
{"name": "neopossum_foxmask","url": "/parts/neopossum_foxmask.png", "color": "lightgrey"},
|
||||
{"name": "neopossum_catmask","url": "/parts/neopossum_catmask.png", "color": "lightgrey"},
|
||||
|
@ -65,6 +66,16 @@
|
|||
{"name": "neopossum_rainbow","url": "/parts/neopossum_rainbow.png", "color": "lightgrey"},
|
||||
{"name": "neorat","url": "/parts/neorat.png", "color": "white"},
|
||||
{"name": "neorat_frozen","url": "/parts/neorat_frozen.png", "color": "blue"},
|
||||
{"name": "neobread","url": "/parts/neobread.png", "color": "lightbrown"},
|
||||
{"name": "neobread_ace","url": "/parts/neobread_ace.png", "color": "lightbrown"},
|
||||
{"name": "neobread_agender","url": "/parts/neobread_agender.png", "color": "lightbrown"},
|
||||
{"name": "neobread_aro","url": "/parts/neobread_aro.png", "color": "lightbrown"},
|
||||
{"name": "neobread_bi","url": "/parts/neobread_bi.png", "color": "lightbrown"},
|
||||
{"name": "neobread_lesbian","url": "/parts/neobread_lesbian.png", "color": "lightbrown"},
|
||||
{"name": "neobread_nb","url": "/parts/neobread_nb.png", "color": "lightbrown"},
|
||||
{"name": "neobread_pan","url": "/parts/neobread_pan.png", "color": "lightbrown"},
|
||||
{"name": "neobread_rainbow","url": "/parts/neobread_rainbow.png", "color": "lightbrown"},
|
||||
{"name": "neobread_trans","url": "/parts/neobread_trans.png", "color": "lightbrown"},
|
||||
{"name": "neofox","url": "/parts/neofox.png", "color": "orange"}
|
||||
],
|
||||
"mouth": [
|
||||
|
@ -91,6 +102,7 @@
|
|||
{"name": "nom_verified","url": "/parts/mouth_nom_verified.png"},
|
||||
{"name": "nom_waffle","url": "/parts/mouth_nom_waffle.png"},
|
||||
{"name": "hissing","url": "/parts/mouth_hissing.png"},
|
||||
{"name": "woozy","url": "/parts/mouth_woozy.png"},
|
||||
{"name": "blank", "url": "/parts/blank.png"}
|
||||
],
|
||||
"arms": [
|
||||
|
@ -280,6 +292,37 @@
|
|||
{"name": "book","url": "/parts/arms_book_yellow.png", "color": "yellow"},
|
||||
{"name": "hold_burger","url": "/parts/arms_hold_burger_yellow.png", "color": "yellow"},
|
||||
{"name": "hungry","url": "/parts/arms_hungry_yellow.png", "color": "yellow"},
|
||||
{"name": "hide","url": "/parts/arms_hide_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "aww","url": "/parts/arms_aww_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "pleading","url": "/parts/arms_pleading_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "reach","url": "/parts/arms_reach_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "3c","url": "/parts/arms_3c_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "facepalm","url": "/parts/arms_facepalm_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "mug","url": "/parts/arms_mug_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "knife","url": "/parts/arms_knife_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "phone","url": "/parts/arms_phone_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "fingerguns","url": "/parts/arms_fingerguns_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "science","url": "/parts/arms_science_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_no","url": "/parts/arms_sign_no_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_aaa","url": "/parts/arms_sign_aaa_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_nya","url": "/parts/arms_sign_nya_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_thx","url": "/parts/arms_sign_thx_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_yes","url": "/parts/arms_sign_yes_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_yip","url": "/parts/arms_sign_yip_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_boobs","url": "/parts/arms_sign_boobs_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_butts","url": "/parts/arms_sign_butts_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sign_heart","url": "/parts/arms_heart_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "solder","url": "/parts/arms_solder_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "redlos","url": "/parts/arms_redlos_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "think","url": "/parts/arms_think_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "sweat","url": "/parts/arms_sweat_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "verified","url": "/parts/arms_verified_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "shocked","url": "/parts/arms_shocked_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "thumbsdown","url": "/parts/arms_thumbsdown_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "thumbsup","url": "/parts/arms_thumbsup_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "book","url": "/parts/arms_book_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "hold_burger","url": "/parts/arms_hold_burger_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "hungry","url": "/parts/arms_hungry_lightbrown.png", "color": "lightbrown"},
|
||||
{"name": "boop","url": "/parts/arms_boop.png", "color": ""},
|
||||
{"name": "sip","url": "/parts/arms_sip.png", "color": ""},
|
||||
{"name": "blank", "url": "/parts/blank.png", "color": ""}
|
||||
|
|
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 21 KiB |