From d3470b5b3e42548817036a0b4ce28153db211e10 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Thu, 30 Sep 2021 11:57:35 -0400 Subject: [PATCH] Add entity forms. Add Alex Xuria Forms allow for one entity to have multiple distinct sets of views and sizes. --- macrovision.css | 1 + macrovision.html | 4 + macrovision.js | 118 +- media/attribution.js | 64 + media/characters/alex-xuria/demon-back.svg | 768 +++++++++++ media/characters/alex-xuria/demon-cock.svg | 197 +++ media/characters/alex-xuria/demon-foot.svg | 81 ++ media/characters/alex-xuria/demon-front.svg | 1184 +++++++++++++++++ media/characters/alex-xuria/demon-hand.svg | 109 ++ media/characters/alex-xuria/demon-head.svg | 371 ++++++ media/characters/alex-xuria/demon-paw.svg | 165 +++ .../alex-xuria/demon-tail-closed.svg | 54 + .../characters/alex-xuria/demon-tail-open.svg | 190 +++ media/characters/alex-xuria/incubus-back.svg | 559 ++++++++ media/characters/alex-xuria/incubus-front.svg | 675 ++++++++++ media/characters/alex-xuria/incubus-head.svg | 424 ++++++ media/characters/alex-xuria/rabbit-back.svg | 295 ++++ media/characters/alex-xuria/rabbit-front.svg | 360 +++++ media/characters/alex-xuria/rabbit-side.svg | 258 ++++ presets/characters.js | 180 ++- 20 files changed, 6045 insertions(+), 12 deletions(-) create mode 100644 media/characters/alex-xuria/demon-back.svg create mode 100644 media/characters/alex-xuria/demon-cock.svg create mode 100644 media/characters/alex-xuria/demon-foot.svg create mode 100644 media/characters/alex-xuria/demon-front.svg create mode 100644 media/characters/alex-xuria/demon-hand.svg create mode 100644 media/characters/alex-xuria/demon-head.svg create mode 100644 media/characters/alex-xuria/demon-paw.svg create mode 100644 media/characters/alex-xuria/demon-tail-closed.svg create mode 100644 media/characters/alex-xuria/demon-tail-open.svg create mode 100644 media/characters/alex-xuria/incubus-back.svg create mode 100644 media/characters/alex-xuria/incubus-front.svg create mode 100644 media/characters/alex-xuria/incubus-head.svg create mode 100644 media/characters/alex-xuria/rabbit-back.svg create mode 100644 media/characters/alex-xuria/rabbit-front.svg create mode 100644 media/characters/alex-xuria/rabbit-side.svg diff --git a/macrovision.css b/macrovision.css index c9b9867f..c66daabf 100644 --- a/macrovision.css +++ b/macrovision.css @@ -645,6 +645,7 @@ i.far { font-size: 150%; } +#entity-form, #entity-view { text-align: center; font-weight: bold; diff --git a/macrovision.html b/macrovision.html index aed82471..278f4b43 100644 --- a/macrovision.html +++ b/macrovision.html @@ -128,6 +128,10 @@
+
+ Form +
+
View
diff --git a/macrovision.js b/macrovision.js index 886565ab..7c6aca4f 100644 --- a/macrovision.js +++ b/macrovision.js @@ -1068,14 +1068,14 @@ function drawHorizontalScale(ifDirty = false) { // It is invoked like makeEntity so that it can be dropped in easily, // but returns an object that lets you construct many copies of an entity, // rather than creating a new entity. -function createEntityMaker(info, views, sizes) { +function createEntityMaker(info, views, sizes, forms) { const maker = {}; maker.name = info.name; maker.info = info; maker.sizes = sizes; - maker.constructor = () => makeEntity(info, views, sizes); + maker.constructor = () => makeEntity(info, views, sizes, forms); maker.authors = []; maker.owners = []; maker.nsfw = false; @@ -1110,7 +1110,7 @@ function createEntityMaker(info, views, sizes) { // references to a common object. This allows for the objects to be // safely mutated. -function makeEntity(info, views, sizes) { +function makeEntity(info, views, sizes, forms = {}) { const entityTemplate = { name: info.name, identifier: info.name, @@ -1119,18 +1119,31 @@ function makeEntity(info, views, sizes) { info: JSON.parse(JSON.stringify(info)), views: JSON.parse(JSON.stringify(views), math.reviver), sizes: sizes === undefined ? [] : JSON.parse(JSON.stringify(sizes), math.reviver), + forms: forms, init: function () { const entity = this; + + Object.entries(this.forms).forEach(([formKey, form]) => { + if (form.default) { + this.defaultForm = formKey; + } + }); + Object.entries(this.views).forEach(([viewKey, view]) => { view.parent = this; if (this.defaultView === undefined) { this.defaultView = viewKey; this.view = viewKey; + this.form = view.form; } if (view.default) { - this.defaultView = viewKey; - this.view = viewKey; + if (forms === {} || this.defaultForm === view.form) + { + this.defaultView = viewKey; + this.view = viewKey; + this.form = view.form; + } } // to remember the units the user last picked @@ -1231,6 +1244,14 @@ function makeEntity(info, views, sizes) { } ) + this.formViews = {}; + + Object.entries(views).forEach(([key, value]) => { + if (value.default) { + this.formViews[value.form] = key; + } + }); + delete this.init; return this; } @@ -1353,6 +1374,7 @@ function select(target) { displayAttribution(selectedEntity.views[selectedEntity.view].image.source); + configFormList(selectedEntity, selectedEntity.form); configViewList(selectedEntity, selectedEntity.view); configEntityOptions(selectedEntity, selectedEntity.view); configViewOptions(selectedEntity, selectedEntity.view); @@ -1364,6 +1386,35 @@ function select(target) { document.querySelector("#fit").disabled = false; } +function configFormList(entity, selectedForm) { + const label = document.querySelector("#options-label-form"); + const list = document.querySelector("#entity-form"); + + list.innerHTML = ""; + + + if (selectedForm === undefined) { + label.style.display = "none"; + list.style.display = "none"; + return; + } + + label.style.display = "block"; + list.style.display = "block"; + + Object.keys(entity.forms).forEach(form => { + const option = document.createElement("option"); + option.innerText = entity.forms[form].name; + option.value = form; + + if (form === selectedForm) { + option.selected = true; + } + + list.appendChild(option); + }); +} + function configViewList(entity, selectedView) { const list = document.querySelector("#entity-view"); @@ -1372,6 +1423,11 @@ function configViewList(entity, selectedView) { list.style.display = "block"; Object.keys(entity.views).forEach(view => { + if (Object.keys(entity.forms).length > 0) { + if (entity.views[view].form !== entity.form) { + return; + } + } const option = document.createElement("option"); option.innerText = entity.views[view].name; option.value = view; @@ -1488,18 +1544,35 @@ function configEntityOptions(entity, view) { holder.appendChild(nameLabel); holder.appendChild(nameRow); + configSizeList(entity); + + document.querySelector("#options-order-display").innerText = entity.priority; + document.querySelector("#options-brightness-display").innerText = entity.brightness; + document.querySelector("#options-ordering").style.display = "flex"; +} + +function configSizeList(entity) { const defaultHolder = document.querySelector("#options-entity-defaults"); defaultHolder.innerHTML = ""; entity.sizes.forEach(defaultInfo => { + if (Object.keys(entity.forms).length > 0) { + if (defaultInfo.form !== entity.form) { + return; + } + } const button = document.createElement("button"); button.classList.add("options-button"); button.innerText = defaultInfo.name; button.addEventListener("click", e => { - entity.views[entity.defaultView].height = defaultInfo.height; + if (Object.keys(entity.forms).length > 0) { + entity.views[entity.formViews[entity.form]].height = defaultInfo.height; + } else { + entity.views[entity.defaultView].height = defaultInfo.height; + } entity.dirty = true; updateEntityOptions(entity, entity.view); updateViewOptions(entity, entity.view); @@ -1517,10 +1590,6 @@ function configEntityOptions(entity, view) { defaultHolder.appendChild(button); }); - - document.querySelector("#options-order-display").innerText = entity.priority; - document.querySelector("#options-brightness-display").innerText = entity.brightness; - document.querySelector("#options-ordering").style.display = "flex"; } function updateEntityOptions(entity, view) { @@ -3206,6 +3275,33 @@ document.addEventListener("DOMContentLoaded", () => { clickUp(fakeEvent); }); + const formList = document.querySelector("#entity-form"); + + formList.addEventListener("input", e => { + const entity = entities[selected.dataset.key]; + entity.form = e.target.value; + entity.view = entity.formViews[entity.form]; + + configViewList(entity, entity.view); + + const image = entity.views[entity.view].image; + selected.querySelector(".entity-image").src = image.source; + + configViewOptions(entity, entity.view); + + displayAttribution(image.source); + + if (image.bottom !== undefined) { + selected.querySelector(".entity-image").style.setProperty("--offset", ((-1 + image.bottom) * 100) + "%") + } else { + selected.querySelector(".entity-image").style.setProperty("--offset", ((-1) * 100) + "%") + } + configSizeList(entity); + updateSizes(); + updateEntityOptions(entities[selected.dataset.key], e.target.value); + updateViewOptions(entities[selected.dataset.key], entity.view); + }); + const viewList = document.querySelector("#entity-view"); document.querySelector("#entity-view").addEventListener("input", e => { @@ -4492,6 +4588,7 @@ function exportScene() { scale: entity.scale, rotation: entity.rotation, view: entity.view, + form: entity.form, x: element.dataset.x, y: element.dataset.y, priority: entity.priority, @@ -4652,6 +4749,7 @@ function importScene(data) { entity.rotation = entityInfo.rotation; entity.priority = entityInfo.priority; entity.brightness = entityInfo.brightness; + entity.form = entityInfo.form; displayEntity(entity, entityInfo.view, entityInfo.x, entityInfo.y); }); diff --git a/media/attribution.js b/media/attribution.js index ea827455..8bfa087e 100644 --- a/media/attribution.js +++ b/media/attribution.js @@ -17423,6 +17423,54 @@ const attributionData = { "mongrelist" ] }, + { + prefix: "./media/characters/alex-xuria/", + files: [ + { name: "demon-back.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-cock.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: true }, + { name: "demon-foot.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-front.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-hand.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-head.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-paw.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-tail-closed.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + { name: "demon-tail-open.svg", source: "https://www.furaffinity.net/view/37480472/ ", nsfw: false }, + ], + authors: [ + "shadoweyenoom" + ], + owners: [ + "gula" + ] + }, + { + prefix: "./media/characters/alex-xuria/", + files: [ + { name: "incubus-back.svg", source: "https://www.furaffinity.net/view/41985342/", nsfw: false }, + { name: "incubus-front.svg", source: "https://www.furaffinity.net/view/41985342/", nsfw: false }, + { name: "incubus-head.svg", source: "https://www.furaffinity.net/view/41985342/", nsfw: false }, + ], + authors: [ + "mihaelt" + ], + owners: [ + "gula" + ] + }, + { + prefix: "./media/characters/alex-xuria/", + files: [ + { name: "rabbit-back.svg", source: "https://www.furaffinity.net/view/22584929/", nsfw: true }, + { name: "rabbit-front.svg", source: "https://www.furaffinity.net/view/22584929/", nsfw: true }, + { name: "rabbit-side.svg", source: "https://www.furaffinity.net/view/22584929/", nsfw: true }, + ], + authors: [ + "lustbubbles" + ], + owners: [ + "gula" + ] + }, //characters { prefix: "./media/dildos/chance/", @@ -24113,6 +24161,22 @@ const attributionData = { "name": "Terry", "url": null }, + "gula": { + "name": "Gula", + "url": "https://www.furaffinity.net/user/gula/" + }, + "shadoweyenoom": { + "name": "ShadowEyenoom", + "url": "https://www.furaffinity.net/user/shadoweyenoom" + }, + "mihaelt": { + "name": "Mihaelt", + "url": "https://www.furaffinity.net/user/mihaelt" + }, + "lustbubbles": { + "name": "LustBubbles", + "url": "https://www.furaffinity.net/user/lustbubbles" + }, } } diff --git a/media/characters/alex-xuria/demon-back.svg b/media/characters/alex-xuria/demon-back.svg new file mode 100644 index 00000000..44fd238c --- /dev/null +++ b/media/characters/alex-xuria/demon-back.svg @@ -0,0 +1,768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-cock.svg b/media/characters/alex-xuria/demon-cock.svg new file mode 100644 index 00000000..3d145f2a --- /dev/null +++ b/media/characters/alex-xuria/demon-cock.svg @@ -0,0 +1,197 @@ + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-foot.svg b/media/characters/alex-xuria/demon-foot.svg new file mode 100644 index 00000000..48d35db6 --- /dev/null +++ b/media/characters/alex-xuria/demon-foot.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-front.svg b/media/characters/alex-xuria/demon-front.svg new file mode 100644 index 00000000..e00f18fc --- /dev/null +++ b/media/characters/alex-xuria/demon-front.svg @@ -0,0 +1,1184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-hand.svg b/media/characters/alex-xuria/demon-hand.svg new file mode 100644 index 00000000..d2f0ccaf --- /dev/null +++ b/media/characters/alex-xuria/demon-hand.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-head.svg b/media/characters/alex-xuria/demon-head.svg new file mode 100644 index 00000000..26cd3282 --- /dev/null +++ b/media/characters/alex-xuria/demon-head.svg @@ -0,0 +1,371 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-paw.svg b/media/characters/alex-xuria/demon-paw.svg new file mode 100644 index 00000000..3244847a --- /dev/null +++ b/media/characters/alex-xuria/demon-paw.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-tail-closed.svg b/media/characters/alex-xuria/demon-tail-closed.svg new file mode 100644 index 00000000..b514f385 --- /dev/null +++ b/media/characters/alex-xuria/demon-tail-closed.svg @@ -0,0 +1,54 @@ + + + + + + + + + diff --git a/media/characters/alex-xuria/demon-tail-open.svg b/media/characters/alex-xuria/demon-tail-open.svg new file mode 100644 index 00000000..8a3e852d --- /dev/null +++ b/media/characters/alex-xuria/demon-tail-open.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/incubus-back.svg b/media/characters/alex-xuria/incubus-back.svg new file mode 100644 index 00000000..c97b3207 --- /dev/null +++ b/media/characters/alex-xuria/incubus-back.svg @@ -0,0 +1,559 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/incubus-front.svg b/media/characters/alex-xuria/incubus-front.svg new file mode 100644 index 00000000..9d89f92d --- /dev/null +++ b/media/characters/alex-xuria/incubus-front.svg @@ -0,0 +1,675 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/incubus-head.svg b/media/characters/alex-xuria/incubus-head.svg new file mode 100644 index 00000000..223af5be --- /dev/null +++ b/media/characters/alex-xuria/incubus-head.svg @@ -0,0 +1,424 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/rabbit-back.svg b/media/characters/alex-xuria/rabbit-back.svg new file mode 100644 index 00000000..7c57827d --- /dev/null +++ b/media/characters/alex-xuria/rabbit-back.svg @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/rabbit-front.svg b/media/characters/alex-xuria/rabbit-front.svg new file mode 100644 index 00000000..f030d8ba --- /dev/null +++ b/media/characters/alex-xuria/rabbit-front.svg @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/characters/alex-xuria/rabbit-side.svg b/media/characters/alex-xuria/rabbit-side.svg new file mode 100644 index 00000000..541484ef --- /dev/null +++ b/media/characters/alex-xuria/rabbit-side.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/presets/characters.js b/presets/characters.js index e731c0ea..11b98655 100644 --- a/presets/characters.js +++ b/presets/characters.js @@ -1,6 +1,6 @@ const characterMakers = []; -function makeCharacter(info, viewInfo, defaultSizes) { +function makeCharacter(info, viewInfo, defaultSizes, forms) { views = {}; Object.entries(viewInfo).forEach(([key, value]) => { @@ -14,6 +14,7 @@ function makeCharacter(info, viewInfo, defaultSizes) { } }, image: value.image, + form: value.form, name: value.name, info: value.info, rename: value.rename, @@ -57,7 +58,7 @@ function makeCharacter(info, viewInfo, defaultSizes) { } }); - return createEntityMaker(info, views, defaultSizes); + return createEntityMaker(info, views, defaultSizes, forms); } const speciesData = { @@ -46144,6 +46145,181 @@ characterMakers.push(() => makeCharacter( ] )) +characterMakers.push(() => makeCharacter( + { name: "Alex Xuria", species: ["demon", "rabbit"], tags: ["anthro"] }, + { + demonFront: { + height: math.unit(36, "feet"), + name: "Front", + image: { + source: "./media/characters/alex-xuria/demon-front.svg", + extra: 1705/1673, + bottom: 198/1903 + }, + form: "demon", + default: true + }, + demonBack: { + height: math.unit(36, "feet"), + name: "Back", + image: { + source: "./media/characters/alex-xuria/demon-back.svg", + extra: 1725/1693, + bottom: 70/1795 + }, + form: "demon" + }, + demonHead: { + height: math.unit(2.14, "meters"), + name: "Head", + image: { + source: "./media/characters/alex-xuria/demon-head.svg" + }, + form: "demon" + }, + demonHand: { + height: math.unit(1.61, "meters"), + name: "Hand", + image: { + source: "./media/characters/alex-xuria/demon-hand.svg" + }, + form: "demon" + }, + demonPaw: { + height: math.unit(1.35, "meters"), + name: "Paw", + image: { + source: "./media/characters/alex-xuria/demon-paw.svg" + }, + form: "demon" + }, + demonFoot: { + height: math.unit(2.2, "meters"), + name: "Foot", + image: { + source: "./media/characters/alex-xuria/demon-foot.svg" + }, + form: "demon" + }, + demonCock: { + height: math.unit(1.74, "meters"), + name: "Cock", + image: { + source: "./media/characters/alex-xuria/demon-cock.svg" + }, + form: "demon" + }, + demonTailClosed: { + height: math.unit(1.47, "meters"), + name: "Tail (Closed)", + image: { + source: "./media/characters/alex-xuria/demon-tail-closed.svg" + }, + form: "demon" + }, + demonTailOpen: { + height: math.unit(2.85, "meters"), + name: "Tail (Open)", + image: { + source: "./media/characters/alex-xuria/demon-tail-open.svg" + }, + form: "demon" + }, + incubusFront: { + height: math.unit(12, "feet"), + name: "Front", + image: { + source: "./media/characters/alex-xuria/incubus-front.svg", + extra: 1754/1677, + bottom: 125/1879 + }, + form: "incubus", + default: true + }, + incubusBack: { + height: math.unit(12, "feet"), + name: "Back", + image: { + source: "./media/characters/alex-xuria/incubus-back.svg", + extra: 1702/1647, + bottom: 30/1732 + }, + form: "incubus" + }, + incubusHead: { + height: math.unit(3.45, "feet"), + name: "Head", + image: { + source: "./media/characters/alex-xuria/incubus-head.svg" + }, + form: "incubus" + }, + rabbitFront: { + height: math.unit(6, "feet"), + name: "Front", + image: { + source: "./media/characters/alex-xuria/rabbit-front.svg", + extra: 1369/1349, + bottom: 45/1414 + }, + form: "rabbit", + default: true + }, + rabbitSide: { + height: math.unit(6, "feet"), + name: "Side", + image: { + source: "./media/characters/alex-xuria/rabbit-side.svg", + extra: 1370/1356, + bottom: 37/1407 + }, + form: "rabbit" + }, + rabbitBack: { + height: math.unit(6, "feet"), + name: "Back", + image: { + source: "./media/characters/alex-xuria/rabbit-back.svg", + extra: 1375/1358, + bottom: 43/1418 + }, + form: "rabbit" + }, + }, + [ + { + name: "Normal", + height: math.unit(6, "feet"), + default: true, + form: "rabbit" + }, + { + name: "Incubus", + height: math.unit(12, "feet"), + default: true, + form: "incubus" + }, + { + name: "Demon", + height: math.unit(36, "feet"), + default: true, + form: "demon" + } + ], + { + "demon": { + name: "Demon", + default: true + }, + "incubus": { + name: "Incubus", + }, + "rabbit": { + name: "Rabbit" + } + } +)) + //characters function makeCharacters() {