diff --git a/css/style-9.css b/css/style-9.css
index eddc2db9..980c7f4e 100644
--- a/css/style-9.css
+++ b/css/style-9.css
@@ -1,909 +1,933 @@
-/*fonts*/
-@font-face {
- font-family: gothammedium;
- src: url("../fonts/gotham-medium.ttf") format('truetype');
-}
-@font-face {
- font-family: belerenb;
- src: url("../fonts/beleren-b.ttf") format('truetype');
-}
-@font-face {
- font-family: belerenbsc;
- src: url("../fonts/beleren-bsc.ttf") format('truetype');
-}
-@font-face {
- font-family: matrix;
- src: url("../fonts/matrix.ttf") format('truetype');
-}
-@font-face {
- font-family: matrixb;
- src: url("../fonts/matrix-b.ttf") format('truetype');
-}
-@font-face {
- font-family: matrixbsc;
- src: url("../fonts/Matrix Bold Small Caps.ttf") format('truetype');
-}
-@font-face {
- font-family: mplantin;
- src: url("../fonts/mplantin.ttf") format('truetype');
-}
-@font-face {
- font-family: mplantini;
- src: url("../fonts/mplantin-i.ttf") format('truetype');
-}
-@font-face {
- font-family: plantinsemibold;
- src: url("../fonts/plantin-semibold.otf") format('opentype');
-}
-@font-face {
- font-family: plantinsemibolditalic;
- src: url("../fonts/Plantin-SemiboldItalic.otf") format('opentype');
-}
-@font-face {
- font-family: goudymedieval;
- src: url("../fonts/goudy-medieval.ttf") format('truetype');
-}
-@font-face {
- font-family: phyrexianold;
- src: url("../fonts/phyrexian.ttf") format('truetype');
-}
-@font-face {
- font-family: phyrexian;
- src: url("../fonts/phy.woff2") format("woff2");
-}
-@font-face {
- font-family: Montserrat-SemiBold;
- src: url("../fonts/Montserrat-SemiBold.ttf") format('truetype');
-}
-@font-face {
- font-family: Montserrat-Medium;
- src: url("../fonts/Montserrat-Medium.ttf") format('truetype');
-}
-@font-face {
- font-family: Acme-Regular;
- src: url("../fonts/Acme-Regular.ttf") format('truetype');
-}
-@font-face {
- font-family: fritz-quadrata;
- src: url("../fonts/fritz-quadrata.ttf") format('truetype');
-}
-@font-face {
- font-family: japanese-title;
- src: url("../fonts/NudMotoyaExAporo_W6.ttf") format('truetype');
-}
-@font-face {
- font-family: japanese;
- src: url('../fonts/2012c863631ba71f874aba70590795a1.otf') format('opentype');
-}
-@font-face {
- font-family: invocation;
- src: url('../fonts/Invocation.ttf') format('truetype');
-}
-@font-face {
- font-family: invocation-text;
- src: url('../fonts/shango-gothic-bold.ttf') format('truetype');
-}
-@font-face {
- font-family: souvenir;
- src: url('../fonts/Souvenir-Itc-T-OT-Bold.otf') format('opentype');
-}
-@font-face {
- font-family: palatino;
- src: url('../fonts/Palatino Font.ttf') format('truetype');
-}
-@font-face {
- font-family: amanda;
- src: url('../fonts/Amanda Std Regular.otf') format('opentype');
-}
-@font-face {
- font-family: gillsans;
- src: url('../fonts/Gill Sans Medium.otf') format('opentype');
-}
-@font-face {
- font-family: gillsansbold;
- src: url('../fonts/Gill Sans Condensed Bold.otf') format('opentype');
-}
-@font-face {
- font-family: gillsansitalic;
- src: url('../fonts/Gill Sans Medium Italic') format('opentype');
-}
-@font-face {
- font-family: gillsansbolditalic;
- src: url('../fonts/Gill Sans Bold Italic.otf') format('opentype');
-}
-@font-face {
- font-family: specialelite;
- src: url('../fonts/SpecialElite-Regular.ttf') format('truetype');
-}
-@font-face {
- font-family: neosans;
- src: url('../fonts/NeoSansProRegular.OTF') format('opentype');
-}
-@font-face {
- font-family: neosansitalic;
- src: url('../fonts/NeoSansProItalic.OTF') format('opentype');
-}
-@font-face {
- font-family: ocra;
- src: url('../fonts/OCR A Std Regular.ttf') format('truetype');
-}
-/*Variables*/
-:root {
- --site-background: url('../img/lowpolyBackground.svg');
- --color-primary: #35603E;
- --color-selected: #ae9;
- --color-highlight: #8f8;
- --font-color: #fff;
- --font-color-2: #bbb;
- --input-background: #333;
- --input-background-selected: #555;
- --darkened-backdrop-filter: grayscale(1) brightness(0.3);
- --regular-backdrop-filter: none;
- --window-diagonal-size: 400px;
-}
-/*Main Site Elements*/
-.background {
- position: fixed;
- z-index: -1;
- width: 100vw;
- height: 100vh;
- background: var(--site-background);
- background-repeat: no-repeat;
- background-attachment: fixed;
- background-size: cover;
- background-position: center;
- filter: var(--regular-backdrop-filter);
-}
-html {
- font-size: 12pt;
- overflow-x: hidden;
- background: #151515;
- color: var(--font-color);
-}
-body {
- width: 100vw;
- overflow-x: hidden;
-}
-header, footer, .main-content {
- overflow-x: hidden;
-}
-header, footer {
- backdrop-filter: var(--darkened-backdrop-filter);
- -webkit-backdrop-filter: var(--darkened-backdrop-filter);
-}
-header {
- padding: 2rem 0;
-}
-.header-extension {
- padding-bottom: 2rem;
-}
-footer {
- padding: 2rem;
- display: grid;
- grid-template-columns: calc(1fr - 4rem);
- grid-gap: 1rem;
-}
-@media only screen and (min-width: 750px) {
- footer {
- grid-template-columns: repeat(3, 1fr);
- }
-}
-footer > div > * {
- margin: 1rem 0;
-}
-/*Viewport*/
-img {
- max-width: 100%;
-}
-/*Scrollbar Mod*/
-::-webkit-scrollbar {
- width: 0.5rem;
- height: 0;
- background: #222;
-}
-::-webkit-scrollbar-thumb {
- background: #888;
- border-radius: 0.25rem;
-}
-/*Fonts*/
-.title {
- font-family: belerenbsc;
-}
-h1.title {
- font-size: 4rem;
-}
-.shadow {
- text-shadow: 0.2rem 0.2rem 0.5rem black;
-}
-h1 {
- font-size: 3rem;
- font-family: Montserrat-SemiBold, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-h2 {
- font-size: 2.5rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-h3 {
- font-size: 2rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-h4 {
- font-size: 1.5rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-h5 {
- font-size: 1.25rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-p {
- font-size: 1rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- overflow-wrap: break-word;
-}
-a {
- color: inherit;
- text-decoration: inherit;
- overflow-wrap: break-word;
-}
-a:hover {
- text-decoration: underline;
-}
-a.underline {
- text-decoration: underline;
-}
-::selection {
- color: var(--font-color);
- background: var(--color-highlight);
-}
-::moz-selection {
- color: var(--font-color);
- background: var(--color-highlight);;
-}
-/*General styles*/
-.hidden {
- display: none;
-}
-.fake-hidden {
- opacity: 0;
- position: absolute;
- top: -100%;
- left: -100%;
-}
-.margin-bottom {
- margin-bottom: 0.5rem;
-}
-.margin-bottom-large {
- margin-bottom: 2rem;
-}
-.margin-bottom-larger {
- margin-bottom: 3rem;
-}
-.margin-top {
- margin-top: 0.5rem;
-}
-.padding {
- padding: 0.5rem;
-}
-.readable-background {
- backdrop-filter: var(--darkened-backdrop-filter);
- -webkit-backdrop-filter: var(--darkened-backdrop-filter);
-}
-.box-shadow {
- box-shadow: 0 2px 8px #0008;
-}
-.split-grid {
- display: grid;
- grid-template-columns: 1fr 1fr;
- grid-gap: 0.5rem;
-}
-.center {
- text-align: center;
-}
-.layer {
- padding: 0.5rem;
-}
-.vertical-center {
- margin: auto;
-}
-@media only screen and (min-width: 750px) {
- .layer {
- padding: 4rem;
- }
-}
-/*Hamburger*/
-.hamburger {
- position: fixed;
- right: 0rem;
- top: 0rem;
- width: 4rem;
- height: 4rem;
- fill-rule: evenodd;
- clip-rule: evenodd;
- stroke-linejoin: round;
- stroke-miterlimit: 1.5;
- cursor: pointer;
- z-index: 100;
- background: var(--color-primary);
- border-radius: 0 0 0 0.5rem;
-}
-.hamburger > path {
- fill: none;
- stroke: white;
- stroke-width: 8px;
- transition: 0.5s;
-}
-.line1, .line3 {
- stroke-dasharray: 80 183;
- stroke-dashoffset: 0;
-}
-.line2 {
- stroke-dasharray: 80 80;
- stroke-dashoffset: 0;
-}
-.opened > .line1, .opened > .line3 {
- stroke-dasharray: 103 183;
- stroke-dashoffset: -80;
-}
-.opened > .line2 {
- stroke-dasharray: 0 60;
- stroke-dashoffset: -40;
-}
-.circle {
- z-index: 5;
- position: fixed;
- right: 0;
- top: 0;
- padding: 0;
- background: var(--color-primary);
- border-radius: 100%;
- transition: 0.333s ease;
-}
-.hamburger:hover + .circle {
- /*padding: 3rem;
- right: -1rem;
- top: -1rem;*/
-}
-.hamburger.opened + .circle {
- padding: var(--window-diagonal-size);
- right: calc(0px - var(--window-diagonal-size));
- top: calc(0px - var(--window-diagonal-size));
- transition: 0.75s cubic-bezier(.53,.47,.76,-0.52);
-}
-/*Menus*/
-.menu {
- position: fixed;
- z-index: 10;
- bottom: 200vh;
- left: 0;
- width: 100vw;
- height: 100vh;
- overflow-y: scroll;
- transition: 0.5s;
- text-align: center;
-}
-.menu.menu-visible {
- bottom: 0;
- transition-delay: 0.667s;
-}
-.menu > div {
- display: inline-block;
- margin: 0 auto;
- text-align: left;
-}
-/*Main (Nav) Menu*/
-.main-menu {
- padding: 2rem;
- line-height: 3rem;
-}
-.main-menu > h2 {
- margin-top: 4rem;
-}
-/*notifications*/
-.notification-container {
- position: fixed;
- z-index: 10;
- bottom: 0;
- left: 1.5rem;
- width: calc(100vw - 3rem);
- max-height: 75vh;
- overflow-y: scroll;
- transition: 0.5s;
-}
-.notification {
- border-top: 0.25rem solid var(--color-selected);
- background: var(--input-background);
- display: grid;
- grid-template-columns: auto 2rem;
- transition: 0.5s;
-}
-.notification > h3 {
- text-align: center;
- user-select: none;
- cursor: pointer;
-}
-.notification.hidden {
- opacity: 0;
-}
-/*Inputs*/
-.input {
- box-sizing: border-box;
- width: 100%;
- background: var(--input-background);
- color: inherit;
- font-size: 1.25rem;
- font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
- font-weight: 100;
- border-width: 0.25rem 0 0 0;
- border-style: solid;
- border-color: #0000;
- padding: 0 0.25rem 0.25rem 0.25rem;
- transition: 0.5s;
-}
-.input:hover {
- box-shadow: 0 0px 16px black;
- transition: 0.05s;
-}
-.input:focus {
- outline: none;
-}
-.input:active {
- border-color: var(--color-selected);
-}
-.input:disabled {
- opacity: 0.5;
-}
-.input:disabled:hover {
- box-shadow: none;
-}
-.input-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
- grid-gap: 0.5rem;
-}
-.input-description {
- color: var(--font-color-2);
- font-style: italic;
-}
-input[type=checkbox].input {
- /*nothing for now*/
-}
-.input:not([type=text]):not([type=number]):not([type=url]) {
- cursor: pointer;
-}
-textarea.input {
- cursor: text !important;
- resize: vertical;
- box-sizing: border-box;
- min-height: 10rem;
- max-height: 20rem;
- transition: height 0s;
-}
-/*Checkboxes*/
-.checkbox-container {
- display: block;
- position: relative;
- padding-left: 2.25rem;
- cursor: pointer;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.checkbox-container input {
- position: absolute;
- opacity: 0;
- cursor: pointer;
- height: 0;
- width: 0;
-}
-.checkmark {
- position: absolute;
- top: 0;
- left: 0.25rem;
- height: 1.5rem;
- width: 1.5rem;
- border-radius: 0.25rem;
- background-color: #efefef;
-}
-.checkbox-container input:checked ~ .checkmark {
- background-color: var(--color-selected);
-}
-.checkmark:after {
- content: "";
- position: absolute;
- display: none;
-}
-.checkbox-container input:checked ~ .checkmark:after {
- display: block;
-}
-.checkbox-container .checkmark:after {
- left: 0.5rem;
- top: 0.25rem;
- width: 0.25rem;
- height: 0.75rem;
- border: solid var(--color-primary);
- border-width: 0 0.25rem 0.25rem 0;
- -webkit-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- transform: rotate(45deg);
-}
-/*Collapsible*/
-.collapsible {
- cursor: pointer;
- user-select: none;
-}
-.collapsible:after {
- content: '';
- border: solid white;
- border-width: 0 0.15em 0.15em 0;
- display: inline-block;
- padding: 0.15em;
- transform: rotate(-135deg) translate(-0.2em, 0.2em);
- -webkit-transform: rotate(-135deg) translate(-0.2em, 0.2em);
-}
-.collapsible.collapsed:after {
- transform: rotate(45deg) translate(0, -0.3em);
- -webkit-transform: rotate(45deg) translate(0, -0.3em);
-}
-.collapsed + div {
- display: none;
-}
-/*Videos*/
-.video {
- position: relative;
- padding-bottom: 56.25%;
- padding-top: 30px;
- height: 0;
- overflow: hidden;
-}
-.video iframe, .video object, .video embed, .video video {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-/*drop to upload*/
-.drop-area {
- border: 0.125rem dashed gray;
- transition: 0.25s;
-}
-.drop-area.hover {
- border-color: var(--color-selected);
-}
-
-
-/*Animated cards*/
-.animated-scene {
- perspective: 100rem;
-}
-.animated-card-1 {
- animation: animatedcardone 3s ease-in-out 0s alternate infinite;
- -moz-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
- -webkit-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
- -o-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
- transform-style: preserve-3d;
-}
-.animation-delay-2 {
- animation-delay: 1s !important;
-}
-.animation-delay-4 {
- animation-delay: 2s !important;
-}
-@keyframes animatedcardone {
- 0% {transform: rotateY(15deg);}
- 100% {transform: rotateY(-15deg);}
-}
-
-
-
-
-/*Home Page only*/
-.sample-grid {
- display: grid;
- grid-gap: 1rem;
- grid-template-columns: 1fr;
-}
-.sample-grid > img {
- display: block;
- max-width: 375px;
- width: 100%;
- height: auto;
- margin: 1rem auto;
-}
-@media only screen and (min-width: 750px) {
- .sample-grid {
- grid-template-columns: 375px auto;
- }
- .sample-grid.right {
- grid-template-columns: auto 375px;
- }
-}
-
-
-
-
-/*Tutorial Page only*/
-.tutorial-grid {
- display: grid;
- grid-gap: 1rem;
- grid-template-columns: 1fr;
-}
-.tutorial-grid > img {
- display: block;
- width: 100%;
- height: auto;
- margin: 1rem auto;
-}
-.readable-background > .tutorial-grid > img {
- border: 0.1rem solid gray;
-}
-@media only screen and (min-width: 750px) {
- .tutorial-grid {
- grid-template-columns: 1fr 1fr;
- }
-}
-
-
-
-/*Creator related only*/
-/*Creator Grid/Canvas/Menu*/
-.creator-grid {
- width: 100%;
- display: grid;
- grid-template-columns: 1fr;
- justify-items: center;
- grid-gap: 1rem;
- padding: 1rem 0;
-}
-.creator-canvas {
- max-width: 750px;
- width: 100vw;
- height: auto;
- /*backdrop-filter: hue-rotate(80deg);*/
-}
-.creator-menu {
- width: 100%;
-}
-@media only screen and (min-width: 1250px) {
- .creator-grid {
- grid-template-columns: 750px auto;
- padding: 1rem;
- justify-items: left;
- }
- .creator-menu {
- width: calc(100% - 2rem);
- }
- .creator-canvas {
- border-radius: 37.5px;
- }
-}
-/*Creator Menu Tabs*/
-.creator-menu-tabs {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
- grid-gap: 0.5rem;
- margin-bottom: 0.5rem;
-}
-/*Selectables*/
-.selectable {
- text-align: center;
- user-select: none;
- padding: 1rem;
- padding-top: 0.9rem;
- border-top: 0.1rem;
- border-style: solid;
- border-color: #0000;
- transition: 0.5s;
- cursor: pointer;
-}
-.selectable.selected {
- padding-top: 0.5rem;
- border-top: 0.5rem;
- border-style: solid;
- border-color: var(--color-selected);
- transition: 0.5s !important;
-}
-.selectable:hover {
- box-shadow: 0 0px 16px black;
- transition: 0.05s;
-}
-/*Draggables*/
-.draggable {
- background: var(--input-background);
- touch-action: none;
-}
-.dragging {
- box-shadow: 0 0px 16px black;
- background: var(--input-background-selected);
- cursor: move;
-}
-.frame-list{
- display: grid;
- grid-template-columns: 1fr;
- grid-gap: 0.25rem;
- user-select: none;
-}
-/* Frame Search */
-.autocomplete {
- position: relative;
-}
-.autocomplete-items {
- position: absolute;
- border: 1px solid black;
- border-bottom: none;
- top: 100%;
- left: 0;
- right: 0;
- z-index: 99;
- max-height: 8rem;
- height: auto;
- overflow-y: scroll;
-}
-.autocomplete-items div {
- border-bottom: 1px solid black !important;
- z-index: 99;
-}
-.autocomplete-items div:hover {
- background-color: var(--input-background-selected);
-}
-.autocomplete-active {
- background-color: var(--color-highlight) !important;
- color: black;
-}
-/*Frame/Mask-Pickers*/
-.frame-picker, .mask-picker {
- display: grid;
- grid-gap: 0.5rem;
- height: 20rem;
- overflow-y: scroll;
- overflow-x: hidden;
- grid-auto-rows: 6.5rem;
-}
-.frame-picker {
- grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
- justify-items: left;
- align-items: left;
-}
-.mask-picker {
- grid-template-columns: 1fr;
-}
-.frame-option, .mask-option {
- cursor: pointer;
- background: var(--input-background);
- width: 100%;
- height: 6rem;
- padding: 0.25rem 0;
- text-align: center;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -o-user-select: none;
- user-select: none;
- transition: 0.25s;
-}
-.frame-option.selected, .mask-option.selected {
- background: var(--input-background-selected);
-}
-.frame-option > img, .mask-option > img {
- width: 100%;
- height: 100%;
- object-fit: contain;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -o-user-select: none;
- user-select: none;
-}
-.mask-option {
- display: grid;
- grid-template-columns: 6rem auto;
- text-align: left;
- grid-gap: 0.5rem;
- align-items: center;
- height: 6rem;
-}
-.mask-option > img {
- max-height: 6rem;
-}
-/*Frame Elements*/
-.frame-element {
- display: grid;
- grid-template-columns: 4rem 4rem 1fr 4rem;
- grid-gap: 0.5rem;
- padding: 0.25rem;
- align-items: center;
- cursor: grab;
-}
-.frame-element > h4 {
- overflow-x: scroll;
-}
-.frame-element > img {
- width: 4rem;
- height: 4rem;
- object-fit: contain;
- padding: none;
-}
-.frame-element:hover {
- box-shadow: 0 0px 16px black;
- transition: 0.05s;
-}
-.frame-element-close {
- font-size: 2rem;
- cursor: pointer;
- text-align: center;
- padding: 0.5rem 0;
-}
-.frame-element-editor, .textbox-editor {
- display: none;
- position: fixed;
- max-width: calc(100vw - 6rem);
- width: 64rem; /*multiple of 16?*/
- max-height: calc(100vh - 6rem);
- height: auto;
- overflow-y: scroll;
- -webkit-transform: translateX(-50%) translateY(-50%);
- -moz-transform: translateX(-50%) translateY(-50%);
- -ms-transform: translateX(-50%) translateY(-50%);
- -o-transform: translateX(-50%) translateY(-50%);
- transform: translateX(-50%) translateY(-50%);
- top: 50%;
- left: 50%;
- background: var(--color-primary);
- border: 0.5rem solid #333;
- border-radius: 1rem;
- box-shadow: 0.5rem 0.5rem 1rem 0.5rem black;
- z-index: 10;
- padding: 2rem;
- grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
- grid-gap: 1rem;
-}
-.frame-element-editor.opened, .textbox-editor.opened {
- display: grid;
-}
-.frame-element-editor > .frame-element-editor-title, .textbox-editor > .textbox-editor-title {
- grid-column: 1 / -2;
-}
-.frame-element-editor > .frame-element-editor-close, .textbox-editor > .textbox-editor-close {
- cursor: pointer;
- width: auto;
- height: auto;
- grid-column: -1 span 1;
- user-select: none;
- justify-self: right;
-}
-/*Text tab*/
-.text-option {
- background: var(--input-background);
-}
-.text-codes {
- max-width: calc(100vw - 3rem);
- display: grid;
- grid-template-columns: auto auto;
- overflow-x: scroll;
-}
-.text-codes > * {
- border: 1px solid black;
- padding: 0.5rem;
-}
-/*download button*/
-.download {
- text-align: center;
- user-select: none;
- cursor: pointer;
-}
-.download:hover {
- text-decoration: underline;
-}
-/*supporters*/
-.supporters {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
- grid-gap: 0.5rem;
- padding: 1rem 2rem;
-}
+/*fonts*/
+@font-face {
+ font-family: gothammedium;
+ src: url("../fonts/gotham-medium.ttf") format('truetype');
+}
+@font-face {
+ font-family: belerenb;
+ src: url("../fonts/beleren-b.ttf") format('truetype');
+}
+@font-face {
+ font-family: belerenbsc;
+ src: url("../fonts/beleren-bsc.ttf") format('truetype');
+}
+@font-face {
+ font-family: matrix;
+ src: url("../fonts/matrix.ttf") format('truetype');
+}
+@font-face {
+ font-family: matrixb;
+ src: url("../fonts/matrix-b.ttf") format('truetype');
+}
+@font-face {
+ font-family: matrixbsc;
+ src: url("../fonts/Matrix Bold Small Caps.ttf") format('truetype');
+}
+@font-face {
+ font-family: mplantin;
+ src: url("../fonts/mplantin.ttf") format('truetype');
+}
+@font-face {
+ font-family: mplantini;
+ src: url("../fonts/mplantin-i.ttf") format('truetype');
+}
+@font-face {
+ font-family: plantinsemibold;
+ src: url("../fonts/plantin-semibold.otf") format('opentype');
+}
+@font-face {
+ font-family: plantinsemibolditalic;
+ src: url("../fonts/Plantin-SemiboldItalic.otf") format('opentype');
+}
+@font-face {
+ font-family: goudymedieval;
+ src: url("../fonts/goudy-medieval.ttf") format('truetype');
+}
+@font-face {
+ font-family: phyrexianold;
+ src: url("../fonts/phyrexian.ttf") format('truetype');
+}
+@font-face {
+ font-family: phyrexian;
+ src: url("../fonts/phy.woff2") format("woff2");
+}
+@font-face {
+ font-family: Montserrat-SemiBold;
+ src: url("../fonts/Montserrat-SemiBold.ttf") format('truetype');
+}
+@font-face {
+ font-family: Montserrat-Medium;
+ src: url("../fonts/Montserrat-Medium.ttf") format('truetype');
+}
+@font-face {
+ font-family: Acme-Regular;
+ src: url("../fonts/Acme-Regular.ttf") format('truetype');
+}
+@font-face {
+ font-family: fritz-quadrata;
+ src: url("../fonts/fritz-quadrata.ttf") format('truetype');
+}
+@font-face {
+ font-family: japanese-title;
+ src: url("../fonts/NudMotoyaExAporo_W6.ttf") format('truetype');
+}
+@font-face {
+ font-family: japanese;
+ src: url('../fonts/2012c863631ba71f874aba70590795a1.otf') format('opentype');
+}
+@font-face {
+ font-family: invocation;
+ src: url('../fonts/Invocation.ttf') format('truetype');
+}
+@font-face {
+ font-family: invocation-text;
+ src: url('../fonts/shango-gothic-bold.ttf') format('truetype');
+}
+@font-face {
+ font-family: souvenir;
+ src: url('../fonts/Souvenir-Itc-T-OT-Bold.otf') format('opentype');
+}
+@font-face {
+ font-family: palatino;
+ src: url('../fonts/Palatino Font.ttf') format('truetype');
+}
+@font-face {
+ font-family: amanda;
+ src: url('../fonts/Amanda Std Regular.otf') format('opentype');
+}
+@font-face {
+ font-family: gillsans;
+ src: url('../fonts/Gill Sans Medium.otf') format('opentype');
+}
+@font-face {
+ font-family: gillsansbold;
+ src: url('../fonts/Gill Sans Condensed Bold.otf') format('opentype');
+}
+@font-face {
+ font-family: gillsansitalic;
+ src: url('../fonts/Gill Sans Medium Italic') format('opentype');
+}
+@font-face {
+ font-family: gillsansbolditalic;
+ src: url('../fonts/Gill Sans Bold Italic.otf') format('opentype');
+}
+@font-face {
+ font-family: specialelite;
+ src: url('../fonts/SpecialElite-Regular.ttf') format('truetype');
+}
+@font-face {
+ font-family: neosans;
+ src: url('../fonts/NeoSansProRegular.OTF') format('opentype');
+}
+@font-face {
+ font-family: neosansitalic;
+ src: url('../fonts/NeoSansProItalic.OTF') format('opentype');
+}
+@font-face {
+ font-family: ocra;
+ src: url('../fonts/OCR A Std Regular.ttf') format('truetype');
+}
+@font-face {
+ font-family: decour;
+ src: url('../fonts/decour-cnd-regular.ttf') format('truetype');
+}
+@font-face {
+ font-family: decouritalic;
+ src: url('../fonts/decour-cnd-regular-italic.ttf') format('truetype');
+}
+@font-face {
+ font-family: officina;
+ src: url('../fonts/officina-ser-itc-black.otf') format('opentype');
+}
+@font-face {
+ font-family: davisonamericana;
+ src: url('../fonts/Davison Americana CG Regular.otf') format('opentype');
+}
+@font-face {
+ font-family: saloongirl;
+ src: url('../fonts/saloon-girl.ttf') format('truetype');
+}
+@font-face {
+ font-family: arialblack;
+ src: url('../fonts/arial_black.ttf') format('truetype');
+}
+/*Variables*/
+:root {
+ --site-background: url('../img/lowpolyBackground.svg');
+ --color-primary: #35603E;
+ --color-selected: #ae9;
+ --color-highlight: #8f8;
+ --font-color: #fff;
+ --font-color-2: #bbb;
+ --input-background: #333;
+ --input-background-selected: #555;
+ --darkened-backdrop-filter: grayscale(1) brightness(0.3);
+ --regular-backdrop-filter: none;
+ --window-diagonal-size: 400px;
+}
+/*Main Site Elements*/
+.background {
+ position: fixed;
+ z-index: -1;
+ width: 100vw;
+ height: 100vh;
+ background: var(--site-background);
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: center;
+ filter: var(--regular-backdrop-filter);
+}
+html {
+ font-size: 12pt;
+ overflow-x: hidden;
+ background: #151515;
+ color: var(--font-color);
+}
+body {
+ width: 100vw;
+ overflow-x: hidden;
+}
+header, footer, .main-content {
+ overflow-x: hidden;
+}
+header, footer {
+ backdrop-filter: var(--darkened-backdrop-filter);
+ -webkit-backdrop-filter: var(--darkened-backdrop-filter);
+}
+header {
+ padding: 2rem 0;
+}
+.header-extension {
+ padding-bottom: 2rem;
+}
+footer {
+ padding: 2rem;
+ display: grid;
+ grid-template-columns: calc(1fr - 4rem);
+ grid-gap: 1rem;
+}
+@media only screen and (min-width: 750px) {
+ footer {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+footer > div > * {
+ margin: 1rem 0;
+}
+/*Viewport*/
+img {
+ max-width: 100%;
+}
+/*Scrollbar Mod*/
+::-webkit-scrollbar {
+ width: 0.5rem;
+ height: 0;
+ background: #222;
+}
+::-webkit-scrollbar-thumb {
+ background: #888;
+ border-radius: 0.25rem;
+}
+/*Fonts*/
+.title {
+ font-family: belerenbsc;
+}
+h1.title {
+ font-size: 4rem;
+}
+.shadow {
+ text-shadow: 0.2rem 0.2rem 0.5rem black;
+}
+h1 {
+ font-size: 3rem;
+ font-family: Montserrat-SemiBold, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+h2 {
+ font-size: 2.5rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+h3 {
+ font-size: 2rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+h4 {
+ font-size: 1.5rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+h5 {
+ font-size: 1.25rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+p {
+ font-size: 1rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ overflow-wrap: break-word;
+}
+a {
+ color: inherit;
+ text-decoration: inherit;
+ overflow-wrap: break-word;
+}
+a:hover {
+ text-decoration: underline;
+}
+a.underline {
+ text-decoration: underline;
+}
+::selection {
+ color: var(--font-color);
+ background: var(--color-highlight);
+}
+::moz-selection {
+ color: var(--font-color);
+ background: var(--color-highlight);;
+}
+/*General styles*/
+.hidden {
+ display: none;
+}
+.fake-hidden {
+ opacity: 0;
+ position: absolute;
+ top: -100%;
+ left: -100%;
+}
+.margin-bottom {
+ margin-bottom: 0.5rem;
+}
+.margin-bottom-large {
+ margin-bottom: 2rem;
+}
+.margin-bottom-larger {
+ margin-bottom: 3rem;
+}
+.margin-top {
+ margin-top: 0.5rem;
+}
+.padding {
+ padding: 0.5rem;
+}
+.readable-background {
+ backdrop-filter: var(--darkened-backdrop-filter);
+ -webkit-backdrop-filter: var(--darkened-backdrop-filter);
+}
+.box-shadow {
+ box-shadow: 0 2px 8px #0008;
+}
+.split-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 0.5rem;
+}
+.center {
+ text-align: center;
+}
+.layer {
+ padding: 0.5rem;
+}
+.vertical-center {
+ margin: auto;
+}
+@media only screen and (min-width: 750px) {
+ .layer {
+ padding: 4rem;
+ }
+}
+/*Hamburger*/
+.hamburger {
+ position: fixed;
+ right: 0rem;
+ top: 0rem;
+ width: 4rem;
+ height: 4rem;
+ fill-rule: evenodd;
+ clip-rule: evenodd;
+ stroke-linejoin: round;
+ stroke-miterlimit: 1.5;
+ cursor: pointer;
+ z-index: 100;
+ background: var(--color-primary);
+ border-radius: 0 0 0 0.5rem;
+}
+.hamburger > path {
+ fill: none;
+ stroke: white;
+ stroke-width: 8px;
+ transition: 0.5s;
+}
+.line1, .line3 {
+ stroke-dasharray: 80 183;
+ stroke-dashoffset: 0;
+}
+.line2 {
+ stroke-dasharray: 80 80;
+ stroke-dashoffset: 0;
+}
+.opened > .line1, .opened > .line3 {
+ stroke-dasharray: 103 183;
+ stroke-dashoffset: -80;
+}
+.opened > .line2 {
+ stroke-dasharray: 0 60;
+ stroke-dashoffset: -40;
+}
+.circle {
+ z-index: 5;
+ position: fixed;
+ right: 0;
+ top: 0;
+ padding: 0;
+ background: var(--color-primary);
+ border-radius: 100%;
+ transition: 0.333s ease;
+}
+.hamburger:hover + .circle {
+ /*padding: 3rem;
+ right: -1rem;
+ top: -1rem;*/
+}
+.hamburger.opened + .circle {
+ padding: var(--window-diagonal-size);
+ right: calc(0px - var(--window-diagonal-size));
+ top: calc(0px - var(--window-diagonal-size));
+ transition: 0.75s cubic-bezier(.53,.47,.76,-0.52);
+}
+/*Menus*/
+.menu {
+ position: fixed;
+ z-index: 10;
+ bottom: 200vh;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ overflow-y: scroll;
+ transition: 0.5s;
+ text-align: center;
+}
+.menu.menu-visible {
+ bottom: 0;
+ transition-delay: 0.667s;
+}
+.menu > div {
+ display: inline-block;
+ margin: 0 auto;
+ text-align: left;
+}
+/*Main (Nav) Menu*/
+.main-menu {
+ padding: 2rem;
+ line-height: 3rem;
+}
+.main-menu > h2 {
+ margin-top: 4rem;
+}
+/*notifications*/
+.notification-container {
+ position: fixed;
+ z-index: 10;
+ bottom: 0;
+ left: 1.5rem;
+ width: calc(100vw - 3rem);
+ max-height: 75vh;
+ overflow-y: scroll;
+ transition: 0.5s;
+}
+.notification {
+ border-top: 0.25rem solid var(--color-selected);
+ background: var(--input-background);
+ display: grid;
+ grid-template-columns: auto 2rem;
+ transition: 0.5s;
+}
+.notification > h3 {
+ text-align: center;
+ user-select: none;
+ cursor: pointer;
+}
+.notification.hidden {
+ opacity: 0;
+}
+/*Inputs*/
+.input {
+ box-sizing: border-box;
+ width: 100%;
+ background: var(--input-background);
+ color: inherit;
+ font-size: 1.25rem;
+ font-family: Montserrat-Medium, Helvetica, Tahoma, Verdana, Geneva, sans-serif;
+ font-weight: 100;
+ border-width: 0.25rem 0 0 0;
+ border-style: solid;
+ border-color: #0000;
+ padding: 0 0.25rem 0.25rem 0.25rem;
+ transition: 0.5s;
+}
+.input:hover {
+ box-shadow: 0 0px 16px black;
+ transition: 0.05s;
+}
+.input:focus {
+ outline: none;
+}
+.input:active {
+ border-color: var(--color-selected);
+}
+.input:disabled {
+ opacity: 0.5;
+}
+.input:disabled:hover {
+ box-shadow: none;
+}
+.input-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
+ grid-gap: 0.5rem;
+}
+.input-description {
+ color: var(--font-color-2);
+ font-style: italic;
+}
+input[type=checkbox].input {
+ /*nothing for now*/
+}
+.input:not([type=text]):not([type=number]):not([type=url]) {
+ cursor: pointer;
+}
+textarea.input {
+ cursor: text !important;
+ resize: vertical;
+ box-sizing: border-box;
+ min-height: 10rem;
+ max-height: 20rem;
+ transition: height 0s;
+}
+/*Checkboxes*/
+.checkbox-container {
+ display: block;
+ position: relative;
+ padding-left: 2.25rem;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.checkbox-container input {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 0;
+ width: 0;
+}
+.checkmark {
+ position: absolute;
+ top: 0;
+ left: 0.25rem;
+ height: 1.5rem;
+ width: 1.5rem;
+ border-radius: 0.25rem;
+ background-color: #efefef;
+}
+.checkbox-container input:checked ~ .checkmark {
+ background-color: var(--color-selected);
+}
+.checkmark:after {
+ content: "";
+ position: absolute;
+ display: none;
+}
+.checkbox-container input:checked ~ .checkmark:after {
+ display: block;
+}
+.checkbox-container .checkmark:after {
+ left: 0.5rem;
+ top: 0.25rem;
+ width: 0.25rem;
+ height: 0.75rem;
+ border: solid var(--color-primary);
+ border-width: 0 0.25rem 0.25rem 0;
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+/*Collapsible*/
+.collapsible {
+ cursor: pointer;
+ user-select: none;
+}
+.collapsible:after {
+ content: '';
+ border: solid white;
+ border-width: 0 0.15em 0.15em 0;
+ display: inline-block;
+ padding: 0.15em;
+ transform: rotate(-135deg) translate(-0.2em, 0.2em);
+ -webkit-transform: rotate(-135deg) translate(-0.2em, 0.2em);
+}
+.collapsible.collapsed:after {
+ transform: rotate(45deg) translate(0, -0.3em);
+ -webkit-transform: rotate(45deg) translate(0, -0.3em);
+}
+.collapsed + div {
+ display: none;
+}
+/*Videos*/
+.video {
+ position: relative;
+ padding-bottom: 56.25%;
+ padding-top: 30px;
+ height: 0;
+ overflow: hidden;
+}
+.video iframe, .video object, .video embed, .video video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+/*drop to upload*/
+.drop-area {
+ border: 0.125rem dashed gray;
+ transition: 0.25s;
+}
+.drop-area.hover {
+ border-color: var(--color-selected);
+}
+
+
+/*Animated cards*/
+.animated-scene {
+ perspective: 100rem;
+}
+.animated-card-1 {
+ animation: animatedcardone 3s ease-in-out 0s alternate infinite;
+ -moz-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
+ -webkit-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
+ -o-animation: animatedcardone 3s ease-in-out 0s alternate infinite;
+ transform-style: preserve-3d;
+}
+.animation-delay-2 {
+ animation-delay: 1s !important;
+}
+.animation-delay-4 {
+ animation-delay: 2s !important;
+}
+@keyframes animatedcardone {
+ 0% {transform: rotateY(15deg);}
+ 100% {transform: rotateY(-15deg);}
+}
+
+
+
+
+/*Home Page only*/
+.sample-grid {
+ display: grid;
+ grid-gap: 1rem;
+ grid-template-columns: 1fr;
+}
+.sample-grid > img {
+ display: block;
+ max-width: 375px;
+ width: 100%;
+ height: auto;
+ margin: 1rem auto;
+}
+@media only screen and (min-width: 750px) {
+ .sample-grid {
+ grid-template-columns: 375px auto;
+ }
+ .sample-grid.right {
+ grid-template-columns: auto 375px;
+ }
+}
+
+
+
+
+/*Tutorial Page only*/
+.tutorial-grid {
+ display: grid;
+ grid-gap: 1rem;
+ grid-template-columns: 1fr;
+}
+.tutorial-grid > img {
+ display: block;
+ width: 100%;
+ height: auto;
+ margin: 1rem auto;
+}
+.readable-background > .tutorial-grid > img {
+ border: 0.1rem solid gray;
+}
+@media only screen and (min-width: 750px) {
+ .tutorial-grid {
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+
+
+/*Creator related only*/
+/*Creator Grid/Canvas/Menu*/
+.creator-grid {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 1fr;
+ justify-items: center;
+ grid-gap: 1rem;
+ padding: 1rem 0;
+}
+.creator-canvas {
+ max-width: 750px;
+ width: 100vw;
+ height: auto;
+ /*backdrop-filter: hue-rotate(80deg);*/
+}
+.creator-menu {
+ width: 100%;
+}
+@media only screen and (min-width: 1250px) {
+ .creator-grid {
+ grid-template-columns: 750px auto;
+ padding: 1rem;
+ justify-items: left;
+ }
+ .creator-menu {
+ width: calc(100% - 2rem);
+ }
+ .creator-canvas {
+ border-radius: 37.5px;
+ }
+}
+/*Creator Menu Tabs*/
+.creator-menu-tabs {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
+ grid-gap: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+/*Selectables*/
+.selectable {
+ text-align: center;
+ user-select: none;
+ padding: 1rem;
+ padding-top: 0.9rem;
+ border-top: 0.1rem;
+ border-style: solid;
+ border-color: #0000;
+ transition: 0.5s;
+ cursor: pointer;
+}
+.selectable.selected {
+ padding-top: 0.5rem;
+ border-top: 0.5rem;
+ border-style: solid;
+ border-color: var(--color-selected);
+ transition: 0.5s !important;
+}
+.selectable:hover {
+ box-shadow: 0 0px 16px black;
+ transition: 0.05s;
+}
+/*Draggables*/
+.draggable {
+ background: var(--input-background);
+ touch-action: none;
+}
+.dragging {
+ box-shadow: 0 0px 16px black;
+ background: var(--input-background-selected);
+ cursor: move;
+}
+.frame-list{
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-gap: 0.25rem;
+ user-select: none;
+}
+/* Frame Search */
+.autocomplete {
+ position: relative;
+}
+.autocomplete-items {
+ position: absolute;
+ border: 1px solid black;
+ border-bottom: none;
+ top: 100%;
+ left: 0;
+ right: 0;
+ z-index: 99;
+ max-height: 8rem;
+ height: auto;
+ overflow-y: scroll;
+}
+.autocomplete-items div {
+ border-bottom: 1px solid black !important;
+ z-index: 99;
+}
+.autocomplete-items div:hover {
+ background-color: var(--input-background-selected);
+}
+.autocomplete-active {
+ background-color: var(--color-highlight) !important;
+ color: black;
+}
+/*Frame/Mask-Pickers*/
+.frame-picker, .mask-picker {
+ display: grid;
+ grid-gap: 0.5rem;
+ height: 20rem;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ grid-auto-rows: 6.5rem;
+}
+.frame-picker {
+ grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
+ justify-items: left;
+ align-items: left;
+}
+.mask-picker {
+ grid-template-columns: 1fr;
+}
+.frame-option, .mask-option {
+ cursor: pointer;
+ background: var(--input-background);
+ width: 100%;
+ height: 6rem;
+ padding: 0.25rem 0;
+ text-align: center;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ transition: 0.25s;
+}
+.frame-option.selected, .mask-option.selected {
+ background: var(--input-background-selected);
+}
+.frame-option > img, .mask-option > img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+.mask-option {
+ display: grid;
+ grid-template-columns: 6rem auto;
+ text-align: left;
+ grid-gap: 0.5rem;
+ align-items: center;
+ height: 6rem;
+}
+.mask-option > img {
+ max-height: 6rem;
+}
+/*Frame Elements*/
+.frame-element {
+ display: grid;
+ grid-template-columns: 4rem 4rem 1fr 4rem;
+ grid-gap: 0.5rem;
+ padding: 0.25rem;
+ align-items: center;
+ cursor: grab;
+}
+.frame-element > h4 {
+ overflow-x: scroll;
+}
+.frame-element > img {
+ width: 4rem;
+ height: 4rem;
+ object-fit: contain;
+ padding: none;
+}
+.frame-element:hover {
+ box-shadow: 0 0px 16px black;
+ transition: 0.05s;
+}
+.frame-element-close {
+ font-size: 2rem;
+ cursor: pointer;
+ text-align: center;
+ padding: 0.5rem 0;
+}
+.frame-element-editor, .textbox-editor {
+ display: none;
+ position: fixed;
+ max-width: calc(100vw - 6rem);
+ width: 64rem; /*multiple of 16?*/
+ max-height: calc(100vh - 6rem);
+ height: auto;
+ overflow-y: scroll;
+ -webkit-transform: translateX(-50%) translateY(-50%);
+ -moz-transform: translateX(-50%) translateY(-50%);
+ -ms-transform: translateX(-50%) translateY(-50%);
+ -o-transform: translateX(-50%) translateY(-50%);
+ transform: translateX(-50%) translateY(-50%);
+ top: 50%;
+ left: 50%;
+ background: var(--color-primary);
+ border: 0.5rem solid #333;
+ border-radius: 1rem;
+ box-shadow: 0.5rem 0.5rem 1rem 0.5rem black;
+ z-index: 10;
+ padding: 2rem;
+ grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
+ grid-gap: 1rem;
+}
+.frame-element-editor.opened, .textbox-editor.opened {
+ display: grid;
+}
+.frame-element-editor > .frame-element-editor-title, .textbox-editor > .textbox-editor-title {
+ grid-column: 1 / -2;
+}
+.frame-element-editor > .frame-element-editor-close, .textbox-editor > .textbox-editor-close {
+ cursor: pointer;
+ width: auto;
+ height: auto;
+ grid-column: -1 span 1;
+ user-select: none;
+ justify-self: right;
+}
+/*Text tab*/
+.text-option {
+ background: var(--input-background);
+}
+.text-codes {
+ max-width: calc(100vw - 3rem);
+ display: grid;
+ grid-template-columns: auto auto;
+ overflow-x: scroll;
+}
+.text-codes > * {
+ border: 1px solid black;
+ padding: 0.5rem;
+}
+/*download button*/
+.download {
+ text-align: center;
+ user-select: none;
+ cursor: pointer;
+}
+.download:hover {
+ text-decoration: underline;
+}
+/*supporters*/
+.supporters {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
+ grid-gap: 0.5rem;
+ padding: 1rem 2rem;
+}
diff --git a/fonts/Davison Americana CG Regular.otf b/fonts/Davison Americana CG Regular.otf
new file mode 100644
index 00000000..8d1cb36c
Binary files /dev/null and b/fonts/Davison Americana CG Regular.otf differ
diff --git a/fonts/arial_black.ttf b/fonts/arial_black.ttf
new file mode 100644
index 00000000..453ecb5f
Binary files /dev/null and b/fonts/arial_black.ttf differ
diff --git a/fonts/decour-cnd-regular-italic.ttf b/fonts/decour-cnd-regular-italic.ttf
new file mode 100644
index 00000000..a52ab860
Binary files /dev/null and b/fonts/decour-cnd-regular-italic.ttf differ
diff --git a/fonts/decour-cnd-regular.ttf b/fonts/decour-cnd-regular.ttf
new file mode 100644
index 00000000..e5d6ef55
Binary files /dev/null and b/fonts/decour-cnd-regular.ttf differ
diff --git a/fonts/officina-ser-itc-black.otf b/fonts/officina-ser-itc-black.otf
new file mode 100644
index 00000000..81a86be1
Binary files /dev/null and b/fonts/officina-ser-itc-black.otf differ
diff --git a/fonts/saloon-girl.ttf b/fonts/saloon-girl.ttf
new file mode 100644
index 00000000..010c5f39
Binary files /dev/null and b/fonts/saloon-girl.ttf differ
diff --git a/img/frames/wanted/a.png b/img/frames/wanted/a.png
new file mode 100644
index 00000000..c6974d29
Binary files /dev/null and b/img/frames/wanted/a.png differ
diff --git a/img/frames/wanted/aThumb.png b/img/frames/wanted/aThumb.png
new file mode 100644
index 00000000..22045a25
Binary files /dev/null and b/img/frames/wanted/aThumb.png differ
diff --git a/img/frames/wanted/b.png b/img/frames/wanted/b.png
new file mode 100644
index 00000000..b50363b0
Binary files /dev/null and b/img/frames/wanted/b.png differ
diff --git a/img/frames/wanted/bThumb.png b/img/frames/wanted/bThumb.png
new file mode 100644
index 00000000..f4385a3a
Binary files /dev/null and b/img/frames/wanted/bThumb.png differ
diff --git a/img/frames/wanted/g.png b/img/frames/wanted/g.png
new file mode 100644
index 00000000..0b8a218b
Binary files /dev/null and b/img/frames/wanted/g.png differ
diff --git a/img/frames/wanted/gThumb.png b/img/frames/wanted/gThumb.png
new file mode 100644
index 00000000..04eb39ad
Binary files /dev/null and b/img/frames/wanted/gThumb.png differ
diff --git a/img/frames/wanted/m.png b/img/frames/wanted/m.png
new file mode 100644
index 00000000..c3ea888d
Binary files /dev/null and b/img/frames/wanted/m.png differ
diff --git a/img/frames/wanted/mThumb.png b/img/frames/wanted/mThumb.png
new file mode 100644
index 00000000..07616420
Binary files /dev/null and b/img/frames/wanted/mThumb.png differ
diff --git a/img/frames/wanted/margin.png b/img/frames/wanted/margin.png
new file mode 100644
index 00000000..cfe07d28
Binary files /dev/null and b/img/frames/wanted/margin.png differ
diff --git a/img/frames/wanted/marginThumb.png b/img/frames/wanted/marginThumb.png
new file mode 100644
index 00000000..9de9656b
Binary files /dev/null and b/img/frames/wanted/marginThumb.png differ
diff --git a/img/frames/wanted/pt/a.png b/img/frames/wanted/pt/a.png
new file mode 100644
index 00000000..2b8a2f20
Binary files /dev/null and b/img/frames/wanted/pt/a.png differ
diff --git a/img/frames/wanted/pt/aThumb.png b/img/frames/wanted/pt/aThumb.png
new file mode 100644
index 00000000..828a224c
Binary files /dev/null and b/img/frames/wanted/pt/aThumb.png differ
diff --git a/img/frames/wanted/pt/b.png b/img/frames/wanted/pt/b.png
new file mode 100644
index 00000000..9a574b0a
Binary files /dev/null and b/img/frames/wanted/pt/b.png differ
diff --git a/img/frames/wanted/pt/bThumb.png b/img/frames/wanted/pt/bThumb.png
new file mode 100644
index 00000000..dcd7d436
Binary files /dev/null and b/img/frames/wanted/pt/bThumb.png differ
diff --git a/img/frames/wanted/pt/g.png b/img/frames/wanted/pt/g.png
new file mode 100644
index 00000000..ae179639
Binary files /dev/null and b/img/frames/wanted/pt/g.png differ
diff --git a/img/frames/wanted/pt/gThumb.png b/img/frames/wanted/pt/gThumb.png
new file mode 100644
index 00000000..cc12b3db
Binary files /dev/null and b/img/frames/wanted/pt/gThumb.png differ
diff --git a/img/frames/wanted/pt/m.png b/img/frames/wanted/pt/m.png
new file mode 100644
index 00000000..3db29c55
Binary files /dev/null and b/img/frames/wanted/pt/m.png differ
diff --git a/img/frames/wanted/pt/mThumb.png b/img/frames/wanted/pt/mThumb.png
new file mode 100644
index 00000000..00e3355f
Binary files /dev/null and b/img/frames/wanted/pt/mThumb.png differ
diff --git a/img/frames/wanted/pt/r.png b/img/frames/wanted/pt/r.png
new file mode 100644
index 00000000..c6d3d91b
Binary files /dev/null and b/img/frames/wanted/pt/r.png differ
diff --git a/img/frames/wanted/pt/rThumb.png b/img/frames/wanted/pt/rThumb.png
new file mode 100644
index 00000000..2915dbe7
Binary files /dev/null and b/img/frames/wanted/pt/rThumb.png differ
diff --git a/img/frames/wanted/pt/u.png b/img/frames/wanted/pt/u.png
new file mode 100644
index 00000000..e56345f2
Binary files /dev/null and b/img/frames/wanted/pt/u.png differ
diff --git a/img/frames/wanted/pt/uThumb.png b/img/frames/wanted/pt/uThumb.png
new file mode 100644
index 00000000..4fd396de
Binary files /dev/null and b/img/frames/wanted/pt/uThumb.png differ
diff --git a/img/frames/wanted/pt/w.png b/img/frames/wanted/pt/w.png
new file mode 100644
index 00000000..b5765766
Binary files /dev/null and b/img/frames/wanted/pt/w.png differ
diff --git a/img/frames/wanted/pt/wThumb.png b/img/frames/wanted/pt/wThumb.png
new file mode 100644
index 00000000..0c6cebe1
Binary files /dev/null and b/img/frames/wanted/pt/wThumb.png differ
diff --git a/img/frames/wanted/r.png b/img/frames/wanted/r.png
new file mode 100644
index 00000000..766b54b7
Binary files /dev/null and b/img/frames/wanted/r.png differ
diff --git a/img/frames/wanted/rThumb.png b/img/frames/wanted/rThumb.png
new file mode 100644
index 00000000..b1008703
Binary files /dev/null and b/img/frames/wanted/rThumb.png differ
diff --git a/img/frames/wanted/stamp/a.png b/img/frames/wanted/stamp/a.png
new file mode 100644
index 00000000..6468617d
Binary files /dev/null and b/img/frames/wanted/stamp/a.png differ
diff --git a/img/frames/wanted/stamp/aThumb.png b/img/frames/wanted/stamp/aThumb.png
new file mode 100644
index 00000000..bea6e1ae
Binary files /dev/null and b/img/frames/wanted/stamp/aThumb.png differ
diff --git a/img/frames/wanted/stamp/b.png b/img/frames/wanted/stamp/b.png
new file mode 100644
index 00000000..b620d42a
Binary files /dev/null and b/img/frames/wanted/stamp/b.png differ
diff --git a/img/frames/wanted/stamp/bThumb.png b/img/frames/wanted/stamp/bThumb.png
new file mode 100644
index 00000000..f4c43d0c
Binary files /dev/null and b/img/frames/wanted/stamp/bThumb.png differ
diff --git a/img/frames/wanted/stamp/g.png b/img/frames/wanted/stamp/g.png
new file mode 100644
index 00000000..467aa959
Binary files /dev/null and b/img/frames/wanted/stamp/g.png differ
diff --git a/img/frames/wanted/stamp/gThumb.png b/img/frames/wanted/stamp/gThumb.png
new file mode 100644
index 00000000..88bf6022
Binary files /dev/null and b/img/frames/wanted/stamp/gThumb.png differ
diff --git a/img/frames/wanted/stamp/m.png b/img/frames/wanted/stamp/m.png
new file mode 100644
index 00000000..f889d2b5
Binary files /dev/null and b/img/frames/wanted/stamp/m.png differ
diff --git a/img/frames/wanted/stamp/mThumb.png b/img/frames/wanted/stamp/mThumb.png
new file mode 100644
index 00000000..fd1019fb
Binary files /dev/null and b/img/frames/wanted/stamp/mThumb.png differ
diff --git a/img/frames/wanted/stamp/r.png b/img/frames/wanted/stamp/r.png
new file mode 100644
index 00000000..596b1e9b
Binary files /dev/null and b/img/frames/wanted/stamp/r.png differ
diff --git a/img/frames/wanted/stamp/rThumb.png b/img/frames/wanted/stamp/rThumb.png
new file mode 100644
index 00000000..2346595d
Binary files /dev/null and b/img/frames/wanted/stamp/rThumb.png differ
diff --git a/img/frames/wanted/stamp/u.png b/img/frames/wanted/stamp/u.png
new file mode 100644
index 00000000..9174c934
Binary files /dev/null and b/img/frames/wanted/stamp/u.png differ
diff --git a/img/frames/wanted/stamp/uThumb.png b/img/frames/wanted/stamp/uThumb.png
new file mode 100644
index 00000000..c6deadeb
Binary files /dev/null and b/img/frames/wanted/stamp/uThumb.png differ
diff --git a/img/frames/wanted/stamp/w.png b/img/frames/wanted/stamp/w.png
new file mode 100644
index 00000000..4e555561
Binary files /dev/null and b/img/frames/wanted/stamp/w.png differ
diff --git a/img/frames/wanted/stamp/wThumb.png b/img/frames/wanted/stamp/wThumb.png
new file mode 100644
index 00000000..640c5023
Binary files /dev/null and b/img/frames/wanted/stamp/wThumb.png differ
diff --git a/img/frames/wanted/u.png b/img/frames/wanted/u.png
new file mode 100644
index 00000000..87f2024c
Binary files /dev/null and b/img/frames/wanted/u.png differ
diff --git a/img/frames/wanted/uThumb.png b/img/frames/wanted/uThumb.png
new file mode 100644
index 00000000..7935f511
Binary files /dev/null and b/img/frames/wanted/uThumb.png differ
diff --git a/img/frames/wanted/w.png b/img/frames/wanted/w.png
new file mode 100644
index 00000000..c92a33a1
Binary files /dev/null and b/img/frames/wanted/w.png differ
diff --git a/img/frames/wanted/wThumb.png b/img/frames/wanted/wThumb.png
new file mode 100644
index 00000000..f966e14e
Binary files /dev/null and b/img/frames/wanted/wThumb.png differ
diff --git a/img/manaSymbols/wanted/wanted0.svg b/img/manaSymbols/wanted/wanted0.svg
new file mode 100644
index 00000000..30e0b28c
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted0.svg
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted1.svg b/img/manaSymbols/wanted/wanted1.svg
new file mode 100644
index 00000000..62739d38
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted1.svg
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted2.svg b/img/manaSymbols/wanted/wanted2.svg
new file mode 100644
index 00000000..a1b48baf
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted2.svg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted3.svg b/img/manaSymbols/wanted/wanted3.svg
new file mode 100644
index 00000000..d2bee9b3
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted3.svg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted4.svg b/img/manaSymbols/wanted/wanted4.svg
new file mode 100644
index 00000000..2e895772
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted4.svg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted5.svg b/img/manaSymbols/wanted/wanted5.svg
new file mode 100644
index 00000000..e443c323
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted5.svg
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted6.svg b/img/manaSymbols/wanted/wanted6.svg
new file mode 100644
index 00000000..739e66d9
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted6.svg
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted7.svg b/img/manaSymbols/wanted/wanted7.svg
new file mode 100644
index 00000000..9cfb57cb
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted7.svg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted8.svg b/img/manaSymbols/wanted/wanted8.svg
new file mode 100644
index 00000000..d08c5895
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted8.svg
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wanted9.svg b/img/manaSymbols/wanted/wanted9.svg
new file mode 100644
index 00000000..a5acb904
--- /dev/null
+++ b/img/manaSymbols/wanted/wanted9.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedb.svg b/img/manaSymbols/wanted/wantedb.svg
new file mode 100644
index 00000000..feeee324
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedb.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedc.svg b/img/manaSymbols/wanted/wantedc.svg
new file mode 100644
index 00000000..af1fb91f
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedc.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedg.svg b/img/manaSymbols/wanted/wantedg.svg
new file mode 100644
index 00000000..47a9249f
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedg.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedr.svg b/img/manaSymbols/wanted/wantedr.svg
new file mode 100644
index 00000000..afee45b5
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedr.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedu.svg b/img/manaSymbols/wanted/wantedu.svg
new file mode 100644
index 00000000..92ff1909
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedu.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedw.svg b/img/manaSymbols/wanted/wantedw.svg
new file mode 100644
index 00000000..9b276e1c
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedw.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/manaSymbols/wanted/wantedx.svg b/img/manaSymbols/wanted/wantedx.svg
new file mode 100644
index 00000000..0fe8e3f3
--- /dev/null
+++ b/img/manaSymbols/wanted/wantedx.svg
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/img/watermarks/0.svg b/img/watermarks/0.svg
deleted file mode 100644
index c0b16dff..00000000
--- a/img/watermarks/0.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/js/creator-23.js b/js/creator-23.js
index 172c4dde..cde0a086 100644
--- a/js/creator-23.js
+++ b/js/creator-23.js
@@ -1,5435 +1,5455 @@
-//URL Params
-var params = new URLSearchParams(window.location.search);
-const debugging = params.get('debug') != null;
-if (debugging) {
- alert('debugging - 4.0');
- document.querySelectorAll('.debugging').forEach(element => element.classList.remove('hidden'));
-}
-
-//To save the server from being overloaded? Maybe?
-function fixUri(input) {
- /* --- DISABLED FOR LOCAL VERSION --
- var prefix = 'https://card-conjurer.storage.googleapis.com';//'https://raw.githubusercontent.com/ImKyle4815/cardconjurer/remake';
- if (input.includes(prefix) || input.includes('http') || input.includes('data:image') || window.location.href.includes('localhost')) {
- return input;
- } else {
- return prefix + input; //input.replace('/img/frames', prefix + '/img/frames');
- } */
- return input;
-}
-function setImageUrl(image, source) {
- image.crossOrigin = 'anonymous';
- image.src = fixUri(source);
-}
-
-const baseWidth = 1500;
-const baseHeight = 2100;
-const highResScale = 1.34;
-// function getStandardWidth() {
-// var value = baseWidth;
-// if (localStorage.getItem('high-res') == 'true') {
-// value *= highResScale;
-// }
-// return value;
-// }
-// function getStandardHeight() {
-// var value = baseHeight;
-// if (localStorage.getItem('high-res') == 'true') {
-// value *= highResScale;
-// }
-// return value;
-// }
-function getStandardWidth() {
- return 2010;
-}
-function getStandardHeight() {
- return 2814;
-}
-
-//card object
-var card = {width:getStandardWidth(), height:getStandardHeight(), marginX:0, marginY:0, frames:[], artSource:fixUri('/img/blank.png'), artX:0, artY:0, artZoom:1, artRotate:0, setSymbolSource:fixUri('/img/blank.png'), setSymbolX:0, setSymbolY:0, setSymbolZoom:1, watermarkSource:fixUri('/img/blank.png'), watermarkX:0, watermarkY:0, watermarkZoom:1, watermarkLeft:'none', watermarkRight:'none', watermarkOpacity:0.4, version:'', manaSymbols:[]};
-//core images/masks
-const black = new Image(); black.crossOrigin = 'anonymous'; black.src = fixUri('/img/black.png');
-const blank = new Image(); blank.crossOrigin = 'anonymous'; blank.src = fixUri('/img/blank.png');
-const right = new Image(); right.crossOrigin = 'anonymous'; right.src = fixUri('/img/frames/maskRightHalf.png');
-const middle = new Image(); middle.crossOrigin = 'anonymous'; middle.src = fixUri('/img/frames/maskMiddleThird.png');
-const corner = new Image(); corner.crossOrigin = 'anonymous'; corner.src = fixUri('/img/frames/cornerCutout.png');
-//art
-art = new Image(); art.crossOrigin = 'anonymous'; art.src = blank.src;
-art.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
-art.onload = artEdited;
-//set symbol
-setSymbol = new Image(); setSymbol.crossOrigin = 'anonymous'; setSymbol.src = blank.src;
-setSymbol.onerror = function() {
- if (this.src.includes('gatherer.wizards.com')) {
- notify('Loading the set symbol from Gatherer failed. Please check this link to see if it exists. If it does, it may be necessary to manually download and upload the image. ', 5);
- }
- if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}
-}
-setSymbol.onload = setSymbolEdited;
-//watermark
-watermark = new Image(); watermark.crossOrigin = 'anonymous'; watermark.src = blank.src;
-watermark.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
-watermark.onload = watermarkEdited;
-//preview canvas
-var previewCanvas = document.querySelector('#previewCanvas');
-var previewContext = previewCanvas.getContext('2d');
-var canvasList = [];
-//frame/mask picker stuff
-var availableFrames = [];
-var selectedFrame = null;
-var selectedFrameIndex = 0;
-var selectedMaskIndex = 0;
-var selectedTextIndex = 0;
-var replacementMasks = {};
-var customCount = 0;
-var lastFrameClick = null;
-var lastMaskClick = null;
-//for imports
-var scryfallArt;
-var scryfallCard;
-//for text
-var drawTextBetweenFrames = false;
-var redrawFrames = false;
-var savedTextXPosition = 0;
-var savedTextXPosition2 = 0;
-var savedRollYPosition = null;
-var savedFont = null;
-var savedTextContents = {};
-//for misc
-var date = new Date();
-card.infoYear = date.getFullYear();
-document.querySelector("#info-year").value = card.infoYear;
-//to avoid rerunning special scripts (planeswalker, saga, etc...)
-
-var loadedVersions = [];
-//Card Object managament
-async function resetCardIrregularities({canvas = [getStandardWidth(), getStandardHeight(), 0, 0], resetOthers = true} = {}) {
- //misc details
- card.margins = false;
- card.bottomInfoTranslate = {x:0, y:0};
- card.bottomInfoRotate = 0;
- card.bottomInfoZoom = 1;
- replacementMasks = {};
- //rotation
- if (card.landscape) {
- // previewContext.scale(card.width/card.height, card.height/card.width);
- // previewContext.rotate(Math.PI / 2);
- // previewContext.translate(0, -card.width / 2);
- previewContext.setTransform(1, 0, 0, 1, 0, 0);
- card.landscape = false;
- }
- //card size
- card.width = canvas[0];
- card.height = canvas[1];
- card.marginX = canvas[2];
- card.marginY = canvas[3];
- //canvases
- canvasList.forEach(name => {
- if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
- sizeCanvas(name);
- }
- });
- if (resetOthers) {
- setBottomInfoStyle();
- //onload
- card.onload = null;
-
- card.hideBottomInfoBorder = false;
- card.showsFlavorBar = true;
- }
-}
-async function setBottomInfoStyle() {
- if (document.querySelector('#enableNewCollectorStyle').checked) {
- await loadBottomInfo({
- midLeft: {text:'{elemidinfo-set} \u2022 {elemidinfo-language} {savex}{fontbelerenbsc}{fontsize' + scaleHeight(0.001) + '}{upinline' + scaleHeight(0.0005) + '}\uFFEE{savex2}{elemidinfo-artist}', x:0.0647, y:0.9548, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- topLeft: {text:'{elemidinfo-rarity} {kerning3}{elemidinfo-number}{kerning0}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- note: {text:'{loadx}{elemidinfo-note}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- bottomLeft: {text:'NOT FOR SALE', x:0.0647, y:0.9719, width:0.8707, height:0.0143, oneLine:true, font:'gothammedium', size:0.0143, color:'white', outlineWidth:0.003},
- wizards: {name:'wizards', text:'{ptshift0,0.0172}\u2122 & \u00a9 {elemidinfo-year} Wizards of the Coast', x:0.0647, y:0.9377, width:0.8707, height:0.0167, oneLine:true, font:'mplantin', size:0.0162, color:'white', align:'right', outlineWidth:0.003},
- bottomRight: {text:'{ptshift0,0.0172}CardConjurer.com', x:0.0647, y:0.9548, width:0.8707, height:0.0143, oneLine:true, font:'mplantin', size:0.0143, color:'white', align:'right', outlineWidth:0.003}
- });
- } else {
- await loadBottomInfo({
- midLeft: {text:'{elemidinfo-set} \u2022 {elemidinfo-language} {savex}{fontbelerenbsc}{fontsize' + scaleHeight(0.001) + '}{upinline' + scaleHeight(0.0005) + '}\uFFEE{savex2}{elemidinfo-artist}', x:0.0647, y:0.9548, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- topLeft: {text:'{elemidinfo-number}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- note: {text:'{loadx2}{elemidinfo-note}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- rarity: {text:'{loadx}{elemidinfo-rarity}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
- bottomLeft: {text:'NOT FOR SALE', x:0.0647, y:0.9719, width:0.8707, height:0.0143, oneLine:true, font:'gothammedium', size:0.0143, color:'white', outlineWidth:0.003},
- wizards: {name:'wizards', text:'{ptshift0,0.0172}\u2122 & \u00a9 {elemidinfo-year} Wizards of the Coast', x:0.0647, y:0.9377, width:0.8707, height:0.0167, oneLine:true, font:'mplantin', size:0.0162, color:'white', align:'right', outlineWidth:0.003},
- bottomRight: {text:'{ptshift0,0.0172}CardConjurer.com', x:0.0647, y:0.9548, width:0.8707, height:0.0143, oneLine:true, font:'mplantin', size:0.0143, color:'white', align:'right', outlineWidth:0.003}
- });
- }
-}
-//Canvas management
-function sizeCanvas(name, width = Math.round(card.width * (1 + 2 * card.marginX)), height = Math.round(card.height * (1 + 2 * card.marginY))) {
- if (!window[name + 'Canvas']) {
- window[name + 'Canvas'] = document.createElement('canvas');
- window[name + 'Context'] = window[name + 'Canvas'].getContext('2d');
- canvasList[canvasList.length] = name;
- }
- window[name + 'Canvas'].width = width;
- window[name + 'Canvas'].height = height;
- if (name == 'line') { //force true to view all canvases - must restore to name == 'line' for proper kerning adjustments
- window[name + 'Canvas'].style = 'width: 20rem; height: 28rem; border: 1px solid red;';
- const label = document.createElement('div');
- label.innerHTML = name + ' If you can see this and don\'t want to, please clear your cache.';
- label.appendChild(window[name + 'Canvas']);
- label.classList = 'fake-hidden'; //Comment this out to view canvases
- document.body.appendChild(label);
- }
-}
-//create main canvases
-sizeCanvas('card');
-sizeCanvas('frame');
-sizeCanvas('frameMasking');
-sizeCanvas('frameCompositing');
-sizeCanvas('text');
-sizeCanvas('paragraph');
-sizeCanvas('line');
-sizeCanvas('watermark');
-sizeCanvas('bottomInfo');
-sizeCanvas('guidelines');
-sizeCanvas('prePT');
-//Scaling
-function scaleX(input) {
- return Math.round((input + card.marginX) * card.width);
-}
-function scaleWidth(input) {
- return Math.round(input * card.width);
-}
-function scaleY(input) {
- return Math.round((input + card.marginY) * card.height);
-}
-function scaleHeight(input) {
- return Math.round(input * card.height);
-}
-//Other nifty functions
-function getElementIndex(element) {
- return Array.prototype.indexOf.call(element.parentElement.children, element);
-}
-function getCardName() {
- if (card.text == undefined || card.text.title == undefined) {
- return 'unnamed';
- }
- var imageName = card.text.title.text || 'unnamed';
- if (card.text.nickname) {
- imageName += ' (' + card.text.nickname.text + ')';
- }
- return imageName.replace(/\{[^}]+\}/g, '');
-}
-function getInlineCardName() {
- if (card.text == undefined || card.text.title == undefined) {
- return 'unnamed';
- }
- var imageName = card.text.title.text || 'unnamed';
- if (card.text.nickname) {
- imageName = card.text.nickname.text;
- }
- return imageName.replace(/\{[^}]+\}/g, '');
-}
-//UI
-function toggleCreatorTabs(event, target) {
- Array.from(document.querySelector('#creator-menu-sections').children).forEach(element => element.classList.add('hidden'));
- document.querySelector('#creator-menu-' + target).classList.remove('hidden');
- selectSelectable(event);
-}
-function selectSelectable(event) {
- var eventTarget = event.target.closest('.selectable');
- Array.from(eventTarget.parentElement.children).forEach(element => element.classList.remove('selected'));
- eventTarget.classList.add('selected');
-}
-function dragStart(event) {
- Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
- event.target.closest('.draggable').classList.add('dragging');
-}
-function dragEnd(event) {
- Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
-}
-function touchMove(event) {
- if (event.target.nodeName != 'H4') {
- event.preventDefault();
- }
- var clientX = event.touches[0].clientX;
- var clientY = event.touches[0].clientY;
- Array.from(document.querySelector('.dragging').parentElement.children).forEach(element => {
- var elementBounds = element.getBoundingClientRect();
- if (clientY > elementBounds.top && clientY < elementBounds.bottom) {
- dragOver(element, false);
- }
- })
-}
-function dragOver(event, drag=true) {
- var eventTarget;
- if (drag) {
- eventTarget = event.target.closest('.draggable');
- } else {
- eventTarget = event;
- }
- var movingElement = document.querySelector('.dragging');
- if (document.querySelector('.dragging') && !eventTarget.classList.contains('dragging') && eventTarget.parentElement == movingElement.parentElement) {
- var parentElement = eventTarget.parentElement;
- var elements = document.createDocumentFragment();
- var movingElementPassed = false;
- var movingElementOldIndex = -1;
- var movingElementNewIndex = -1;
- Array.from(parentElement.children).forEach((element, index) => {
- if (element == eventTarget) {
- movingElementNewIndex = index;
- if(movingElementPassed) {
- elements.appendChild(element.cloneNode(true));
- elements.appendChild(movingElement.cloneNode(true));
- } else {
- elements.appendChild(movingElement.cloneNode(true));
- elements.appendChild(element.cloneNode(true));
- }
- } else if(element != movingElement) {
- elements.appendChild(element.cloneNode(true));
- } else {
- movingElementOldIndex = index;
- movingElementPassed = true;
- }
- });
- Array.from(elements.children).forEach(element => {
- element.ondragstart = dragStart;
- element.ontouchstart = dragStart;
- element.ondragend = dragEnd;
- element.ontouchend = dragEnd;
- element.ondragover = dragOver;
- element.ontouchmove = touchMove;
- element.onclick = frameElementClicked;
- element.children[3].onclick = removeFrame;
- })
- parentElement.innerHTML = null;
- parentElement.appendChild(elements);
- if (movingElementNewIndex >= 0) {
- var originalMovingElement = card.frames[movingElementOldIndex];
- card.frames.splice(movingElementOldIndex, 1);
- card.frames.splice(movingElementNewIndex, 0, originalMovingElement);
- drawFrames();
- }
- }
-}
-//Set Symbols
-const setSymbolAliases = new Map([
- ["anb", "ana"],
- ["tsb", "tsp"],
- ["pmei", "sld"],
-]);
-//Mana Symbols
-const mana = new Map();""
-// var manaSymbols = [];
-loadManaSymbols(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
- 'w', 'u', 'b', 'r', 'g', 'c', 'x', 'y', 'z', 't', 'untap', 'e', 's', 'oldtap', 'originaltap', 'purple', "a", "inf", "alchemy"]);
-loadManaSymbols(['wu', 'wb', 'ub', 'ur', 'br', 'bg', 'rg', 'rw', 'gw', 'gu', '2w', '2u', '2b', '2r', '2g', 'wp', 'up', 'bp', 'rp', 'gp', 'p',
- 'wup', 'wbp', 'ubp', 'urp', 'brp', 'bgp', 'rgp', 'rwp', 'gwp', 'gup', 'purplew', 'purpleu', 'purpleb', 'purpler', 'purpleg',
- '2purple', 'purplep'], [1.2, 1.2]);
-loadManaSymbols(['bar.png', 'whitebar.png']);
-loadManaSymbols(['chaos'], [1.2, 1]);
-loadManaSymbols(['tk'], [0.8, 1]);
-loadManaSymbols(['planeswalker'], [0.6, 1.2]);
-loadManaSymbols(['+1', '+2', '+3', '+4', '+5', '+6', '+7', '+8', '+9', '-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '+0'], [1.6, 1]);
-function loadManaSymbols(manaSymbolPaths, size = [1, 1]) {
- manaSymbolPaths.forEach(item => {
- var manaSymbol = {};
- if (typeof item == 'string') {
- manaSymbol.name = item.split('.')[0];
- manaSymbol.path = item;
- } else {
- manaSymbol.name = item[0].split('.')[0];
- manaSymbol.path = item[0];
- }
- if (manaSymbol.name.includes('/')) {
- manaSymbol.name = manaSymbol.name.split('/');
- manaSymbol.name = manaSymbol.name[manaSymbol.name.length - 1];
- }
- if (typeof item != 'string') {
- manaSymbol.back = item[1];
- manaSymbol.backs = item[2];
- for (var i = 0; i < item[2]; i ++) {
- loadManaSymbols([manaSymbol.path.replace(manaSymbol.name, 'back' + i + item[1])])
- }
- }
- manaSymbol.width = size[0];
- manaSymbol.height = size[1];
- manaSymbol.image = new Image();
- manaSymbol.image.crossOrigin = 'anonymous';
- var manaSymbolPath = '/img/manaSymbols/' + manaSymbol.path;
- if (!manaSymbolPath.includes('.png')) {
- manaSymbolPath += '.svg';
- }
- manaSymbol.image.src = fixUri(manaSymbolPath);
- mana.set(manaSymbol.name, manaSymbol);
- // manaSymbols.push(manaSymbol);
- });
-}
-function findManaSymbolIndex(string) {
- return mana.get(key) || -1;
-}
-function getManaSymbol(key) {
- return mana.get(key);
-}
-//FRAME TAB
-function drawFrames() {
- frameContext.clearRect(0, 0, frameCanvas.width, frameCanvas.height);
- var frameToDraw = card.frames.slice().reverse();
- var haveDrawnPrePTCanvas = false;
- frameToDraw.forEach(item => {
- if (item.image) {
- if (!haveDrawnPrePTCanvas && drawTextBetweenFrames && item.name.includes('Power/Toughness')) {
- haveDrawnPrePTCanvas = true;
- frameContext.globalCompositeOperation = 'source-over';
- frameContext.globalAlpha = 1;
- frameContext.drawImage(prePTCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
- }
- frameContext.globalCompositeOperation = item.mode || 'source-over';
- frameContext.globalAlpha = item.opacity / 100 || 1;
- if (item.opacity == 0) {
- frameContext.globalAlpha = 0;
- }
- var bounds = item.bounds || {};
- var ogBounds = item.ogBounds || bounds;
- frameX = Math.round(scaleX(bounds.x || 0));
- frameY = Math.round(scaleY(bounds.y || 0));
- frameWidth = Math.round(scaleWidth(bounds.width || 1));
- frameHeight = Math.round(scaleHeight(bounds.height || 1));
- frameMaskingContext.globalCompositeOperation = 'source-over';
- frameMaskingContext.drawImage(black, 0, 0, frameMaskingCanvas.width, frameMaskingCanvas.height);
- frameMaskingContext.globalCompositeOperation = 'source-in';
- item.masks.forEach(mask => frameMaskingContext.drawImage(mask.image, scaleX((bounds.x || 0) - (ogBounds.x || 0) - ((ogBounds.x || 0) * ((bounds.width || 1) / (ogBounds.width || 1) - 1))), scaleY((bounds.y || 0) - (ogBounds.y || 0) - ((ogBounds.y || 0) * ((bounds.height || 1) / (ogBounds.height || 1) - 1))), scaleWidth((bounds.width || 1) / (ogBounds.width || 1)), scaleHeight((bounds.height || 1) / (ogBounds.height || 1))));
- if (item.preserveAlpha) { //preserves alpha, and blends colors using an alpha that only cares about the mask(s), and the user-set opacity value
- //draw the image onto a separate canvas to view its unaltered state
- frameCompositingContext.clearRect(0, 0, frameCanvas.width, frameCanvas.height);
- frameCompositingContext.drawImage(item.image, frameX, frameY, frameWidth, frameHeight);
- //create pixel arrays for the existing image, new image, and alpha mask
- var existingData = frameContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height)
- var existingPixels = existingData.data;
- var newPixels = frameCompositingContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height).data;
- var maskPixels = frameMaskingContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height).data;
- const functionalAlphaMultiplier = frameContext.globalAlpha / 255;
- //manually blends colors, basing blending-alpha on the masks and desired draw-opacity, but preserving alpha
- for (var i = 0; i < existingPixels.length; i += 4) {
- const functionalAlpha = maskPixels[i + 3] * functionalAlphaMultiplier //functional alpha = alpha ignoring source image
- if (newPixels[i + 3] > 0) { //Only blend if the new image has alpha
- existingPixels[ i ] = existingPixels[ i ] * (1 - functionalAlpha) + newPixels[ i ] * functionalAlpha; //RED
- existingPixels[i + 1] = existingPixels[i + 1] * (1 - functionalAlpha) + newPixels[i + 1] * functionalAlpha; //GREEN
- existingPixels[i + 2] = existingPixels[i + 2] * (1 - functionalAlpha) + newPixels[i + 2] * functionalAlpha; //BLUE
- }
- }
- frameContext.putImageData(existingData, 0, 0);
- } else {
- //mask the image
- frameMaskingContext.drawImage(item.image, frameX, frameY, frameWidth, frameHeight);
- //color overlay
- if (item.colorOverlayCheck) {frameMaskingContext.globalCompositeOperation = 'source-in'; frameMaskingContext.fillStyle = item.colorOverlay; frameMaskingContext.fillRect(0, 0, frameMaskingCanvas.width, frameMaskingCanvas.height);}
- //HSL adjustments
- if (item.hslHue || item.hslSaturation || item.hslLightness) {
- hsl(frameMaskingCanvas, item.hslHue || 0, item.hslSaturation || 0, item.hslLightness || 0);
- }
- //erase mode
- if (item.erase) {frameContext.globalCompositeOperation = 'destination-out';}
- frameContext.drawImage(frameMaskingCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
- }
- }
- });
- if (!haveDrawnPrePTCanvas && drawTextBetweenFrames) {
- haveDrawnPrePTCanvas = true;
- frameContext.globalCompositeOperation = 'source-over';
- frameContext.globalAlpha = 1;
- frameContext.drawImage(prePTCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
- }
- drawCard();
-}
-function loadFramePacks(framePackOptions = []) {
- document.querySelector('#selectFramePack').innerHTML = null;
- framePackOptions.forEach(item => {
- var framePackOption = document.createElement('option');
- framePackOption.innerHTML = item.name;
- if (item.value == 'disabled') {
- framePackOption.disabled = true;
- } else {
- framePackOption.value = item.value;
- }
- document.querySelector('#selectFramePack').appendChild(framePackOption);
- });
- loadScript("/js/frames/pack" + document.querySelector('#selectFramePack').value + ".js");
-}
-function loadFramePack(frameOptions = availableFrames) {
- resetDoubleClick();
- document.querySelector('#frame-picker').innerHTML = null;
- frameOptions.forEach(item => {
- var frameOption = document.createElement('div');
- frameOption.classList = 'frame-option hidden';
- frameOption.onclick = frameOptionClicked;
- var frameOptionImage = document.createElement('img');
- frameOption.appendChild(frameOptionImage);
- frameOptionImage.onload = function() {
- this.parentElement.classList.remove('hidden');
- }
- if (!item.noThumb && !item.src.includes('/img/black.png')) {
- frameOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
- } else {
- frameOptionImage.src = fixUri(item.src);
- }
- document.querySelector('#frame-picker').appendChild(frameOption);
-
- })
- document.querySelector('#mask-picker').innerHTML = '';
- document.querySelector('#frame-picker').children[0].click();
- if (localStorage.getItem('autoLoadFrameVersion') == 'true') {
- document.querySelector('#loadFrameVersion').click();
- }
-}
-function autoLoadFrameVersion() {
- localStorage.setItem('autoLoadFrameVersion', document.querySelector('#autoLoadFrameVersion').checked);
-}
-function frameOptionClicked(event) {
- const button = doubleClick(event, 'frame');
- const clickedFrameOption = event.target.closest('.frame-option');
- const newFrameIndex = getElementIndex(clickedFrameOption);
- if (newFrameIndex != selectedFrameIndex || document.querySelector('#mask-picker').innerHTML == '') {
- resetDoubleClick();
- Array.from(document.querySelectorAll('.frame-option.selected')).forEach(element => element.classList.remove('selected'));
- clickedFrameOption.classList.add('selected');
- selectedFrameIndex = newFrameIndex;
- if (!availableFrames[selectedFrameIndex].noDefaultMask) {
- document.querySelector('#mask-picker').innerHTML = '
No Mask
';
- } else {
- document.querySelector('#mask-picker').innerHTML = '';
- }
- document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', No Mask)';
- if (availableFrames[selectedFrameIndex].masks) {
- availableFrames[selectedFrameIndex].masks.forEach(item => {
- const maskOption = document.createElement('div');
- maskOption.classList = 'mask-option hidden';
- maskOption.onclick = maskOptionClicked;
- const maskOptionImage = document.createElement('img');
- maskOption.appendChild(maskOptionImage);
- maskOptionImage.onload = function() {
- this.parentElement.classList.remove('hidden');
- }
- maskOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
- const maskOptionLabel = document.createElement('p');
- maskOptionLabel.innerHTML = item.name;
- maskOption.appendChild(maskOptionLabel);
- document.querySelector('#mask-picker').appendChild(maskOption);
- });
- }
- const firstChild = document.querySelector('#mask-picker').firstChild;
- firstChild.classList.add('selected');
- firstChild.click();
- } else if (button) { button.click(); resetDoubleClick(); }
-}
-function maskOptionClicked(event) {
- var button = doubleClick(event, 'mask');
- const clickedMaskOption = event.target.closest('.mask-option');
- (document.querySelector('.mask-option.selected').classList || document.querySelector('body').classList).remove('selected');
- clickedMaskOption.classList.add('selected');
- const newMaskIndex = getElementIndex(clickedMaskOption)
- if (newMaskIndex != selectedMaskIndex) { button = null; }
- selectedMaskIndex = newMaskIndex;
- var selectedMaskName = 'No Mask'
- if (selectedMaskIndex > 0) {selectedMaskName = availableFrames[selectedFrameIndex].masks[selectedMaskIndex - 1].name;}
- document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', ' + selectedMaskName + ')';
- if (button) { button.click(); resetDoubleClick(); }
-}
-function resetDoubleClick() {
- lastFrameClick, lastMaskClick = null, null;
-}
-function doubleClick(event, maskOrFrame) {
- const currentClick = (new Date()).getTime();
- var lastClick = null;
- if (maskOrFrame == 'mask') {
- lastClick = lastMaskClick;
- lastMaskClick = currentClick;
- } else {
- lastClick = lastFrameClick + 0;
- lastFrameClick = currentClick + 0;
- }
- if (lastClick && lastClick + 500 > currentClick) {
- var buttonID = null;
- if (event.shiftKey) {
- buttonID = '#addToRightHalf';
- } else if (event.ctrlKey) {
- buttonID = '#addToLeftHalf';
- } else if (event.altKey) {
- buttonID = '#addToMiddleThird';
- } else {
- buttonID = '#addToFull';
- }
- return document.querySelector(buttonID);
- }
- return null;
-}
-function cardFrameProperties(colors, manaCost, typeLine, power, style) {
- var colors = colors.map(color => color.toUpperCase())
- if ([
- ['U', 'W'],
- ['B', 'W'],
- ['R', 'B'],
- ['G', 'B'],
- ['B', 'U'],
- ['R', 'U'],
- ['G', 'R'],
- ['W', 'R'],
- ['W', 'G'],
- ['U', 'G']
- ].map(arr => JSON.stringify(arr) === JSON.stringify(colors)).includes(true)) {
- colors.reverse();
- }
-
- var isHybrid = manaCost.includes('/');
-
- var rules;
- if (style == 'Seventh') {
- if (typeLine.includes('Land')) {
- if (colors.length == 0 || colors.length > 2) {
- rules = 'L';
- } else {
- rules = colors[0] + 'L';
- }
- } else {
- if (colors.length == 1) {
- rules = colors[0];
- } else if (colors.length >=2) {
- rules = 'M';
- } else if (typeLine.includes("Artifact")) {
- rules = 'A';
- } else {
- rules = 'C';
- }
- }
-
- } else {
- if (typeLine.includes('Land')) {
- if (colors.length == 0) {
- rules = 'L';
- } else if (colors.length > 2) {
- rules = 'ML';
- } else {
- rules = colors[0] + 'L';
- }
- } else if (colors.length > 2) {
- if (style == 'Etched' && typeLine.includes('Artifact')) {
- rules = 'A';
- } else {
- rules = 'M';
- }
- } else if (colors.length != 0) {
- rules = colors[0];
- } else if (style == 'Borderless' && !typeLine.includes('Artifact')) {
- rules = 'C';
- } else {
- rules = 'A';
- }
- }
-
- var rulesRight;
- if (colors.length == 2) {
- if (typeLine.includes('Land')) {
- rulesRight = colors[1] + 'L';
- } else if (style != 'Seventh') {
- rulesRight = colors[1];
- }
- }
-
- var pinline = rules;
- var pinlineRight = rulesRight;
-
- if (style == 'Seventh' && typeLine.includes('Land') && colors.length >= 2) {
- pinline = 'L';
- pinlineRight = null;
- }
-
- var typeTitle;
- if (colors.length >= 2) {
- if (isHybrid || typeLine.includes('Land')) {
- if (colors.length >= 3) {
- typeTitle = 'M';
- } else {
- typeTitle = 'L';
- }
- } else {
- typeTitle = 'M';
- }
- } else if (typeLine.includes('Land')) {
- if (colors.length == 0) {
- typeTitle = 'L';
- } else if (style == 'Etched') {
- if (colors.length > 2) {
- typeTitle = 'M';
- } else if (colors.length == 1) {
- typeTitle = colors[0];
- } else {
- typeTitle = 'L';
- }
- } else {
- typeTitle = colors[0] + 'L';
- }
- } else if (colors.length == 1) {
- typeTitle = colors[0];
- } else if (style == 'Borderless' && !typeLine.includes('Artifact')) {
- typeTitle = 'C';
- } else {
- typeTitle = 'A';
- }
-
- var pt;
- if (power) {
- if (typeLine.includes('Vehicle')) {
- pt = 'V';
- } else if (typeTitle == 'L') {
- pt = 'C';
- } else {
- pt = typeTitle;
- }
- }
-
- var frame;
- if (style == 'Seventh') {
- if (typeLine.includes('Land')) {
- frame = 'L'
- } else {
- frame = pinline;
- }
- } else if (typeLine.includes('Land')) {
- if (style == 'Etched') {
- if (colors.length > 2) {
- frame = 'M';
- } else if (colors.length > 0) {
- frame = colors[0];
- } else {
- frame = 'L';
- }
- } else {
- frame = 'L';
- }
- } else if (typeLine.includes('Vehicle')) {
- frame = 'V';
- } else if (typeLine.includes('Artifact')) {
- frame = 'A';
- } else if (colors.length > 2) {
- frame = 'M';
- } else if (colors.length == 2) {
- if (isHybrid || style == 'Etched') {
- frame = colors[0];
- } else {
- frame = 'M';
- }
- } else if (colors.length == 1) {
- frame = colors[0];
- } else {
- frame = 'L';
- }
-
- var frameRight;
- if (!(typeLine.includes('Vehicle') || typeLine.includes('Artifact'))) {
- if (colors.length == 2 && (isHybrid || style == 'Etched')) {
- frameRight = colors[1];
- }
- }
-
- return {
- 'pinline': pinline,
- 'pinlineRight': pinlineRight,
- 'rules': rules,
- 'rulesRight': rulesRight,
- 'typeTitle': typeTitle,
- 'pt': pt,
- 'frame': frame,
- 'frameRight': frameRight
- }
-}
-var autoFramePack;
-function autoFrame() {
- var frame = document.querySelector('#autoFrame').value;
- if (frame == 'false') { autoFramePack = null; return; }
-
- var colors = [];
- if (card.text.type.text.toLowerCase().includes('land')) {
- var rules = card.text.rules.text;
- var flavorIndex = rules.indexOf('{flavor}');
- if (flavorIndex == -1) {
- flavorIndex = rules.indexOf('{oldflavor}');
- }
- if (flavorIndex != -1) {
- rules = rules.substring(0, flavorIndex);
- }
-
- var lines = rules.split('\n');
-
- lines.forEach(function(line) {
- var addIndex = line.indexOf('Add');
- var length = 3;
- if (addIndex == -1) {
- addIndex = line.toLowerCase().indexOf(' add');
- length = 4;
- }
- if (addIndex != -1) {
- var upToAdd = line.substring(addIndex+length).toLowerCase();
- ['W', 'U', 'B', 'R', 'G'].forEach(function (color) {
- if (upToAdd.includes('{' + color.toLowerCase() + '}')) {
- colors.push(color);
- }
- });
- }
- });
-
- if (!colors.includes('W') && (rules.toLowerCase().includes('plains') || card.text.type.text.toLowerCase().includes('plains'))) {
- colors.push('W');
- }
- if (!colors.includes('U') && (rules.toLowerCase().includes('island') || card.text.type.text.toLowerCase().includes('island'))) {
- colors.push('U');
- }
- if (!colors.includes('B') && (rules.toLowerCase().includes('swamp') || card.text.type.text.toLowerCase().includes('swamp'))) {
- colors.push('B');
- }
- if (!colors.includes('R') && (rules.toLowerCase().includes('mountain') || card.text.type.text.toLowerCase().includes('mountain'))) {
- colors.push('R');
- }
- if (!colors.includes('G') && (rules.toLowerCase().includes('forest') || card.text.type.text.toLowerCase().includes('forest'))) {
- colors.push('G');
- }
-
- if (rules.toLowerCase().includes('search') && colors.length == 0) {
- // TODO: This doesn't match Bog Wreckage
- if (rules.includes('into your hand') || (rules.includes('tapped') && !(rules.toLowerCase().includes('enters the battlefield tapped')) && !(rules.toLowerCase().includes('untap')))) {
- colors = [];
- } else if (colors.length == 0) {
- colors = ['W', 'U', 'B', 'R', 'G'];
- }
- }
-
- if (rules.includes('any color') || rules.includes('any one color') || rules.includes('choose a color') || rules.includes('any combination of colors')) {
- colors = ['W', 'U', 'B', 'R', 'G'];
- }
-
-
- } else {
- colors = [...new Set(card.text.mana.text.toUpperCase().split('').filter(char => ['W', 'U', 'B', 'R', 'G'].includes(char)))];
- }
-
- var group;
- if (frame == 'M15Regular-1') {
- autoM15Frame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Standard-3';
- } else if (frame == 'M15RegularNew') {
- autoM15NewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Accurate';
- } else if (frame == 'M15Eighth') {
- autoM15EighthFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Custom';
- } else if (frame == 'M15EighthUB') {
- autoM15EighthUBFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Custom';
- } else if (frame == 'UB') {
- autoUBFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Showcase-5';
- } else if (frame == 'UBNew') {
- autoUBNewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Accurate';
- } else if (frame == 'FullArtNew') {
- autoFullArtNewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Accurate';
- } else if (frame == 'Circuit') {
- autoCircuitFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- group = 'Custom';
- } else if (frame == 'Etched') {
- group = 'Showcase-5';
- autoEtchedFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- } else if (frame == 'Praetors') {
- group = 'Showcase-5';
- autoPhyrexianFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- } else if (frame == 'Seventh') {
- group = 'Misc-2';
- autoSeventhEditionFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- } else if (frame == 'M15BoxTopper') {
- group = 'Showcase-5';
- autoExtendedArtFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, false);
- } else if (frame == 'M15ExtendedArtShort') {
- group = 'Showcase-5';
- autoExtendedArtFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, true);
- } else if (frame == '8th') {
- group = 'Misc-2';
- auto8thEditionFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, false);
- } else if (frame == 'Borderless') {
- group = 'Showcase-5';
- autoBorderlessFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
- }
-
- if (autoFramePack != frame) {
- loadScript('/js/frames/pack' + frame + '.js');
- autoFramePack = frame;
- }
-}
-async function autoUBFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp') || frame.name.includes('Gold Holo Stamp'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
-
- // Set frames
-
- if (type_line.toLowerCase().includes('legendary')) {
- if (properties.pinlineRight) {
- frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Crown', true));
- }
- frames.push(makeUBFrameByLetter(properties.pinline, "Crown", false));
- frames.push(makeUBFrameByLetter(properties.pinline, "Crown Border Cover", false));
- }
- if (properties.pinlineRight) {
- frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Stamp', true));
- }
- frames.push(makeUBFrameByLetter(properties.pinline, "Stamp", false));
- if (properties.pt) {
- frames.push(makeUBFrameByLetter(properties.pt, 'PT', false));
- }
- if (properties.pinlineRight) {
- frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Pinline', true));
- }
- frames.push(makeUBFrameByLetter(properties.pinline, 'Pinline', false));
- frames.push(makeUBFrameByLetter(properties.typeTitle, 'Type', false));
- frames.push(makeUBFrameByLetter(properties.typeTitle, 'Title', false));
- if (properties.pinlineRight) {
- frames.push(makeUBFrameByLetter(properties.rulesRight, 'Rules', true));
- }
- frames.push(makeUBFrameByLetter(properties.rules, 'Rules', false));
- if (properties.frameRight) {
- frames.push(makeUBFrameByLetter(properties.frameRight, 'Frame', true));
- }
- frames.push(makeUBFrameByLetter(properties.frame, 'Frame', false));
- frames.push(makeUBFrameByLetter(properties.frame, 'Border', false));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoUBNewFrame(colors, mana_cost, type_line, power) {
- autoM15NewFrame(colors, mana_cost, type_line, power, 'ub');
-}
-async function autoFullArtNewFrame(colors, mana_cost, type_line, power) {
- autoM15NewFrame(colors, mana_cost, type_line, power, 'fullart');
-}
-async function autoCircuitFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp') || frame.name.includes('Gold Holo Stamp'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
-
- // Set frames
-
- if (type_line.toLowerCase().includes('legendary')) {
- if (properties.pinlineRight) {
- frames.push(makeCircuitFrameByLetter(properties.pinlineRight, 'Crown', true));
- }
- frames.push(makeCircuitFrameByLetter(properties.pinline, "Crown", false));
- frames.push(makeCircuitFrameByLetter(properties.pinline, "Crown Border Cover", false));
- }
- if (properties.pt) {
- frames.push(makeCircuitFrameByLetter(properties.pt, 'PT', false));
- }
- if (properties.pinlineRight) {
- frames.push(makeCircuitFrameByLetter(properties.pinlineRight, 'Pinline', true));
- }
- frames.push(makeCircuitFrameByLetter(properties.pinline, 'Pinline', false));
- frames.push(makeCircuitFrameByLetter(properties.typeTitle, 'Type', false));
- frames.push(makeCircuitFrameByLetter(properties.typeTitle, 'Title', false));
- if (properties.pinlineRight) {
- frames.push(makeCircuitFrameByLetter(properties.rulesRight, 'Rules', true));
- }
- frames.push(makeCircuitFrameByLetter(properties.rules, 'Rules', false));
- if (properties.frameRight) {
- frames.push(makeCircuitFrameByLetter(properties.frameRight, 'Frame', true));
- }
- frames.push(makeCircuitFrameByLetter(properties.frame, 'Frame', false));
- frames.push(makeCircuitFrameByLetter(properties.frame, 'Border', false));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoM15Frame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
- var style = 'regular';
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Crown', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, "Crown", false, style));
- frames.push(makeM15FrameByLetter(properties.pinline, "Crown Border Cover", false, style));
- }
- if (properties.pt) {
- frames.push(makeM15FrameByLetter(properties.pt, 'PT', false, style));
- }
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Pinline', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, 'Pinline', false, style));
- frames.push(makeM15FrameByLetter(properties.typeTitle, 'Type', false, style));
- frames.push(makeM15FrameByLetter(properties.typeTitle, 'Title', false, style));
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.rulesRight, 'Rules', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.rules, 'Rules', false, style));
- if (properties.frameRight) {
- frames.push(makeM15FrameByLetter(properties.frameRight, 'Frame', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.frame, 'Frame', false, style));
- frames.push(makeM15FrameByLetter(properties.frame, 'Border', false, style));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoM15NewFrame(colors, mana_cost, type_line, power, style = 'regular') {
- var frames;
- if (style == 'ub') {
- frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp'));
- } else {
- frames = card.frames.filter(frame => frame.name.includes('Extension'));
- }
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
- if (style != 'ub' && style != 'fullart') {
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
- }
-
- frames.push(makeM15NewFrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Crown', true, style));
- }
- frames.push(makeM15NewFrameByLetter(properties.pinline, "Crown", false, style));
- frames.push(makeM15NewFrameByLetter(properties.pinline, "Crown Border Cover", false, style));
- }
-
- if (style == 'ub') {
- if (properties.pinlineRight) {
- frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Stamp', true, style));
- }
- frames.push(makeM15NewFrameByLetter(properties.pinline, "Stamp", false, style));
- }
-
- if (properties.pt) {
- frames.push(makeM15NewFrameByLetter(properties.pt, 'PT', false, style));
- }
- if (properties.pinlineRight) {
- frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
- }
- frames.push(makeM15NewFrameByLetter(properties.pinline, 'Pinline', false, style));
- frames.push(makeM15NewFrameByLetter(properties.typeTitle, 'Type', false, style));
- frames.push(makeM15NewFrameByLetter(properties.typeTitle, 'Title', false, style));
- if (properties.pinlineRight) {
- frames.push(makeM15NewFrameByLetter(properties.rulesRight, 'Rules', true, style));
- }
- frames.push(makeM15NewFrameByLetter(properties.rules, 'Rules', false, style));
- if (properties.frameRight) {
- frames.push(makeM15NewFrameByLetter(properties.frameRight, 'Frame', true, style));
- }
- frames.push(makeM15NewFrameByLetter(properties.frame, 'Frame', false, style));
- frames.push(makeM15NewFrameByLetter(properties.frame, 'Border', false, style));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoM15EighthFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
- var style = 'regular';
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Crown', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, "Crown", false, style));
- frames.push(makeM15FrameByLetter(properties.pinline, "Crown Border Cover", false, style));
- }
- if (properties.pt) {
- frames.push(makeM15EighthFrameByLetter(properties.pt, 'PT', false, style));
- }
- if (properties.pinlineRight) {
- frames.push(makeM15EighthFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
- }
- frames.push(makeM15EighthFrameByLetter(properties.pinline, 'Pinline', false, style));
- frames.push(makeM15EighthFrameByLetter(properties.typeTitle, 'Type', false, style));
- frames.push(makeM15EighthFrameByLetter(properties.typeTitle, 'Title', false, style));
- if (properties.pinlineRight) {
- frames.push(makeM15EighthFrameByLetter(properties.rulesRight, 'Rules', true, style));
- }
- frames.push(makeM15EighthFrameByLetter(properties.rules, 'Rules', false, style));
- if (properties.frameRight) {
- frames.push(makeM15EighthFrameByLetter(properties.frameRight, 'Frame', true, style));
- }
- frames.push(makeM15EighthFrameByLetter(properties.frame, 'Frame', false, style));
- frames.push(makeM15EighthFrameByLetter(properties.frame, 'Border', false, style));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoM15EighthUBFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
- var style = 'regular';
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Crown', true, style));
- }
- frames.push(makeM15EighthUBFrameByLetter(properties.pinline, "Crown", false, style));
- frames.push(makeM15EighthUBFrameByLetter(properties.pinline, "Crown Border Cover", false, style));
- }
- if (properties.pt) {
- frames.push(makeM15EighthUBFrameByLetter(properties.pt, 'PT', false, style));
- }
- if (properties.pinlineRight) {
- frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
- }
- frames.push(makeM15EighthUBFrameByLetter(properties.pinline, 'Pinline', false, style));
- frames.push(makeM15EighthUBFrameByLetter(properties.typeTitle, 'Type', false, style));
- frames.push(makeM15EighthUBFrameByLetter(properties.typeTitle, 'Title', false, style));
- if (properties.pinlineRight) {
- frames.push(makeM15EighthUBFrameByLetter(properties.rulesRight, 'Rules', true, style));
- }
- frames.push(makeM15EighthUBFrameByLetter(properties.rules, 'Rules', false, style));
- if (properties.frameRight) {
- frames.push(makeM15EighthUBFrameByLetter(properties.frameRight, 'Frame', true, style));
- }
- frames.push(makeM15EighthUBFrameByLetter(properties.frame, 'Frame', false, style));
- frames.push(makeM15EighthUBFrameByLetter(properties.frame, 'Border', false, style));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoBorderlessFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Borderless');
- var style = 'regular';
- if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Inner Crown', true));
- }
- frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Crown', true));
- }
- frames.push(makeBorderlessFrameByLetter(properties.pinline, "Crown", false, style));
- frames.push(makeBorderlessFrameByLetter(properties.pinline, "Legend Crown Outline", false))
- frames.push(makeBorderlessFrameByLetter(properties.pinline, "Crown Border Cover", false));
- }
- if (properties.pt) {
- frames.push(makeBorderlessFrameByLetter(properties.pt, 'PT', false));
- }
- if (properties.pinlineRight) {
- frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Pinline', true));
- }
- frames.push(makeBorderlessFrameByLetter(properties.pinline, 'Pinline', false));
- frames.push(makeBorderlessFrameByLetter(properties.typeTitle, 'Type', false));
- frames.push(makeBorderlessFrameByLetter(properties.typeTitle, 'Title', false));
- frames.push(makeBorderlessFrameByLetter(properties.rules, 'Rules', false));
- frames.push(makeBorderlessFrameByLetter(properties.frame, 'Border', false));
-
- // if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- // card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- // }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function auto8thEditionFrame(colors, mana_cost, type_line, power, colorshifted = false) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
-
- // Set frames
- if (properties.pt) {
- frames.push(make8thEditionFrameByLetter(properties.pt, 'PT', false, colorshifted));
- }
- if (properties.pinlineRight) {
- frames.push(make8thEditionFrameByLetter(properties.pinlineRight, 'Pinline', true, colorshifted));
- }
- frames.push(make8thEditionFrameByLetter(properties.pinline, 'Pinline', false, colorshifted));
- frames.push(make8thEditionFrameByLetter(properties.typeTitle, 'Type', false, colorshifted));
- frames.push(make8thEditionFrameByLetter(properties.typeTitle, 'Title', false, colorshifted));
- if (properties.pinlineRight) {
- frames.push(make8thEditionFrameByLetter(properties.rulesRight, 'Rules', true, colorshifted));
- }
- frames.push(make8thEditionFrameByLetter(properties.rules, 'Rules', false, colorshifted));
- if (properties.frameRight) {
- frames.push(make8thEditionFrameByLetter(properties.frameRight, 'Frame', true, colorshifted));
- }
- frames.push(make8thEditionFrameByLetter(properties.frame, 'Frame', false, colorshifted));
- frames.push(make8thEditionFrameByLetter(properties.frame, 'Border', false, colorshifted));
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoExtendedArtFrame(colors, mana_cost, type_line, power, short) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power);
- var style = 'regular';
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
- if (type_line.includes('Legendary')) {
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown Outline", false, style, short));
-
- if (style == 'Nyx') {
- if (properties.pinlineRight) {
- frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style, short));
- }
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, 'Inner Crown', false, style, short));
- }
-
- if (properties.pinlineRight) {
- frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Crown', true, style, short));
- }
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown", false, style, short));
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown Border Cover", false, style, short));
- } else {
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Title Cutout", false, style, short));
- }
- if (properties.pt) {
- frames.push(makeExtendedArtFrameByLetter(properties.pt, 'PT', false, style, short));
- }
- if (properties.pinlineRight) {
- frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Pinline', true, style, short));
- }
- frames.push(makeExtendedArtFrameByLetter(properties.pinline, 'Pinline', false, style, short));
- frames.push(makeExtendedArtFrameByLetter(properties.typeTitle, 'Type', false, style, short));
- frames.push(makeExtendedArtFrameByLetter(properties.typeTitle, 'Title', false, style, short));
- if (properties.pinlineRight) {
- frames.push(makeExtendedArtFrameByLetter(properties.rulesRight, 'Rules', true, style, short));
- }
- frames.push(makeExtendedArtFrameByLetter(properties.rules, 'Rules', false, style, short));
- if (properties.frameRight) {
- frames.push(makeExtendedArtFrameByLetter(properties.frameRight, 'Frame', true, style, short));
- }
- frames.push(makeExtendedArtFrameByLetter(properties.frame, 'Frame', false, style, short));
- frames.push(makeExtendedArtFrameByLetter(properties.frame, 'Border', false, style, short));
-
- if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
- card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
- }
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoEtchedFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Etched');
- var style = 'regular';
- if (type_line.toLowerCase().includes('snow')) {
- style = 'snow';
- } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
- style = 'Nyx';
- }
-
- // Set frames
-
- if (type_line.includes('Legendary')) {
- if (style == 'Nyx') {
- if (properties.frameRight) {
- frames.push(makeEtchedFrameByLetter(properties.pinlineRight, 'Inner Crown', true));
- }
- frames.push(makeEtchedFrameByLetter(properties.pinline, 'Inner Crown', false, style));
- }
-
- if (properties.frameRight) {
- frames.push(makeEtchedFrameByLetter(properties.frameRight, 'Crown', true));
- }
- frames.push(makeEtchedFrameByLetter(properties.frame, "Crown", false));
- frames.push(makeEtchedFrameByLetter(properties.frame, "Crown Border Cover", false));
- }
- if (properties.pt) {
- frames.push(makeEtchedFrameByLetter(properties.pt, 'PT', false));
- }
- frames.push(makeEtchedFrameByLetter(properties.typeTitle, 'Type', false));
- frames.push(makeEtchedFrameByLetter(properties.typeTitle, 'Title', false));
- if (properties.pinlineRight) {
- frames.push(makeEtchedFrameByLetter(properties.rulesRight, 'Rules', true));
- }
- frames.push(makeEtchedFrameByLetter(properties.rules, 'Rules', false));
- if (properties.frameRight) {
- frames.push(makeEtchedFrameByLetter(properties.frameRight, 'Frame', true, style));
- }
- frames.push(makeEtchedFrameByLetter(properties.frame, 'Frame', false, style));
- frames.push(makeEtchedFrameByLetter(properties.frame, 'Border', false));
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoPhyrexianFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Phyrexian');
-
- // Set frames
-
- if (type_line.toLowerCase().includes('legendary')) {
- if (properties.pinlineRight) {
- frames.push(makePhyrexianFrameByLetter(properties.pinlineRight, 'Crown', true));
- }
- frames.push(makePhyrexianFrameByLetter(properties.pinline, "Crown", false));
- }
- if (properties.pt) {
- frames.push(makePhyrexianFrameByLetter(properties.pt, 'PT', false));
- }
- if (properties.pinlineRight) {
- frames.push(makePhyrexianFrameByLetter(properties.pinlineRight, 'Pinline', true));
- }
- frames.push(makePhyrexianFrameByLetter(properties.pinline, 'Pinline', false));
- frames.push(makePhyrexianFrameByLetter(properties.typeTitle, 'Type', false));
- frames.push(makePhyrexianFrameByLetter(properties.typeTitle, 'Title', false));
- if (properties.pinlineRight) {
- frames.push(makePhyrexianFrameByLetter(properties.rulesRight, 'Rules', true));
- }
- frames.push(makePhyrexianFrameByLetter(properties.rules, 'Rules', false));
- if (properties.frameRight) {
- frames.push(makePhyrexianFrameByLetter(properties.frameRight, 'Frame', true));
- }
- frames.push(makePhyrexianFrameByLetter(properties.frame, 'Frame', false));
- frames.push(makePhyrexianFrameByLetter(properties.frame, 'Border', false));
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-async function autoSeventhEditionFrame(colors, mana_cost, type_line, power) {
- var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('DCI Star'));
-
- //clear the draggable frames
- card.frames = [];
- document.querySelector('#frame-list').innerHTML = null;
-
- var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Seventh');
-
- // Set frames
- frames.push(makeSeventhEditionFrameByLetter(properties.pinline, 'Pinline', false));
- if (properties.rulesRight) {
- frames.push(makeSeventhEditionFrameByLetter(properties.rulesRight, 'Rules', true));
- }
- frames.push(makeSeventhEditionFrameByLetter(properties.rules, 'Rules', false));
- frames.push(makeSeventhEditionFrameByLetter(properties.frame, 'Frame', false));
- frames.push(makeSeventhEditionFrameByLetter(properties.pinline, 'Textbox Pinline', false));
- frames.push(makeSeventhEditionFrameByLetter(properties.frame, 'Border', false));
-
- card.frames = frames;
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
-}
-function makeM15FrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/crowns/m15Crown' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1667,
- 'width': 0.9454,
- 'x': 0.0274,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' ' + mask + ' (' + style + ')',
- 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0239,
- 'width': 0.672,
- 'x': 0.164,
- 'y': 0.0239
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/m15/' + style.toLowerCase() + '/m15Frame' + letter + '.png',
- }
-
- if (style == 'snow') {
- frame.src = frame.src.replace('m15Frame' + letter, letter.toLowerCase());
- } else {
- if (letter.includes('L') && letter.length > 1) {
- frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
- }
-
- if (style == 'Nyx') {
- frame.src = frame.src.replace('.png', 'Nyx.png');
- }
- }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-
-function makeM15NewFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if (letter.length == 2) {
- letter = letter.split("").reverse().join("");
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[1];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {x:0, y:0, width:1, height:137/2814}
- }
- }
-
- if (mask == "Crown") {
- var framePath = '';
- if (style == 'ub') {
- framePath = 'ub/';
- }
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/' + framePath + 'crowns/new/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {x:44/2010, y:53/2814, width:1922/2010, height:493/2814}
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' ' + mask + ' (' + style + ')',
- 'src': '/img/frames/m15/innerCrowns/new/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {x:329/2010, y:70/2814, width:1353/2010, height:64/2814}
- };
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- } else if (mask == "Stamp") {
- if (style == 'ub') {
- var frame = {
- 'name': frameName + ' Holo Stamp',
- 'src': '/img/frames/m15/new/ub/stamp/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {x:857/2015, y:2534/2814, width:299/2015, height:137/2814}
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
- }
-
- if (mask == 'PT') {
- var path = '/img/frames/m15/regular/m15PT';
- if (style == 'ub') {
- path = '/img/frames/m15/ub/pt/';
- letter = letter.toLowerCase();
- }
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': path + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var stylePath = '';
- if (style != 'regular') {
- stylePath = style.toLowerCase() + '/';
- }
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/m15/new/' + stylePath + letter.toLowerCase() + '.png',
- }
-
- // if (letter.includes('L') && letter.length > 1) {
- // frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
- // }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/m15/new/' + mask.toLowerCase() + '.png',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeM15EighthFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/crowns/m15Crown' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1667,
- 'width': 0.9454,
- 'x': 0.0274,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' ' + mask + ' (' + style + ')',
- 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0239,
- 'width': 0.672,
- 'x': 0.164,
- 'y': 0.0239
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 1901/2100
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/custom/m15-eighth/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
- }
-
- if (style != 'regular') {
- frame.name = style.charAt(0).toUpperCase() + style.slice(1) + ' ' + frame.name;
- }
-
- if (mask) {
- if (mask.toLowerCase() == 'border' || mask.toLowerCase() == 'frame') {
- frame.masks = [
- {
- 'src': '/img/frames/custom/m15-eighth/regular/' + mask + '.png',
- 'name': mask
- }
- ]
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeM15EighthUBFrameByLetter(letter, mask = false, maskToRightHalf = false) {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1667,
- 'width': 0.9454,
- 'x': 0.0274,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' ' + mask + ' (' + style + ')',
- 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0239,
- 'width': 0.672,
- 'x': 0.164,
- 'y': 0.0239
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/ub/pt/' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 1901/2100
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/custom/m15-eighth/ub/' + letter.toLowerCase() + '.png',
- }
-
- if (mask) {
- if (mask.toLowerCase() == 'border' || mask.toLowerCase() == 'frame') {
- frame.masks = [
- {
- 'src': '/img/frames/custom/m15-eighth/regular/' + mask + '.png',
- 'name': mask
- }
- ]
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeBorderlessFrameByLetter(letter, mask = false, maskToRightHalf = false, style) {
- letter = letter.toUpperCase();
-
- if (letter == 'V') {
- letter = 'A';
- }
-
- if (letter == 'ML') {
- letter = 'M';
- } else if (letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Legend Crown Outline") {
- return {
- 'name': 'Legend Crown Outline',
- 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1062,
- 'width': 0.944,
- 'x': 0.028,
- 'y': 0.0172
- }
- };
- }
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'erase': true,
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/crowns/m15Crown' + letter + 'Floating.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1024,
- 'width': 0.9387,
- 'x': 0.0307,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' ' + mask + ' (' + style + ')',
- 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0239,
- 'width': 0.672,
- 'x': 0.164,
- 'y': 0.0239
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/borderless/pt/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.066666666666,
- 'width': 0.182666666666,
- 'x': 0.764,
- 'y': 0.8861904761904762
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/m15/borderless/m15GenericShowcaseFrame' + letter + '.png',
- }
-
- if (letter.includes('L') && letter.length > 1) {
- frame.src = frame.src.replace(('m15GenericShowcaseFrame' + letter), 'l' + letter[0].toLowerCase())
- }
-
- if (mask) {
- if (mask == 'Pinline') {
- frame.masks = [
- {
- 'src': '/img/frames/m15/genericShowcase/m15GenericShowcaseMask' + mask + '.png',
- 'name': mask
- }
- ];
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ];
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function make8thEditionFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if (mask == 'PT') {
- if (letter.length > 1) {
- letter = letter[0];
- } else if (letter == 'C') {
- letter = 'L';
- }
- }
-
- if (letter == 'V') {
- letter = 'A';
- }
-
- var frameName = frameNames[letter];
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/8th/pt/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0839,
- 'width': 0.2147,
- 'x': 0.7227,
- 'y': 0.8796
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/8th/' + letter.toLowerCase() + '.png',
- }
-
- if (letter.includes('L') && letter.length > 1) {
- frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
- }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/8th/' + mask.toLowerCase() + '.png',
- 'name': mask
- }
- ]
-
- if (mask == 'Border') {
- frame.masks[0].src = frame.masks[0].src.replace('.png', '.svg');
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeExtendedArtFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular', short = false) {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Legend Crown Outline") {
- return {
- 'name': 'Legend Crown Outline',
- 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1062,
- 'width': 0.944,
- 'x': 0.028,
- 'y': 0.0172
- }
- };
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/crowns/m15Crown' + letter + 'Floating.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1024,
- 'width': 0.9387,
- 'x': 0.0307,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Crown Outline") {
- var frame = {
- 'name': 'Legend Crown Outline',
- 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1062,
- 'width': 0.944,
- 'x': 0.028,
- 'y': 0.0172
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + '(' + style + ')' + mask,
- 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0239,
- 'width': 0.672,
- 'x': 0.164,
- 'y': 0.0239
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame'
- }
-
- if (style != 'regular') {
- frame.src = '/img/frames/extended/regular/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png';
- if (short) {
- frame.src = frame.src.replace('/regular/', '/shorter/');
- }
- } else if (short) {
- frame.src = '/img/frames/m15/boxTopper/short/' + letter.toLowerCase() + '.png';
- } else {
- frame.src = '/img/frames/m15/boxTopper/m15BoxTopperFrame' + letter + '.png';
- }
-
- if (mask) {
- if (mask == 'Title Cutout') {
- if (short) {
- frame.masks = [
- {
- 'src': '/img/frames/extended/shorter/titleCutout.png',
- 'name': 'Title Cutout'
- }
- ]
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/m15/boxTopper/m15BoxTopperTitleCutout.png',
- 'name': 'Title Cutout'
- }
- ]
- }
- } else if (short && ['Frame', 'Rules', 'Type', 'Pinline'].includes(mask)) {
- var extension = mask == 'Type' ? '.png' : '.svg';
-
- frame.masks = [
- {
- 'src': '/img/frames/m15/boxTopper/short/' + mask.toLowerCase().replace('rules', 'text') + extension,
- 'name': mask
- }
- ]
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeUBFrameByLetter(letter, mask = false, maskToRightHalf = false) {
- letter = letter.toUpperCase();
-
- if (letter == 'C') {
- letter = 'L';
- }
-
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1667,
- 'width': 0.9454,
- 'x': 0.0274,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- } else if (mask == "Stamp") {
- var frame = {
- 'name': frameName + ' Holo Stamp',
- 'src': '/img/frames/m15/ub/regular/stamp/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0486,
- 'width': 0.1494,
- 'x': 0.4254,
- 'y': 0.9005
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/ub/pt/' + (letter == 'L' ? 'C' : letter).toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/m15/ub/regular/' + letter.toLowerCase() + '.png',
- }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeCircuitFrameByLetter(letter, mask = false, maskToRightHalf = false) {
- letter = letter.toUpperCase();
-
- if (letter == 'C') {
- letter = 'L';
- }
-
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land',
- 'ML': 'Multicolored Land'
- }
-
- if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Border Cover',
- 'src': '/img/black.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0177,
- 'width': 0.9214,
- 'x': 0.0394,
- 'y': 0.0277
- }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.1667,
- 'width': 0.9454,
- 'x': 0.0274,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/ub/pt/' + (letter == 'L' ? 'C' : letter).toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/custom/circuit/' + letter.toLowerCase() + '.png',
- }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeEtchedFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle'
- }
-
- if (mask == 'PT' && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- if (letter == 'ML') {
- letter = 'M';
- } else if (letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- } else if (letter == 'V' && mask == 'Crown') {
- letter = 'A';
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown Border Cover") {
- return {
- 'name': 'Legend Crown Cover',
- 'src': '/img/frames/etched/regular/crowns/cover.svg',
- 'masks': [],
- 'bounds': { }
- }
- }
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legend Crown',
- 'src': '/img/frames/etched/regular/crowns/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.092,
- 'width': 0.9387,
- 'x': 0.0307,
- 'y': 0.0191
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == "Inner Crown") {
- var frame = {
- 'name': frameName + ' Inner Crown',
- 'src': '/img/frames/etched/regular/innerCrowns/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {x:244/1500, y:51/2100, width:1012/1500, height:64/2100}
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/etched/regular/pt/' + letter.toLowerCase() + '.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0733,
- 'width': 0.188,
- 'x': 0.7573,
- 'y': 0.8848
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/etched/regular/' + letter.toLowerCase() + '.png',
- }
-
- if (style != 'regular') {
- frame.src = frame.src.replace('/regular/', '/regular/' + style.toLowerCase() + '/');
- frame.name = frame.name += ' (' + style +')';
- }
-
- if (mask) {
- frame.masks = [
- {
- 'src': '/img/frames/etched/regular/' + mask.toLowerCase() + '.svg',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makePhyrexianFrameByLetter(letter, mask = false, maskToRightHalf = false) {
- if (letter == 'C' || letter == 'V') {
- letter = 'L';
- }
-
- if (mask == 'Rules') {
- mask = 'Rules Text';
- }
-
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land'
- }
-
- if (mask == 'PT' && letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- if (letter == 'ML') {
- letter = 'M';
- } else if (letter.includes('L') && letter.length > 1) {
- letter = letter[0];
- }
-
- var frameName = frameNames[letter];
-
- if (mask == "Crown") {
- var frame = {
- 'name': frameName + ' Legendary Crown',
- 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + 'Crown.png',
- 'masks': [],
- 'bounds': {
- 'height': 100/2100,
- 'width': 1,
- 'x': 0,
- 'y': 0
- }
- }
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- return frame;
- }
-
- if (mask == 'PT') {
- return {
- 'name': frameName + ' Power/Toughness',
- 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + 'pt.png',
- 'masks': [],
- 'bounds': {
- 'height': 0.0772,
- 'width': 0.212,
- 'x': 0.746,
- 'y': 0.8858
- }
- }
- }
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + '.png',
- }
-
- if (mask == 'Type' || mask == 'Title') {
- frame.masks = [
- {
- 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else if (mask) {
- var extension = "png";
- var name = mask.toLowerCase();
- if (mask == 'Frame') {
- extension = 'svg';
- } else if (mask == 'Rules Text') {
- extension = 'svg';
- name = 'text';
- }
-
- frame.masks = [
- {
- 'src': '/img/frames/m15/praetors/' + name + '.' + extension,
- 'name': mask
- }
- ]
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-function makeSeventhEditionFrameByLetter(letter, mask = false, maskToRightHalf = false) {
- letter = letter.toUpperCase();
- var frameNames = {
- 'W': 'White',
- 'U': 'Blue',
- 'B': 'Black',
- 'R': 'Red',
- 'G': 'Green',
- 'M': 'Multicolored',
- 'A': 'Artifact',
- 'L': 'Land',
- 'C': 'Colorless',
- 'V': 'Vehicle',
- 'WL': 'White Land',
- 'UL': 'Blue Land',
- 'BL': 'Black Land',
- 'RL': 'Red Land',
- 'GL': 'Green Land'
- }
-
- if (letter == 'V') {
- letter = 'A';
- }
-
- if (letter == 'ML') {
- letter = 'L';
- }
-
- var frameName = frameNames[letter];
-
- var frame = {
- 'name': frameName + ' Frame',
- 'src': '/img/frames/seventh/regular/' + letter.toLowerCase() + '.png'
- };
-
- if (mask) {
- if (mask == 'Textbox Pinline') {
- frame.masks = [
- {
- 'src': '/img/frames/seventh/regular/trim.svg',
- 'name': 'Textbox Pinline'
- }
- ]
- } else {
- frame.masks = [
- {
- 'src': '/img/frames/seventh/regular/' + mask.toLowerCase() + '.svg',
- 'name': mask
- }
- ]
- }
-
- if (maskToRightHalf) {
- frame.masks.push({
- 'src': '/img/frames/maskRightHalf.png',
- 'name': 'Right Half'
- });
- }
- } else {
- frame.masks = [];
- }
-
- return frame;
-}
-async function addFrame(additionalMasks = [], loadingFrame = false) {
- var frameToAdd = JSON.parse(JSON.stringify(availableFrames[selectedFrameIndex]));
- var maskThumbnail = true;
- if (!loadingFrame) {
- // The frame is being added manually by the user, so we must process which mask(s) they have selected
- var noDefaultMask = 0;
- if (frameToAdd.noDefaultMask) {noDefaultMask = 1;}
- if (frameToAdd.masks && selectedMaskIndex + noDefaultMask > 0) {
- frameToAdd.masks = frameToAdd.masks.slice(selectedMaskIndex - 1 + noDefaultMask, selectedMaskIndex + noDefaultMask);
- } else {
- frameToAdd.masks = [];
- maskThumbnail = false;
- }
- additionalMasks.forEach(item => {
- if (item.name in replacementMasks) {
- item.src = replacementMasks[item.name];
- }
- frameToAdd.masks.push(item);
- });
- // Likewise, we now add any complementary frames
- if ('complementary' in frameToAdd && frameToAdd.masks.length == 0) {
- if (typeof frameToAdd.complementary == 'number') {
- frameToAdd.complementary = [frameToAdd.complementary];
- }
- const realFrameIndex = selectedFrameIndex;
- for (const index of frameToAdd.complementary) {
- selectedFrameIndex = index;
- await addFrame();
- }
- selectedFrameIndex = realFrameIndex;
- }
- } else {
- frameToAdd = loadingFrame;
- if (frameToAdd.masks.length == 0 || (frameToAdd.masks[0].src.includes('/img/frames/mask'))) {
- maskThumbnail = false;
- }
- }
- frameToAdd.masks.forEach(item => {
- item.image = new Image();
- item.image.crossOrigin = 'anonymous';
- item.image.src = blank.src;
- item.image.onload = drawFrames;
- item.image.src = fixUri(item.src);
- });
- frameToAdd.image = new Image();
- frameToAdd.image.crossOrigin = 'anonymous'
- frameToAdd.image.src = blank.src;
- frameToAdd.image.onload = drawFrames;
- if ('stretch' in frameToAdd) {
- stretchSVG(frameToAdd);
- } else {
- frameToAdd.image.src = fixUri(frameToAdd.src);
- }
- if (!loadingFrame) {
- card.frames.unshift(frameToAdd);
- }
- var frameElement = document.createElement('div');
- frameElement.classList = 'draggable frame-element';
- frameElement.draggable = 'true';
- frameElement.ondragstart = dragStart;
- frameElement.ondragend = dragEnd;
- frameElement.ondragover = dragOver;
- frameElement.ontouchstart = dragStart;
- frameElement.ontouchend = dragEnd;
- frameElement.ontouchmove = touchMove;
- frameElement.onclick = frameElementClicked;
- var frameElementImage = document.createElement('img');
- if (frameToAdd.noThumb || frameToAdd.src.includes('/img/black.png')) {
- frameElementImage.src = fixUri(frameToAdd.src);
- } else {
- frameElementImage.src = fixUri(frameToAdd.src.replace('.png', 'Thumb.png'));
- }
- frameElement.appendChild(frameElementImage);
- var frameElementMask = document.createElement('img');
- if (maskThumbnail) {
- frameElementMask.src = fixUri(frameToAdd.masks[0].src.replace('.png', 'Thumb.png'));
- } else {
- frameElementMask.src = black.src;
- }
- frameElement.appendChild(frameElementMask);
- var frameElementLabel = document.createElement('h4');
- frameElementLabel.innerHTML = frameToAdd.name;
- frameToAdd.masks.forEach(item => frameElementLabel.innerHTML += ', ' + item.name);
- frameElement.appendChild(frameElementLabel);
- var frameElementClose = document.createElement('h4');
- frameElementClose.innerHTML = 'X';
- frameElementClose.classList = 'frame-element-close';
- frameElementClose.onclick = removeFrame;
- frameElement.appendChild(frameElementClose);
- document.querySelector('#frame-list').prepend(frameElement);
- bottomInfoEdited();
-}
-function removeFrame(event) {
- card.frames.splice(getElementIndex(event.target.parentElement), 1);
- event.target.parentElement.remove();
- drawFrames();
- bottomInfoEdited();
-}
-function frameElementClicked(event) {
- if (!event.target.classList.contains('frame-element-close')) {
- var selectedFrameElement = event.target.closest('.frame-element');
- selectedFrame = card.frames[Array.from(selectedFrameElement.parentElement.children).indexOf(selectedFrameElement)];
- document.querySelector('#frame-element-editor').classList.add('opened');
- selectedFrame.bounds = selectedFrame.bounds || {};
- if (selectedFrame.ogBounds == undefined) {
- selectedFrame.ogBounds = JSON.parse(JSON.stringify(selectedFrame.bounds));
- }
- // Basic manipulations
- document.querySelector('#frame-editor-x').value = scaleWidth(selectedFrame.bounds.x || 0);
- document.querySelector('#frame-editor-x').onchange = (event) => {selectedFrame.bounds.x = (event.target.value / card.width); drawFrames();}
- document.querySelector('#frame-editor-y').value = scaleHeight(selectedFrame.bounds.y || 0);
- document.querySelector('#frame-editor-y').onchange = (event) => {selectedFrame.bounds.y = (event.target.value / card.height); drawFrames();}
- document.querySelector('#frame-editor-width').value = scaleWidth(selectedFrame.bounds.width || 1);
- document.querySelector('#frame-editor-width').onchange = (event) => {selectedFrame.bounds.width = (event.target.value / card.width); drawFrames();}
- document.querySelector('#frame-editor-height').value = scaleHeight(selectedFrame.bounds.height || 1);
- document.querySelector('#frame-editor-height').onchange = (event) => {selectedFrame.bounds.height = (event.target.value / card.height); drawFrames();}
- document.querySelector('#frame-editor-opacity').value = selectedFrame.opacity || 100;
- document.querySelector('#frame-editor-opacity').onchange = (event) => {selectedFrame.opacity = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-erase').checked = selectedFrame.erase || false;
- document.querySelector('#frame-editor-erase').onchange = (event) => {selectedFrame.erase = event.target.checked; drawFrames();}
- document.querySelector('#frame-editor-alpha').checked = selectedFrame.preserveAlpha || false;
- document.querySelector('#frame-editor-alpha').onchange = (event) => {selectedFrame.preserveAlpha = event.target.checked; drawFrames();}
- document.querySelector('#frame-editor-color-overlay-check').checked = selectedFrame.colorOverlayCheck || false;
- document.querySelector('#frame-editor-color-overlay-check').onchange = (event) => {selectedFrame.colorOverlayCheck = event.target.checked; drawFrames();}
- document.querySelector('#frame-editor-color-overlay').value = selectedFrame.colorOverlay || false;
- document.querySelector('#frame-editor-color-overlay').onchange = (event) => {selectedFrame.colorOverlay = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-hue').value = selectedFrame.hslHue || 0;
- document.querySelector('#frame-editor-hsl-hue-slider').value = selectedFrame.hslHue || 0;
- document.querySelector('#frame-editor-hsl-hue').onchange = (event) => {selectedFrame.hslHue = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-hue-slider').onchange = (event) => {selectedFrame.hslHue = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-saturation').value = selectedFrame.hslSaturation || 0;
- document.querySelector('#frame-editor-hsl-saturation-slider').value = selectedFrame.hslSaturation || 0;
- document.querySelector('#frame-editor-hsl-saturation').onchange = (event) => {selectedFrame.hslSaturation = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-saturation-slider').onchange = (event) => {selectedFrame.hslSaturation = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-lightness').value = selectedFrame.hslLightness || 0;
- document.querySelector('#frame-editor-hsl-lightness-slider').value = selectedFrame.hslLightness || 0;
- document.querySelector('#frame-editor-hsl-lightness').onchange = (event) => {selectedFrame.hslLightness = event.target.value; drawFrames();}
- document.querySelector('#frame-editor-hsl-lightness-slider').onchange = (event) => {selectedFrame.hslLightness = event.target.value; drawFrames();}
- // Removing masks
- const selectMaskElement = document.querySelector('#frame-editor-masks');
- selectMaskElement.innerHTML = null;
- const maskOptionNone = document.createElement('option');
- maskOptionNone.disabled = true;
- maskOptionNone.innerHTML = 'None Selected';
- selectMaskElement.appendChild(maskOptionNone);
- selectedFrame.masks.forEach(mask => {
- const maskOption = document.createElement('option');
- maskOption.innerHTML = mask.name;
- selectMaskElement.appendChild(maskOption);
- });
- selectMaskElement.selectedIndex = 0;
- }
-}
-function frameElementMaskRemoved() {
- const selectElement = document.querySelector('#frame-editor-masks');
- const selectedOption = selectElement.value;
- if (selectedOption != 'None Selected') {
- selectElement.remove(selectElement.selectedIndex);
- selectElement.selectedIndex = 0;
- selectedFrame.masks.forEach(mask => {
- if (mask.name == selectedOption) {
- selectedFrame.masks = selectedFrame.masks.filter(item => item.name != selectedOption);
- drawFrames();
- }
- });
- }
-}
-function uploadMaskOption(imageSource) {
- const uploadedMask = {name:`Uploaded Image (${customCount})`, src:imageSource, noThumb:true, image: new Image()};
- customCount ++;
- selectedFrame.masks.push(uploadedMask);
- uploadedMask.image.onload = drawFrames;
- uploadedMask.image.src = imageSource;
-}
-function uploadFrameOption(imageSource) {
- const uploadedFrame = {name:`Uploaded Image (${customCount})`, src:imageSource, noThumb:true};
- customCount ++;
- availableFrames.push(uploadedFrame);
- loadFramePack();
-}
-function hsl(canvas, inputH, inputS, inputL) {
- //adjust inputs
- var hue = parseInt(inputH) / 360;
- var saturation = parseInt(inputS) / 100;
- var lightness = parseInt(inputL) / 100;
- //create needed objects
- var context = canvas.getContext('2d')
- var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
- var pixels = imageData.data;
- //for every pixel...
- for (var i = 0; i < pixels.length; i += 4) {
- //grab rgb
- var r = pixels[i];
- var g = pixels[i + 1];
- var b = pixels[i + 2];
- //convert to hsl
- var res = rgbToHSL(r, g, b);
- h = res[0];
- s = res[1];
- l = res[2];
- //make adjustments
- h += hue;
- while (h > 1) {h --;}
- s = Math.min(Math.max(s + saturation, 0), 1);
- l = Math.min(Math.max(l + lightness, 0), 1);
- //convert back to rgb
- res = hslToRGB(h, s, l);
- r = res[0];
- g = res[1];
- b = res[2];
- //and reassign
- pixels[i] = r;
- pixels[i + 1] = g;
- pixels[i + 2] = b;
- }
- //then put the new image data back
- context.putImageData(imageData, 0, 0);
-}
-function croppedCanvas(oldCanvas, sensitivity = 0) {
- var oldContext = oldCanvas.getContext('2d');
- var newCanvas = document.createElement('canvas');
- var newContext = newCanvas.getContext('2d');
- var pixels = oldContext.getImageData(0, 0, oldCanvas.width, oldCanvas.height).data;
- var pixX = [];
- var pixY = [];
- for (var x = 0; x < oldCanvas.width; x += 1) {
- for (var y = 0; y < oldCanvas.height; y += 1) {
- if (pixels[(y * oldCanvas.width + x) * 4 + 3] > sensitivity) {
- pixX.push(x);
- pixY.push(y);
- }
- }
- }
- pixX.sort(function(a, b) { return a - b });
- pixY.sort(function(a, b) { return a - b });
- var n = pixX.length - 1;
- var newWidth = 1 + pixX[n] - pixX[0];
- var newHeight = 1 + pixY[n] - pixY[0];
- newCanvas.width = newWidth;
- newCanvas.height = newHeight;
- newContext.putImageData(oldCanvas.getContext('2d').getImageData(pixX[0], pixY[0], newWidth, newHeight), 0, 0);
- return newCanvas;
-}
-/*
-shoutout to https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion for providing the hsl-rgb conversion algorithms
-*/
-function rgbToHSL(r, g, b){
- r /= 255, g /= 255, b /= 255;
- var max = Math.max(r, g, b), min = Math.min(r, g, b);
- var h, s, l = (max + min) / 2;
-
- if(max == min){
- h = s = 0; // achromatic
- }else{
- var d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch(max){
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
- h /= 6;
- }
-
- return [h, s, l];
-}
-function hslToRGB(h, s, l){
- var r, g, b;
-
- if(s == 0){
- r = g = b = l; // achromatic
- }else{
- var hue2rgb = function hue2rgb(p, q, t){
- if(t < 0) t += 1;
- if(t > 1) t -= 1;
- if(t < 1/6) return p + (q - p) * 6 * t;
- if(t < 1/2) return q;
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
- return p;
- }
-
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3);
- }
-
- return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
-}
-//TEXT TAB
-var writingText;
-var autoFrameTimer;
-function loadTextOptions(textObject, replace=true) {
- var oldCardText = card.text || {};
- Object.entries(oldCardText).forEach(item => {
- savedTextContents[item[0]] = oldCardText[item[0]].text;
- });
- if (replace) {
- card.text = textObject;
- } else {
- Object.keys(textObject).forEach(key => {
- card.text[key] = textObject[key];
- });
- }
- document.querySelector('#text-options').innerHTML = null;
- Object.entries(card.text).forEach(item => {
- if (oldCardText[item[0]]) {
- card.text[item[0]].text = oldCardText[item[0]].text;
- } else if (savedTextContents[item[0]]) {
- card.text[item[0]].text = savedTextContents[item[0]];
- }
- var textOptionElement = document.createElement('h4');
- textOptionElement.innerHTML = item[1].name;
- textOptionElement.classList = 'selectable text-option'
- textOptionElement.onclick = textOptionClicked;
- document.querySelector('#text-options').appendChild(textOptionElement);
- });
- document.querySelector('#text-options').firstChild.click();
- drawTextBuffer();
- drawNewGuidelines();
-}
-function textOptionClicked(event) {
- selectedTextIndex = getElementIndex(event.target);
- document.querySelector('#text-editor').value = Object.entries(card.text)[selectedTextIndex][1].text;
- document.querySelector('#text-editor-font-size').value = Object.entries(card.text)[selectedTextIndex][1].fontSize;
- selectSelectable(event);
-}
-function textboxEditor() {
- var selectedTextbox = card.text[Object.keys(card.text)[selectedTextIndex]];
- document.querySelector('#textbox-editor').classList.add('opened');
- document.querySelector('#textbox-editor-x').value = scaleWidth(selectedTextbox.x || 0);
- document.querySelector('#textbox-editor-x').onchange = (event) => {selectedTextbox.x = (event.target.value / card.width); textEdited();}
- document.querySelector('#textbox-editor-y').value = scaleHeight(selectedTextbox.y || 0);
- document.querySelector('#textbox-editor-y').onchange = (event) => {selectedTextbox.y = (event.target.value / card.height); textEdited();}
- document.querySelector('#textbox-editor-width').value = scaleWidth(selectedTextbox.width || 1);
- document.querySelector('#textbox-editor-width').onchange = (event) => {selectedTextbox.width = (event.target.value / card.width); textEdited();}
- document.querySelector('#textbox-editor-height').value = scaleHeight(selectedTextbox.height || 1);
- document.querySelector('#textbox-editor-height').onchange = (event) => {selectedTextbox.height = (event.target.value / card.height); textEdited();}
-}
-function textEdited() {
- card.text[Object.keys(card.text)[selectedTextIndex]].text = curlyQuotes(document.querySelector('#text-editor').value);
- drawTextBuffer();
- autoFrameBuffer();
-}
-function fontSizedEdited() {
- card.text[Object.keys(card.text)[selectedTextIndex]].fontSize = document.querySelector('#text-editor-font-size').value;
- drawTextBuffer();
-}
-function drawTextBuffer() {
- clearTimeout(writingText);
- writingText = setTimeout(drawText, 500);
-}
-function autoFrameBuffer() {
- clearTimeout(autoFrameTimer);
- autoFrameTimer = setTimeout(autoFrame, 500);
-}
-async function drawText() {
- textContext.clearRect(0, 0, textCanvas.width, textCanvas.height);
- prePTContext.clearRect(0, 0, prePTCanvas.width, prePTCanvas.height);
- drawTextBetweenFrames = false;
- for (var textObject of Object.entries(card.text)) {
- await writeText(textObject[1], textContext);
- continue;
- }
- if (drawTextBetweenFrames || redrawFrames) {
- drawFrames();
- if (!drawTextBetweenFrames) {
- redrawFrames = false;
- }
- } else {
- drawCard();
- }
-}
-var justifyWidth = 90;
-function writeText(textObject, targetContext) {
- //Most bits of info about text loaded, with defaults when needed
- var textX = scaleX(textObject.x) || scaleX(0);
- var textY = scaleY(textObject.y) || scaleY(0);
- var textWidth = scaleWidth(textObject.width) || scaleWidth(1);
- var textHeight = scaleHeight(textObject.height) || scaleHeight(1);
- var startingTextSize = scaleHeight(textObject.size) || scaleHeight(0.038);
- var textFontHeightRatio = 0.7;
- var textBounded = textObject.bounded || true;
- var textOneLine = textObject.oneLine || false;
- var textManaCost = textObject.manaCost || false;
- var textAllCaps = textObject.allCaps || false;
- var textManaSpacing = scaleWidth(textObject.manaSpacing) || 0;
- //Buffers the canvases accordingly
- var canvasMargin = 300;
- paragraphCanvas.width = textWidth + 2 * canvasMargin;
- paragraphCanvas.height = textHeight + 2 * canvasMargin;
- lineCanvas.width = textWidth + 2 * canvasMargin;
- lineCanvas.height = startingTextSize + 2 * canvasMargin;
- //Preps the text string
- var splitString = '6GJt7eL8';
- var rawText = textObject.text
- if (document.querySelector('#hide-reminder-text').checked && textObject.name && textObject.name != 'Title' && textObject.name != 'Type' && textObject.name != 'Mana Cost' && textObject.name != 'Power/Toughness') {
- var rulesText = rawText;
- var flavorText = '';
- var flavorIndex = rawText.indexOf('{flavor}') || rawText.indexOf('///');
- if (flavorIndex >= 0) {
- flavorText = rawText.substring(flavorIndex);
- rulesText = rawText.substring(0, flavorIndex);
- }
-
- rulesText = rulesText.replace(/\([^\)]+\)/g, '');
-
- rawText = rulesText + flavorText;
- }
- if (textAllCaps) {
- rawText = rawText.toUpperCase();
- }
- if ((textObject.name == 'wizards' || textObject.name == 'copyright') && params.get('copyright') != null && (params.get('copyright') != '' || card.margins)) {
- rawText = params.get('copyright'); //so people using CC for custom card games without WotC's IP can customize their copyright info
- if (rawText == 'none') { rawText = ''; }
- }
- if (rawText.toLowerCase().includes('{cardname}') || rawText.toLowerCase().includes('~')) {
- rawText = rawText.replace(/{cardname}|~/ig, getInlineCardName());
- }
- if (document.querySelector('#info-artist').value == '') {
- rawText = rawText.replace('\uFFEE{savex2}{elemidinfo-artist}', '');
- }
- if (rawText.includes('///')) {
- rawText = rawText.replace(/\/\/\//g, '{flavor}');
- }
- if (rawText.includes('//')) {
- rawText = rawText.replace(/\/\//g, '{lns}');
- }
- if (card.version == 'pokemon') {
- rawText = rawText.replace(/{flavor}/g, '{oldflavor}{fontsize-20}{fontgillsansbolditalic}');
- } else if (card.version == 'dossier') {
- rawText = rawText.replace(/{flavor}(.*)/g, function(v) { return '{/indent}{lns}{bar}{lns}{fixtextalign}' + v.replace(/{flavor}/g, '').toUpperCase(); });
- } else if (!card.showsFlavorBar) {
- rawText = rawText.replace(/{flavor}/g, '{oldflavor}');
- }
- rawText = rawText.replace(/ - /g, ' — ');
- var splitText = rawText.replace(/\n/g, '{line}').replace(/{-}/g, '\u2014').replace(/{divider}/g, '{/indent}{lns}{bar}{lns}{fixtextalign}').replace(/{flavor}/g, '{/indent}{lns}{bar}{lns}{fixtextalign}{i}').replace(/{oldflavor}/g, '{/indent}{lns}{lns}{up30}{i}').replace(/{/g, splitString + '{').replace(/}/g, '}' + splitString).replace(/ /g, splitString + ' ' + splitString).split(splitString);
- splitText = splitText.filter(item => item);
- if (textObject.vertical) {
- newSplitText = [];
- splitText.forEach(item => {
- if (item.includes('{') && item.includes('}')) {
- newSplitText.push(item);
- } else if (item == ' ') {
- newSplitText.push(`{down${scaleHeight(0.01)}}`);
- } else {
- item.split('').forEach(char => {
- if (char == '’') {
- newSplitText.push(`{right${startingTextSize * 0.6}}`, '’', '{lns}', `{up${startingTextSize * 0.75}}`);
- } else {
- newSplitText.push(char, '{lns}');
- }
- });
- // newSplitText = newSplitText.concat(item.split(''));
- }
- });
- splitText = newSplitText;
- }
- // if (textManaCost && textObject.arcStart > 0) {
- // splitText.reverse();
- // }
- if (textObject.manaCost) {
- splitText = splitText.filter(item => item != ' ');
- }
- splitText.push('');
- //Manages the redraw loop
- var drawingText = true;
- //Repeatedly tries to draw the text at smaller and smaller sizes until it fits
- outerloop: while (drawingText) {
- //Rest of the text info loaded that may have been changed by a previous attempt at drawing the text
- var textColor = textObject.color || 'black';
- var textFont = textObject.font || 'mplantin';
- var textAlign = textObject.align || 'left';
- var textJustify = textObject.justify || 'left';
- var textShadowColor = textObject.shadow || 'black';
- var textShadowOffsetX = scaleWidth(textObject.shadowX) || 0;
- var textShadowOffsetY = scaleHeight(textObject.shadowY) || 0;
- var textShadowBlur = scaleHeight(textObject.shadowBlur) || 0;
- var textArcRadius = scaleHeight(textObject.arcRadius) || 0;
- var manaSymbolColor = textObject.manaSymbolColor || null;
- var textRotation = textObject.rotation || 0;
- if (textArcRadius > 0) {
- //Buffers the canvases accordingly
- var canvasMargin = 300 + textArcRadius;
- paragraphCanvas.width = textWidth + 2 * canvasMargin;
- paragraphCanvas.height = textHeight + 2 * canvasMargin;
- lineCanvas.width = textWidth + 2 * canvasMargin;
- lineCanvas.height = startingTextSize + 2 * canvasMargin;
- }
- var textArcStart = textObject.arcStart || 0;
- //Variables for tracking text position/size/font
- var currentX = 0;
- var startingCurrentX = 0;
- var currentY = 0;
- var lineY = 0;
- var newLine = false;
- var textFontExtension = '';
- var textFontStyle = textObject.fontStyle || '';
- var manaPlacementCounter = 0;
- var realTextAlign = textAlign;
- savedRollYPosition = null;
- var savedRollColor = 'black';
- var drawToPrePTCanvas = false;
- var widestLineWidth = 0;
- //variables that track various... things?
- var textSize = startingTextSize;
- var newLineSpacing = (textObject.lineSpacing || 0) * textSize;
- var ptShift = [0, 0];
- var permaShift = [0, 0];
- var fillJustify = false;
- //Finish prepping canvases
- paragraphContext.clearRect(0, 0, paragraphCanvas.width, paragraphCanvas.height);
- lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
- lineContext.letterSpacing = (scaleWidth(textObject.kerning) || 0) + 'px';
- // if (textFont == 'goudymedieval') {
- // lineCanvas.style.letterSpacing = '3.5px';
- // }
- textSize += parseInt(textObject.fontSize || '0');
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- lineContext.fillStyle = textColor;
- lineContext.shadowColor = textShadowColor;
- lineContext.shadowOffsetX = textShadowOffsetX;
- lineContext.shadowOffsetY = textShadowOffsetY;
- lineContext.shadowBlur = textShadowBlur;
- lineContext.strokeStyle = textObject.outlineColor || 'black';
- var textOutlineWidth = scaleHeight(textObject.outlineWidth) || 0;
-
- var hideBottomInfoBorder = card.hideBottomInfoBorder || false;
- if (hideBottomInfoBorder && ['midLeft', 'topLeft', 'note', 'bottomLeft', 'wizards', 'bottomRight'].includes(textObject.name)) {
- textOutlineWidth = 0;
- }
- lineContext.lineWidth = textOutlineWidth;
- //Begin looping through words/codes
- innerloop: for (word of splitText) {
- var wordToWrite = word;
- if (wordToWrite.includes('{') && wordToWrite.includes('}') || textManaCost || savedFont) {
- var possibleCode = wordToWrite.toLowerCase().replace('{', '').replace('}', '');
- wordToWrite = null;
- if (possibleCode == 'line') {
- newLine = true;
- startingCurrentX = 0;
- newLineSpacing = textSize * 0.35;
- } else if (possibleCode == 'lns' || possibleCode == 'linenospace') {
- newLine = true;
- } else if (possibleCode == 'bar') {
- var barWidth = textWidth * 0.96;
- var barHeight = scaleHeight(0.03);
- var barImageName = 'bar';
- var barDistance = 0;
- realTextAlign = textAlign;
- textAlign = 'left';
- if (card.version == 'cartoony') {
- barImageName = 'cflavor';
- barWidth = scaleWidth(0.8547);
- barHeight = scaleHeight(0.0458);
- barDistance = -0.23;
- newLineSpacing = textSize * -0.23;
- textSize -= scaleHeight(0.0086);
- }
- lineContext.drawImage(getManaSymbol(barImageName).image, canvasMargin + (textWidth - barWidth) / 2, canvasMargin + barDistance * textSize, barWidth, barHeight);
- } else if (possibleCode == 'i') {
- if (textFont == 'gilllsans' || textFont == 'neosans') {
- textFontExtension = 'italic';
- } else if (textFont == 'mplantin') {
- textFontExtension = 'i';
- textFontStyle = textFontStyle.replace('italic ', '');
- } else {
- textFontExtension = '';
- if (!textFontStyle.includes('italic')) {textFontStyle += 'italic ';}
- }
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- } else if (possibleCode == '/i') {
- textFontExtension = '';
- textFontStyle = textFontStyle.replace('italic ', '');
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- } else if (possibleCode == 'bold') {
- if (textFont == 'gillsans') {
- textFontExtension = 'bold';
- } else {
- if (!textFontStyle.includes('bold')) {textFontStyle += 'bold ';}
- }
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- } else if (possibleCode == '/bold') {
- if (textFont == 'gillsans') {
- textFontExtension = '';
- } else {
- textFontStyle = textFontStyle.replace('bold ', '');
- }
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- } else if (possibleCode == 'left') {
- textAlign = 'left';
- } else if (possibleCode == 'center') {
- textAlign = 'center';
- } else if (possibleCode == 'right') {
- textAlign = 'right';
- } else if (possibleCode == 'justify-left') {
- textJustify = 'left';
- } else if (possibleCode == 'justify-center') {
- textJustify = 'center';
- } else if (possibleCode == 'justify-right') {
- textJustify = 'right';
- } else if (possibleCode.includes('conditionalcolor')) {
- var codeParams = possibleCode.split(":");
- for (var eligibleFrame of codeParams[1].split(",")) {
- eligibleFrame = eligibleFrame.replace(/_/g, " ");
- if (card.frames.findIndex(element => element.name.toLowerCase().includes(eligibleFrame)) != -1) {
- textColor = codeParams[2];
- lineContext.fillStyle = textColor;
- }
- }
- } else if (possibleCode.includes('fontcolor')) {
- textColor = possibleCode.replace('fontcolor', '');
- lineContext.fillStyle = textColor;
- } else if (possibleCode.includes('fontsize')) {
- if (possibleCode.slice(-2) === "pt") {
- textSize = (parseInt(possibleCode.replace('fontsize', '').replace('pt', '')) * 600 / 72) || 0;
- } else {
- textSize += parseInt(possibleCode.replace('fontsize', '')) || 0;
- }
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- } else if (possibleCode.includes('font') || savedFont) {
- textFont = word.replace('{font', '').replace('}', '');
- if (savedFont) {
- textFont = savedFont;
- wordToWrite = word;
- }
- textFontExtension = '';
- textFontStyle = '';
- lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
- savedFont = null;
- } else if (possibleCode.includes('outlinecolor')) {
- lineContext.strokeStyle = possibleCode.replace('outlinecolor', '');
- } else if (possibleCode.includes('outline')) {
- textOutlineWidth = parseInt(possibleCode.replace('outline', ''));
- lineContext.lineWidth = textOutlineWidth;
- } else if (possibleCode.includes('upinline')) {
- lineY -= parseInt(possibleCode.replace('upinline', '')) || 0;
- } else if (possibleCode.substring(0, 2) == 'up' && possibleCode != 'up') {
- currentY -= parseInt(possibleCode.replace('up', '')) || 0;
- } else if (possibleCode.includes('down')) {
- currentY += parseInt(possibleCode.replace('down', '')) || 0;
- } else if (possibleCode.includes('left')) {
- currentX -= parseInt(possibleCode.replace('left', '')) || 0;
- } else if (possibleCode.includes('right')) {
- currentX += parseInt(possibleCode.replace('right', '')) || 0;
- } else if (possibleCode.includes('shadow')) {
- if (possibleCode.includes('color')) {
- textShadowColor = possibleCode.replace('shadowcolor', '');
- lineContext.shadowColor = textShadowColor;
- } else if (possibleCode.includes('blur')) {
- textShadowBlur = parseInt(possibleCode.replace('shadowblur', '')) || 0;
- lineContext.shadowBlur = textShadowBlur
- } else if (possibleCode.includes('shadowx')) {
- textShadowOffsetX = parseInt(possibleCode.replace('shadowx', '')) || 0;
- lineContext.shadowOffsetX = textShadowOffsetX;
- } else if (possibleCode.includes('shadowy')) {
- textShadowOffsetY = parseInt(possibleCode.replace('shadowy', '')) || 0;
- lineContext.shadowOffsetY = textShadowOffsetY;
- } else {
- textShadowOffsetX = parseInt(possibleCode.replace('shadow', '')) || 0;
- textShadowOffsetY = textShadowOffsetX;
- lineContext.shadowOffsetX = textShadowOffsetX;
- lineContext.shadowOffsetY = textShadowOffsetY;
- }
- } else if (possibleCode == 'planechase') {
- var planechaseHeight = textSize * 1.8;
- lineContext.drawImage(getManaSymbol('chaos').image, currentX + canvasMargin, canvasMargin, planechaseHeight * 1.2, planechaseHeight);
- currentX += planechaseHeight * 1.3;
- startingCurrentX += planechaseHeight * 1.3;
- } else if (possibleCode == 'indent') {
- startingCurrentX += currentX;
- currentY -= 10;
- } else if (possibleCode == '/indent') {
- startingCurrentX = 0;
- } else if (possibleCode.includes('elemid')) {
- if (document.querySelector('#' + word.replace('{elemid', '').replace('}', ''))) {
- wordToWrite = document.querySelector('#' + word.replace('{elemid', '').replace('}', '')).value || '';
- }
- if (word.includes('set')) {
- var bottomTextSubstring = card.bottomInfo.midLeft.text.substring(0, card.bottomInfo.midLeft.text.indexOf(' {savex}')).replace('{elemidinfo-set}', document.querySelector('#info-set').value || '').replace('{elemidinfo-language}', document.querySelector('#info-language').value || '');
- justifyWidth = lineContext.measureText(bottomTextSubstring).width;
- } else if (word.includes('number') && wordToWrite.includes('/') && card.version != 'pokemon') {
- fillJustify = true;
- wordToWrite = Array.from(wordToWrite).join(' ');
- }
- } else if (possibleCode == 'savex') {
- savedTextXPosition = currentX;
- } else if (possibleCode == 'loadx') {
- if (savedTextXPosition > currentX) {
- currentX = savedTextXPosition;
- }
- } else if (possibleCode == 'savex2') {
- savedTextXPosition2 = currentX;
- } else if (possibleCode == 'loadx2') {
- if (savedTextXPosition2 > currentX) {
- currentX = savedTextXPosition2;
- }
- } else if (possibleCode.includes('ptshift')) {
- if (card.frames.findIndex(element => element.name.toLowerCase().includes('power/toughness')) >= 0 || card.version.includes('planeswalker') || ['commanderLegends', 'm21', 'mysticalArchive', 'customDualLands', 'feuerAmeiseKaldheim'].includes(card.version)) {
- ptShift[0] = scaleWidth(parseFloat(possibleCode.replace('ptshift', '').split(',')[0]));
- ptShift[1] = scaleHeight(parseFloat(possibleCode.split(',')[1]));
- }
- } else if (possibleCode.includes('rollcolor')) {
- savedRollColor = possibleCode.replace('rollcolor', '') || 'black';
- } else if (possibleCode.includes('roll')) {
- drawTextBetweenFrames = true;
- redrawFrames = true;
- drawToPrePTCanvas = true;
- if (savedRollYPosition == null) {
- savedRollYPosition = currentY;
- } else {
- savedRollYPosition = -1;
- }
- savedFont = textFont;
- lineContext.font = textFontStyle + textSize + 'px ' + 'belerenb' + textFontExtension;
- wordToWrite = possibleCode.replace('roll', '');
- } else if (possibleCode.includes('permashift')) {
- permaShift = [parseFloat(possibleCode.replace('permashift', '').split(',')[0]), parseFloat(possibleCode.split(',')[1])];
- } else if (possibleCode.includes('arcradius')) {
- textArcRadius = parseInt(possibleCode.replace('arcradius', '')) || 0;
- } else if (possibleCode.includes('arcstart')) {
- textArcStart = parseFloat(possibleCode.replace('arcstart', '')) || 0;
- } else if (possibleCode.includes('rotate')) {
- textRotation = parseInt(possibleCode.replace('rotate', '')) % 360;
- } else if (possibleCode === 'manacolordefault') {
- manaSymbolColor = null;
- } else if (possibleCode.includes('manacolor')) {
- manaSymbolColor = possibleCode.replace('manacolor', '') || 'white';
- } else if (possibleCode.includes('fixtextalign')) {
- textAlign = realTextAlign;
- } else if (possibleCode.includes('kerning')) {
- lineContext.letterSpacing = possibleCode.replace('kerning', '') + 'px';
- lineContext.font = lineContext.font; //necessary for the letterspacing update to be recognized
- } else if (getManaSymbol(possibleCode.replaceAll('/', '')) != undefined || getManaSymbol(possibleCode.replaceAll('/', '').split('').reverse().join('')) != undefined) {
- possibleCode = possibleCode.replaceAll('/', '')
- var manaSymbol;
- if (textObject.manaPrefix && (getManaSymbol(textObject.manaPrefix + possibleCode) != undefined || getManaSymbol(textObject.manaPrefix + possibleCode.split('').reverse().join('')) != undefined)) {
- manaSymbol = getManaSymbol(textObject.manaPrefix + possibleCode) || getManaSymbol(textObject.manaPrefix + possibleCode.split('').reverse().join(''));
- } else {
- manaSymbol = getManaSymbol(possibleCode) || getManaSymbol(possibleCode.split('').reverse().join(''));
- }
- var manaSymbolSpacing = textSize * 0.04 + textManaSpacing;
- var manaSymbolWidth = manaSymbol.width * textSize * 0.78;
- var manaSymbolHeight = manaSymbol.height * textSize * 0.78;
- var manaSymbolX = currentX + canvasMargin + manaSymbolSpacing;
- var manaSymbolY = canvasMargin + textSize * 0.34 - manaSymbolHeight / 2;
- if (textObject.manaPlacement) {
- manaSymbolX = scaleWidth(textObject.manaPlacement.x[manaPlacementCounter] || 0) + canvasMargin;
- manaSymbolY = canvasMargin;
- currentY = scaleHeight(textObject.manaPlacement.y[manaPlacementCounter] || 0);
- manaPlacementCounter ++;
- newLine = true;
- } else if (textObject.manaLayout) {
- var layoutOption = 0;
- var manaSymbolCount = splitText.length - 1;
- while (textObject.manaLayout[layoutOption].max < manaSymbolCount && layoutOption < textObject.manaLayout.length - 1) {
- layoutOption ++;
- }
- var manaLayout = textObject.manaLayout[layoutOption];
- if (manaLayout.pos[manaPlacementCounter] == undefined) {
- manaLayout.pos[manaPlacementCounter] = [0, 0];
- }
- manaSymbolX = scaleWidth(manaLayout.pos[manaPlacementCounter][0] || 0) + canvasMargin;
- manaSymbolY = canvasMargin;
- currentY = scaleHeight(manaLayout.pos[manaPlacementCounter][1] || 0);
- manaPlacementCounter ++;
- manaSymbolWidth *= manaLayout.size;
- manaSymbolHeight *= manaLayout.size;
- newLine = true;
- }
- if (textObject.manaImageScale) {
- currentX -= (textObject.manaImageScale - 1) * manaSymbolWidth;
- manaSymbolX -= (textObject.manaImageScale - 1) / 2 * manaSymbolWidth;
- manaSymbolY -= (textObject.manaImageScale - 1) / 2 * manaSymbolHeight;
- manaSymbolWidth *= textObject.manaImageScale;
- manaSymbolHeight *= textObject.manaImageScale;
- }
- //fake shadow begins
- var fakeShadow = lineCanvas.cloneNode();
- var fakeShadowContext = fakeShadow.getContext('2d');
- fakeShadowContext.clearRect(0, 0, fakeShadow.width, fakeShadow.height);
- var backImage = null;
- if (manaSymbol.backs) {
- backImage = getManaSymbol('back' + Math.floor(Math.random() * manaSymbol.backs) + manaSymbol.back).image;
- }
- if (textArcRadius > 0) {
- if (manaSymbol.backs) {
- fakeShadowContext.drawImageArc(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
- }
- fakeShadowContext.drawImageArc(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
- } else if (manaSymbolColor) {
- fakeShadowContext.fillImage(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, manaSymbolColor);
- } else {
- if (manaSymbol.backs) {
- fakeShadowContext.drawImage(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
- }
- fakeShadowContext.drawImage(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
- }
- lineContext.drawImage(fakeShadow, 0, 0);
- //fake shadow ends (thanks, safari)
- currentX += manaSymbolWidth + manaSymbolSpacing * 2;
- } else {
- wordToWrite = word;
- }
- }
-
- if (wordToWrite && lineContext.font.endsWith('belerenb')) {
- wordToWrite = wordToWrite.replace(/f(?:\s|$)/g, '\ue006').replace(/h(?:\s|$)/g, '\ue007').replace(/m(?:\s|$)/g, '\ue008').replace(/n(?:\s|$)/g, '\ue009').replace(/k(?:\s|$)/g, '\ue00a');
- }
-
- //if the word goes past the max line width, go to the next line
- if (wordToWrite && lineContext.measureText(wordToWrite).width + currentX >= textWidth && textArcRadius == 0) {
- if (textOneLine && startingTextSize > 1) {
- //doesn't fit... try again at a smaller text size?
- startingTextSize -= 1;
- continue outerloop;
- }
- newLine = true;
- }
- //if we need a new line, go to the next line
- if ((newLine && !textOneLine) || splitText.indexOf(word) == splitText.length - 1) {
- var horizontalAdjust = 0
- if (textAlign == 'center') {
- horizontalAdjust = (textWidth - currentX) / 2;
- } else if (textAlign == 'right') {
- horizontalAdjust = textWidth - currentX;
- }
- if (currentX > widestLineWidth) {
- widestLineWidth = currentX;
- }
- paragraphContext.drawImage(lineCanvas, horizontalAdjust, currentY);
- lineY = 0;
- lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
- // boxes for 'roll a d20' cards
- if (savedRollYPosition != null && (newLineSpacing != 0 || !(newLine && !textOneLine))) {
- if (savedRollYPosition != -1) {
- paragraphContext.globalCompositeOperation = 'destination-over';
- paragraphContext.globalAlpha = 0.25;
- paragraphContext.fillStyle = savedRollColor;
- paragraphContext.fillRect(canvasMargin - textSize * 0.1, savedRollYPosition + canvasMargin - textSize * 0.28, paragraphCanvas.width - 2 * canvasMargin + textSize * 0.2, currentY - savedRollYPosition + textSize * 1.3);
- paragraphContext.globalCompositeOperation = 'source-over';
- paragraphContext.globalAlpha = 1;
- savedRollYPosition = -1;
- } else {
- savedRollYPosition = null;
- }
- }
- //reset
- currentX = startingCurrentX;
- currentY += textSize + newLineSpacing;
- newLineSpacing = (textObject.lineSpacing || 0) * textSize;
- newLine = false;
- }
- //if there's a word to write, it's not a space on a new line, and it's allowed to write words, then we write the word
- if (wordToWrite && (currentX != startingCurrentX || wordToWrite != ' ') && !textManaCost) {
- var justifySettings = {
- maxSpaceSize: 6,
- minSpaceSize: 0
- };
-
- if (textArcRadius > 0) {
- lineContext.fillTextArc(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, textArcRadius, textArcStart, currentX, textOutlineWidth);
- } else {
- if (textOutlineWidth >= 1) {
- if (fillJustify) {
- lineContext.strokeJustifyText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, justifyWidth, justifySettings);
- } else {
- lineContext.strokeText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
- }
- }
- if (fillJustify) {
- lineContext.fillJustifyText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, justifyWidth, justifySettings);
- } else {
- lineContext.fillText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
- }
- }
-
- if (fillJustify) {
- currentX += lineContext.measureJustifiedText(wordToWrite, justifyWidth, justifySettings);
- } else {
- currentX += lineContext.measureText(wordToWrite).width;
- }
- }
- if (currentY > textHeight && textBounded && !textOneLine && startingTextSize > 1 && textArcRadius == 0) {
- //doesn't fit... try again at a smaller text size?
- startingTextSize -= 1;
- continue outerloop;
- }
- if (splitText.indexOf(word) == splitText.length - 1) {
- //should manage vertical centering here
- var verticalAdjust = 0;
- if (!textObject.noVerticalCenter) {
- verticalAdjust = (textHeight - currentY + textSize * 0.15) / 2;
- }
- var finalHorizontalAdjust = 0;
- const horizontalAdjustUnit = (textWidth - widestLineWidth) / 2;
- if (textJustify == 'right' && textAlign != 'right') {
- finalHorizontalAdjust = 2 * horizontalAdjustUnit;
- if (textAlign == 'center') {
- finalHorizontalAdjust = horizontalAdjustUnit;
- }
- } else if (textJustify == 'center' && textAlign != 'center') {
- finalHorizontalAdjust = horizontalAdjustUnit;
- if (textAlign == 'right') {
- finalHorizontalAdjust = - horizontalAdjustUnit;
- }
- }
- var trueTargetContext = targetContext;
- if (drawToPrePTCanvas) {
- trueTargetContext = prePTContext;
- }
- if (textRotation) {
- trueTargetContext.save();
- trueTargetContext
- const shapeX = textX + ptShift[0];
- const shapeY = textY + ptShift[1];
- trueTargetContext.translate(shapeX, shapeY);
- trueTargetContext.rotate(Math.PI * textRotation / 180);
- trueTargetContext.drawImage(paragraphCanvas, permaShift[0] - canvasMargin + finalHorizontalAdjust, verticalAdjust - canvasMargin + permaShift[1]);
- trueTargetContext.restore();
- } else {
- trueTargetContext.drawImage(paragraphCanvas, textX - canvasMargin + ptShift[0] + permaShift[0] + finalHorizontalAdjust, textY - canvasMargin + verticalAdjust + ptShift[1] + permaShift[1]);
- }
- drawingText = false;
- }
- }
- }
-}
-CanvasRenderingContext2D.prototype.fillTextArc = function(text, x, y, radius, startRotation, distance = 0, outlineWidth = 0) {
- this.save();
- this.translate(x - distance + scaleWidth(0.5), y + radius);
- this.rotate(startRotation + widthToAngle(distance, radius));
- for (var i = 0; i < text.length; i++) {
- var letter = text[i];
- if (outlineWidth >= 1) {
- this.strokeText(letter, 0, -radius);
- }
- this.fillText(letter, 0, -radius);
- this.rotate(widthToAngle(this.measureText(letter).width, radius));
- }
- this.restore();
-}
-CanvasRenderingContext2D.prototype.drawImageArc = function(image, x, y, width, height, radius, startRotation, distance = 0) {
- this.save();
- this.translate(x - distance + scaleWidth(0.5), y + radius);
- this.rotate(startRotation + widthToAngle(distance, radius));
- this.drawImage(image, 0, -radius, width, height);
- this.restore();
-}
-CanvasRenderingContext2D.prototype.fillImage = function(image, x, y, width, height, color = 'white', margin = 10) {
- var canvas = document.createElement('canvas');
- canvas.width = width + margin * 2;
- canvas.height = height + margin * 2;
- var context = canvas.getContext('2d');
- context.drawImage(image, margin, margin, width, height);
- context.globalCompositeOperation = 'source-in';
- context.fillStyle = pinlineColors(color);
- context.fillRect(0, 0, width + margin * 2, height + margin * 2);
- this.drawImage(canvas, x - margin, y - margin, width + margin * 2, height + margin * 2);
-}
-
-const FILL = 0; //const to indicate filltext render
-const STROKE = 1;
-const MEASURE = 2;
-var maxSpaceSize = 3; // Multiplier for max space size. If greater then no justification applied
-var minSpaceSize = 0.5; // Multiplier for minimum space size
-function renderTextJustified(ctx, text, x, y, width, renderType) {
- var splitChar = " ";
-
- var words, wordsWidth, count, spaces, spaceWidth, adjSpace, renderer, i, textAlign, useSize, totalWidth;
- textAlign = ctx.textAlign;
- ctx.textAlign = "left";
- wordsWidth = 0;
- words = text.split(splitChar).map(word => {
- var w = ctx.measureText(word).width;
- wordsWidth += w;
- return {
- width: w,
- word: word
- };
- });
- // count = num words, spaces = number spaces, spaceWidth normal space size
- // adjSpace new space size >= min size. useSize Reslting space size used to render
- count = words.length;
- spaces = count - 1;
- spaceWidth = ctx.measureText(splitChar).width;
- adjSpace = Math.max(spaceWidth * minSpaceSize, (width - wordsWidth) / spaces);
- useSize = adjSpace > spaceWidth * maxSpaceSize ? spaceWidth : adjSpace;
- totalWidth = wordsWidth + useSize * spaces;
- if (renderType === MEASURE) { // if measuring return size
- ctx.textAlign = textAlign;
- return totalWidth;
- }
- renderer = renderType === FILL ? ctx.fillText.bind(ctx) : ctx.strokeText.bind(ctx); // fill or stroke
- switch(textAlign) {
- case "right":
- x -= totalWidth;
- break;
- case "end":
- x += width - totalWidth;
- break;
- case "center": // intentional fall through to default
- x -= totalWidth / 2;
- default:
- }
- if (useSize === spaceWidth) { // if space size unchanged
- renderer(text, x, y);
- } else {
- for(i = 0; i < count; i += 1) {
- renderer(words[i].word,x,y);
- x += words[i].width;
- x += useSize;
- }
- }
- ctx.textAlign = textAlign;
-}
-
-// Parse vet and set settings object.
-function justifiedTextSettings(settings) {
- var min,max;
- var vetNumber = (num, defaultNum) => {
- num = num !== null && num !== null && !isNaN(num) ? num : defaultNum;
- if(num < 0){
- num = defaultNum;
- }
- return num;
- }
- if(settings === undefined || settings === null){
- return;
- }
- max = vetNumber(settings.maxSpaceSize, maxSpaceSize);
- min = vetNumber(settings.minSpaceSize, minSpaceSize);
- if(min > max){
- return;
- }
- minSpaceSize = min;
- maxSpaceSize = max;
-}
-CanvasRenderingContext2D.prototype.fillJustifyText = function(text, x, y, width, settings) {
- justifiedTextSettings(settings);
- renderTextJustified(this, text, x, y, width, FILL);
-}
-CanvasRenderingContext2D.prototype.strokeJustifyText = function(text, x, y, width, settings){
- justifiedTextSettings(settings);
- renderTextJustified(this, text, x, y, width, STROKE);
-}
-CanvasRenderingContext2D.prototype.measureJustifiedText = function(text, width, settings) {
- justifiedTextSettings(settings);
- renderTextJustified(this, text, 0, 0, width, MEASURE);
-}
-
-function widthToAngle(width, radius) {
- return width / radius;
-}
-function curlyQuotes(input) {
- return input.replace(/ '/g, ' ‘').replace(/^'/, '‘').replace(/'/g, '’').replace(/ "/g, ' “').replace(/" /g, '” ').replace(/\."/, '.”').replace(/"$/, '”').replace(/"\)/g, '”)').replace(/"/g, '“');
-}
-function pinlineColors(color) {
- return color.replace('white', '#fcfeff').replace('blue', '#0075be').replace('black', '#272624').replace('red', '#ef3827').replace('green', '#007b43')
-}
-async function addTextbox(textboxType) {
- if (textboxType == 'Nickname' && !card.text.nickname && card.text.title) {
- await loadTextOptions({nickname: {name:'Nickname', text:card.text.title.text, x:0.14, y:0.1129, width:0.72, height:0.0243, oneLine:true, font:'mplantini', size:0.0229, color:'white', shadowX:0.0014, shadowY:0.001, align:'center'}}, false);
- var nickname = card.text.title;
- nickname.name = 'Nickname';
- card.text.title = card.text.nickname;
- card.text.title.name = 'Title';
- card.text.nickname = nickname;
- } else if (textboxType == 'Power/Toughness' && !card.text.pt) {
- loadTextOptions({pt: {name:'Power/Toughness', text:'', x:0.7928, y:0.902, width:0.1367, height:0.0372, size:0.0372, font:'belerenbsc', oneLine:true, align:'center'}}, false);
- } else if (textboxType == 'DateStamp' && !card.text.dateStamp) {
- loadTextOptions({dateStamp: {name:'Date Stamp', text:'', x:0.11, y:0.5072, width:0.78, height:0.0286, size:0.0286, font:'belerenb', oneLine:true, align:'right', color:'#ffd35b', shadowX:-0.0007, shadowY:-0.001}}, false);
- }
-}
-//ART TAB
-function uploadArt(imageSource, otherParams) {
- art.src = imageSource;
- if (otherParams && otherParams == 'autoFit') {
- art.onload = function() {
- autoFitArt();
- art.onload = artEdited;
- };
- }
-}
-function artEdited() {
- card.artSource = art.src;
- card.artX = document.querySelector('#art-x').value / card.width;
- card.artY = document.querySelector('#art-y').value / card.height;
- card.artZoom = document.querySelector('#art-zoom').value / 100;
- card.artRotate = document.querySelector('#art-rotate').value;
- drawCard();
-}
-function autoFitArt() {
- document.querySelector('#art-rotate').value = 0;
- if (art.width / art.height > scaleWidth(card.artBounds.width) / scaleHeight(card.artBounds.height)) {
- document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - scaleHeight(card.marginY));
- document.querySelector('#art-zoom').value = (scaleHeight(card.artBounds.height) / art.height * 100).toFixed(1);
- document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - (document.querySelector('#art-zoom').value / 100 * art.width - scaleWidth(card.artBounds.width)) / 2 - scaleWidth(card.marginX));
- } else {
- document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - scaleWidth(card.marginX));
- document.querySelector('#art-zoom').value = (scaleWidth(card.artBounds.width) / art.width * 100).toFixed(1);
- document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - (document.querySelector('#art-zoom').value / 100 * art.height - scaleHeight(card.artBounds.height)) / 2 - scaleHeight(card.marginY));
- }
- artEdited();
-}
-
-function centerArtX() {
- document.querySelector('#art-rotate').value = 0;
- if (art.width / art.height > scaleWidth(card.artBounds.width) / scaleHeight(card.artBounds.height)) {
- document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - (document.querySelector('#art-zoom').value / 100 * art.width - scaleWidth(card.artBounds.width)) / 2 - scaleWidth(card.marginX));
- } else {
- document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - scaleWidth(card.marginX));
- }
- artEdited();
-}
-
-function centerArtY() {
- document.querySelector('#art-rotate').value = 0;
- document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - (document.querySelector('#art-zoom').value / 100 * art.height - scaleHeight(card.artBounds.height)) / 2 - scaleHeight(card.marginY));
- artEdited();
-}
-
-function artFromScryfall(scryfallResponse) {
- scryfallArt = []
- const artIndex = document.querySelector('#art-index');
- artIndex.innerHTML = null;
- var optionIndex = 0;
- scryfallResponse.forEach(card => {
- if (card.image_uris && (card.object == 'card' || card.type_line != 'Card') && card.artist) {
- scryfallArt.push(card);
- var option = document.createElement('option');
- option.innerHTML = `${card.name} (${card.set.toUpperCase()} - ${card.artist})`;
- option.value = optionIndex;
- artIndex.appendChild(option);
- optionIndex ++;
- }
- });
-
- if (document.querySelector('#importAllPrints').checked) {
- // If importing unique prints, the art should change to match the unique print selected.
-
- // First we find the illustration ID of the imported print
- var illustrationID = scryfallCard[document.querySelector('#import-index').value].illustration_id;
-
- // Find all unique arts for that card
- var artIllustrations = scryfallArt.map(card => card.illustration_id);
-
- // Find the art that matches the selected print
- var index = artIllustrations.indexOf(illustrationID);
- if (index < 0) {
- // Couldn't find art
- index = 0;
- }
-
- // Use that art
- artIndex.value = index;
- }
-
- changeArtIndex();
-}
-function changeArtIndex() {
- const artIndexValue = document.querySelector('#art-index').value;
- if (artIndexValue != 0 || artIndexValue == '0') {
- const scryfallCardForArt = scryfallArt[artIndexValue];
- uploadArt(scryfallCardForArt.image_uris.art_crop, 'autoFit');
- artistEdited(scryfallCardForArt.artist);
- if (params.get('mtgpics') != null) {
- imageURL(`https://www.mtgpics.com/pics/art/${scryfallCardForArt.set.toLowerCase()}/${("00" + scryfallCardForArt.collector_number).slice(-3)}.jpg`, tryMTGPicsArt);
- }
- }
-}
-function tryMTGPicsArt(src) {
- var attemptedImage = new Image();
- attemptedImage.onload = function() {
- if (this.complete) {
- art.onload = function() {
- autoFitArt();
- art.onload = artEdited;
- };
- art.src = this.src;
- }
- }
- attemptedImage.src = src;
-}
-function initDraggableArt() {
- previewCanvas.onmousedown = artStartDrag;
- previewCanvas.onmousemove = artDrag;
- previewCanvas.onmouseout = artStopDrag;
- previewCanvas.onmouseup = artStopDrag;
- draggingArt = false;
- lastArtDragTime = 0;
-}
-function artStartDrag(e) {
- e.preventDefault();
- e.stopPropagation();
- startX = parseInt(e.clientX);
- startY = parseInt(e.clientY);
- draggingArt = true;
-}
-function artDrag(e) {
- e.preventDefault();
- e.stopPropagation();
- if (draggingArt && Date.now() > lastArtDragTime + 25) {
- lastArtDragTime = Date.now();
- if (e.shiftKey || e.ctrlKey) {
- startX = parseInt(e.clientX);
- const endY = parseInt(e.clientY);
- if (e.ctrlKey) {
- document.querySelector('#art-rotate').value = Math.round((parseFloat(document.querySelector('#art-rotate').value) - (startY - endY) / 10) % 360 * 10) / 10;
- } else {
- document.querySelector('#art-zoom').value = Math.round((parseFloat(document.querySelector('#art-zoom').value) * (1.002 ** (startY - endY))) * 10) / 10;
- }
- startY = endY;
- artEdited();
- } else {
- const endX = parseInt(e.clientX);
- const endY = parseInt(e.clientY);
- var changeX = (endX - startX) * 2;
- var changeY = (endY - startY) * 2;
- if (card.landscape) {
- const temp = changeX;
- changeX = -changeY;
- changeY = temp;
- }
- document.querySelector('#art-x').value = parseInt(document.querySelector('#art-x').value) + changeX;
- document.querySelector('#art-y').value = parseInt(document.querySelector('#art-y').value) + changeY;
- startX = endX;
- startY = endY;
- artEdited();
- }
-
- }
-}
-function artStopDrag(e) {
- e.preventDefault();
- e.stopPropagation();
- if (draggingArt) {
- draggingArt = false;
- }
-}
-//SET SYMBOL TAB
-function uploadSetSymbol(imageSource, otherParams) {
- setSymbol.src = imageSource;
- if (otherParams && otherParams == 'resetSetSymbol') {
- setSymbol.onload = function() {
- resetSetSymbol();
- setSymbol.onload = setSymbolEdited;
- };
- }
-}
-function setSymbolEdited() {
- card.setSymbolSource = setSymbol.src;
- if (document.querySelector('#lockSetSymbolURL').checked) {
- localStorage.setItem('lockSetSymbolURL', card.setSymbolSource);
- }
- localStorage.setItem('set-symbol-source', document.querySelector('#set-symbol-source').value);
- card.setSymbolX = document.querySelector('#setSymbol-x').value / card.width;
- card.setSymbolY = document.querySelector('#setSymbol-y').value / card.height;
- card.setSymbolZoom = document.querySelector('#setSymbol-zoom').value / 100;
- drawCard();
-}
-function resetSetSymbol() {
- if (card.setSymbolBounds == undefined) {
- return;
- }
- document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x));
- document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y));
- var setSymbolZoom;
- if (setSymbol.width / setSymbol.height > scaleWidth(card.setSymbolBounds.width) / scaleHeight(card.setSymbolBounds.height)) {
- setSymbolZoom = (scaleWidth(card.setSymbolBounds.width) / setSymbol.width * 100).toFixed(1);
- } else {
- setSymbolZoom = (scaleHeight(card.setSymbolBounds.height) / setSymbol.height * 100).toFixed(1);
- }
- document.querySelector('#setSymbol-zoom').value = setSymbolZoom;
- if (card.setSymbolBounds.horizontal == 'center') {
- document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) / 2 - scaleWidth(card.marginX));
- } else if (card.setSymbolBounds.horizontal == 'right') {
- document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) - scaleWidth(card.marginX));
- }
- if (card.setSymbolBounds.vertical == 'center') {
- document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) / 2 - scaleHeight(card.marginY));
- } else if (card.setSymbolBounds.vertical == 'bottom') {
- document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) - scaleHeight(card.marginY));
- }
- setSymbolEdited();
-}
-function fetchSetSymbol() {
- var setCode = document.querySelector('#set-symbol-code').value.toLowerCase() || 'cmd';
- if (document.querySelector('#lockSetSymbolCode').checked) {
- localStorage.setItem('lockSetSymbolCode', setCode);
- }
- var setRarity = document.querySelector('#set-symbol-rarity').value.toLowerCase().replace('uncommon', 'u').replace('common', 'c').replace('rare', 'r').replace('mythic', 'm') || 'c';
- if (['sld', 'a22', 'a23', 'j22'].includes(setCode.toLowerCase())) {
- uploadSetSymbol(fixUri(`/img/setSymbols/custom/${setCode.toLowerCase()}-${setRarity}.png`), 'resetSetSymbol');
- } else if (['cc', 'logan', 'joe'].includes(setCode.toLowerCase())) {
- uploadSetSymbol(fixUri(`/img/setSymbols/custom/${setCode.toLowerCase()}-${setRarity}.svg`), 'resetSetSymbol');
- } else if (document.querySelector("#set-symbol-source").value == 'gatherer') {
- if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
- uploadSetSymbol('http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=' + setCode + '&size=large&rarity=' + setRarity, 'resetSetSymbol');
- } else if (document.querySelector("#set-symbol-source").value == 'hexproof') {
- if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
- uploadSetSymbol('https://api.hexproof.io/symbols/set/' + setCode + '/' + setRarity, 'resetSetSymbol');
- } else {
- var extension = 'svg';
- if (['moc', 'ltr', 'ltc', 'cmm', 'who', 'scd', 'woe', 'wot', 'woc', 'lci', 'lcc', 'mkm', 'mkc', 'otj', 'otc'].includes(setCode.toLowerCase())) {
- extension = 'png';
- }
- if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
- uploadSetSymbol(fixUri(`/img/setSymbols/official/${setCode.toLowerCase()}-${setRarity}.` + extension), 'resetSetSymbol');
- }
-}
-function lockSetSymbolCode() {
- var savedValue = '';
- if (document.querySelector('#lockSetSymbolCode').checked) {
- savedValue = document.querySelector('#set-symbol-code').value;
- }
- localStorage.setItem('lockSetSymbolCode', savedValue);
-}
-function lockSetSymbolURL() {
- var savedValue = '';
- if (document.querySelector('#lockSetSymbolURL').checked) {
- savedValue = card.setSymbolSource;
- }
- localStorage.setItem('lockSetSymbolURL', savedValue);
-}
-//WATERMARK TAB
-function uploadWatermark(imageSource, otherParams) {
- watermark.src = imageSource;
- if (otherParams && otherParams == 'resetWatermark') {
- watermark.onload = function() {
- resetWatermark();
- watermark.onload = watermarkEdited;
- };
- }
-}
-function watermarkLeftColor(c) {
- card.watermarkLeft = c;
- watermarkEdited();
-}
-function watermarkRightColor(c) {
- card.watermarkRight = c;
- watermarkEdited();
-}
-function watermarkEdited() {
- card.watermarkSource = watermark.src;
- card.watermarkX = document.querySelector('#watermark-x').value / card.width;
- card.watermarkY = document.querySelector('#watermark-y').value / card.height;
- card.watermarkZoom = document.querySelector('#watermark-zoom').value / 100;
- if (card.watermarkLeft == "none" && document.querySelector('#watermark-left').value != "none") {
- card.watermarkLeft = document.querySelector('#watermark-left').value;
- }
- // card.watermarkLeft = document.querySelector('#watermark-left').value;
- // card.watermarkRight = document.querySelector('#watermark-right').value;
- card.watermarkOpacity = document.querySelector('#watermark-opacity').value / 100;
- watermarkContext.globalCompositeOperation = 'source-over';
- watermarkContext.globalAlpha = 1;
- watermarkContext.clearRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
- if (card.watermarkLeft != 'none' && !card.watermarkSource.includes('/blank.png') && card.watermarkZoom > 0) {
- if (card.watermarkRight != 'none') {
- watermarkContext.drawImage(right, scaleX(0), scaleY(0), scaleWidth(1), scaleHeight(1));
- watermarkContext.globalCompositeOperation = 'source-in';
- if (card.watermarkRight == 'default') {
- watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
- } else {
- watermarkContext.fillStyle = card.watermarkRight;
- watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
- }
- watermarkContext.globalCompositeOperation = 'destination-over';
- }
- if (card.watermarkLeft == 'default') {
- watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
- } else {
- watermarkContext.fillStyle = card.watermarkLeft;
- watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
- }
- watermarkContext.globalCompositeOperation = 'destination-in';
- watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
- watermarkContext.globalAlpha = card.watermarkOpacity;
- watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
- }
- drawCard();
-}
-function resetWatermark() {
- var watermarkZoom;
- if (watermark.width / watermark.height > scaleWidth(card.watermarkBounds.width) / scaleHeight(card.watermarkBounds.height)) {
- watermarkZoom = (scaleWidth(card.watermarkBounds.width) / watermark.width * 100).toFixed(1);
- } else {
- watermarkZoom = (scaleHeight(card.watermarkBounds.height) / watermark.height * 100).toFixed(1);
- }
- document.querySelector('#watermark-zoom').value = watermarkZoom;
- document.querySelector('#watermark-x').value = Math.round(scaleX(card.watermarkBounds.x) - watermark.width * watermarkZoom / 200 - scaleWidth(card.marginX));
- document.querySelector('#watermark-y').value = Math.round(scaleY(card.watermarkBounds.y) - watermark.height * watermarkZoom / 200 - scaleHeight(card.marginY));
- watermarkEdited();
-}
-//svg cropper
-function getSetSymbolWatermark(url, targetImage = watermark) {
- if (!url.includes('/')) {
- url = 'https://cdn.jsdelivr.net/npm/keyrune/svg/' + url + '.svg';
- }
- xhttp = new XMLHttpRequest();
- xhttp.open('GET', url, true);
- xhttp.overrideMimeType('image/svg+xml');
- xhttp.onload = function(event) {
- if (this.readyState == 4 && this.status == 200) {
- var svg = document.body.appendChild(xhttp.responseXML.documentElement);
- var box = svg.getBBox(svg);
- svg.setAttribute('viewBox', [box.x, box.y, box.width, box.height].join(' '));
- svg.setAttribute('width', box.width);
- svg.setAttribute('height', box.height);
- uploadWatermark('data:image/svg+xml,' + encodeURIComponent(svg.outerHTML), 'resetWatermark');
- svg.remove();
- } else if (this.status == 404) {
- throw new Error('Improper Set Code');
- }
- }
- xhttp.send();
-}
-//Bottom Info Tab
-async function loadBottomInfo(textObjects = []) {
- await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
- card.bottomInfo = null;
- card.bottomInfo = textObjects;
- await bottomInfoEdited();
- bottomInfoEdited();
-}
-async function bottomInfoEdited() {
- await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
- card.infoNumber = document.querySelector('#info-number').value;
- card.infoRarity = document.querySelector('#info-rarity').value;
- card.infoSet = document.querySelector('#info-set').value;
- card.infoLanguage = document.querySelector('#info-language').value;
- card.infoArtist = document.querySelector('#info-artist').value;
- card.infoYear = document.querySelector('#info-year').value;
- card.infoNote = document.querySelector('#info-note').value;
-
- if (document.querySelector('#enableCollectorInfo').checked) {
- for (var textObject of Object.entries(card.bottomInfo)) {
- if (["NOT FOR SALE", "Wizards of the Coast", "CardConjurer.com", "cardconjurer.com"].some(v => textObject[1].text.includes(v))) {
- continue;
- } else {
- textObject[1].name = textObject[0];
- await writeText(textObject[1], bottomInfoContext);
- }
- continue;
- }
- }
-
- drawCard();
-}
-function artistEdited(value) {
- document.querySelector('#art-artist').value = value;
- document.querySelector('#info-artist').value = value;
- bottomInfoEdited();
-}
-function toggleStarDot() {
- for (var key of Object.keys(card.bottomInfo)) {
- var text = card.bottomInfo[key].text
- if (text.includes('*')) {
- card.bottomInfo[key].text = text.replace('*', ' \u2022 ');
- } else {
- card.bottomInfo[key].text = text.replace(' \u2022 ', '*');
- }
- }
- defaultCollector.starDot = !defaultCollector.starDot;
- bottomInfoEdited();
-}
-function enableNewCollectorInfoStyle() {
- localStorage.setItem('enableNewCollectorStyle', document.querySelector('#enableNewCollectorStyle').checked);
- setBottomInfoStyle();
- bottomInfoEdited();
-}
-function enableCollectorInfo() {
- localStorage.setItem('enableCollectorInfo', document.querySelector('#enableCollectorInfo').checked);
- bottomInfoEdited();
-}
-function enableImportCollectorInfo() {
- localStorage.setItem('enableImportCollectorInfo', document.querySelector('#enableImportCollectorInfo').checked);
-}
-function setAutoFrame() {
- var value = document.querySelector('#autoFrame').value;
- localStorage.setItem('autoFrame', value);
-
- if (value !== 'false') {
- document.querySelector('#autoLoadFrameVersion').checked = true;
- localStorage.setItem('autoLoadFrameVersion', 'true');
- }
-
- autoFrame();
-}
-function setAutofit() {
- localStorage.setItem('autoFit', document.querySelector('#art-update-autofit').checked);
-}
-function removeDefaultCollector() {
- defaultCollector = {}; //{number: year, rarity:'P', setCode:'MTG', lang:'EN', starDot:false};
- localStorage.removeItem('defaultCollector'); //localStorage.setItem('defaultCollector', JSON.stringify(defaultCollector));
-}
-function setDefaultCollector() {
- starDot = defaultCollector.starDot;
- defaultCollector = {
- number: document.querySelector('#info-number').value,
- rarity: document.querySelector('#info-rarity').value,
- setCode: document.querySelector('#info-set').value,
- lang: document.querySelector('#info-language').value,
- note: document.querySelector('#info-note').value,
- starDot: starDot
- };
- localStorage.setItem('defaultCollector', JSON.stringify(defaultCollector));
-}
-//DRAWING THE CARD (putting it all together)
-function drawCard() {
- // reset
- cardContext.globalCompositeOperation = 'source-over';
- cardContext.clearRect(0, 0, cardCanvas.width, cardCanvas.height);
- // art
- cardContext.save();
- cardContext.translate(scaleX(card.artX), scaleY(card.artY));
- cardContext.rotate(Math.PI / 180 * (card.artRotate || 0));
- if (document.querySelector('#grayscale-art').checked) {
- cardContext.filter='grayscale(1)';
- }
- cardContext.drawImage(art, 0, 0, art.width * card.artZoom, art.height * card.artZoom);
- cardContext.restore();
- // frame elements
- if (card.version.includes('planeswalker') && typeof planeswalkerPreFrameCanvas !== "undefined") {
- cardContext.drawImage(planeswalkerPreFrameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- }
- cardContext.drawImage(frameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- if (card.version.toLowerCase().includes('planeswalker') && typeof planeswalkerPostFrameCanvas !== "undefined") {
- cardContext.drawImage(planeswalkerPostFrameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- } else if (card.version.toLowerCase().includes('planeswalker') && typeof planeswalkerCanvas !== "undefined") {
- cardContext.drawImage(planeswalkerCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- } else if (card.version.toLowerCase().includes('qrcode') && typeof qrCodeCanvas !== "undefined") {
- cardContext.drawImage(qrCodeCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- } // REMOVE/DELETE PLANESWALKERCANVAS AFTER A FEW WEEKS
- // guidelines
- if (document.querySelector('#show-guidelines').checked) {
- cardContext.drawImage(guidelinesCanvas, scaleX(card.marginX) / 2, scaleY(card.marginY) / 2, cardCanvas.width, cardCanvas.height);
- }
- // watermark
- cardContext.drawImage(watermarkCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- // custom elements for sagas, classes, and dungeons
- if (card.version.toLowerCase().includes('saga') && typeof sagaCanvas !== "undefined") {
- cardContext.drawImage(sagaCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- } else if (card.version.toLowerCase().includes('class') && typeof classCanvas !== "undefined") {
- cardContext.drawImage(classCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- } else if (card.version.toLowerCase().includes('dungeon') && typeof dungeonCanvas !== "undefined") {
- cardContext.drawImage(dungeonCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- }
- // text
- cardContext.drawImage(textCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- // set symbol
- cardContext.drawImage(setSymbol, scaleX(card.setSymbolX), scaleY(card.setSymbolY), setSymbol.width * card.setSymbolZoom, setSymbol.height * card.setSymbolZoom)
- // bottom info
- if (card.bottomInfoTranslate) {
- cardContext.save();
- cardContext.rotate(Math.PI / 180 * (card.bottomInfoRotate || 0));
- cardContext.translate(card.bottomInfoTranslate.x || 0, card.bottomInfoTranslate.y || 0);
- cardContext.drawImage(bottomInfoCanvas, 0, 0, cardCanvas.width * (card.bottomInfoZoom || 1), cardCanvas.height * (card.bottomInfoZoom || 1));
- cardContext.restore();
- } else {
- cardContext.drawImage(bottomInfoCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
- }
-
-
- // cutout the corners
- cardContext.globalCompositeOperation = 'destination-out';
- if (!card.noCorners && (card.marginX == 0 && card.marginY == 0)) {
- var w = card.version == 'battle' ? 2100 : getStandardWidth();
-
- cardContext.drawImage(corner, 0, 0, scaleWidth(59/w), scaleWidth(59/w));
- cardContext.rotate(Math.PI / 2);
- cardContext.drawImage(corner, 0, -card.width, scaleWidth(59/w), scaleWidth(59/w));
- cardContext.rotate(Math.PI / 2);
- cardContext.drawImage(corner, -card.width, -card.height, scaleWidth(59/w), scaleWidth(59/w));
- cardContext.rotate(Math.PI / 2);
- cardContext.drawImage(corner, -card.height, 0, scaleWidth(59/w), scaleWidth(59/w));
- cardContext.rotate(Math.PI / 2);
- }
- // show preview
- previewContext.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
- previewContext.drawImage(cardCanvas, 0, 0, previewCanvas.width, previewCanvas.height);
-}
-//DOWNLOADING
-function downloadCard(alt = false, jpeg = false) {
- if (card.infoArtist.replace(/ /g, '') == '' && !card.artSource.includes('/img/blank.png') && !card.artZoom == 0) {
- notify('You must credit an artist before downloading!', 5);
- } else {
- // Prep file information
- var imageDataURL;
- var imageName = getCardName();
- if (jpeg) {
- imageDataURL = cardCanvas.toDataURL('image/jpeg', 0.8);
- imageName = imageName + '.jpeg';
- } else {
- imageDataURL = cardCanvas.toDataURL('image/png');
- imageName = imageName + '.png';
- }
- // Download image
- if (alt) {
- const newWindow = window.open('about:blank');
- setTimeout(function(){
- newWindow.document.body.appendChild(newWindow.document.createElement('img')).src = imageDataURL;
- newWindow.document.querySelector('img').style = 'max-height: 100vh; max-width: 100vw;';
- newWindow.document.body.style = 'padding: 0; margin: 0; text-align: center; background-color: #888;';
- newWindow.document.title = imageName;
- }, 0);
- } else {
- const downloadElement = document.createElement('a');
- downloadElement.download = imageName;
- downloadElement.target = '_blank';
- downloadElement.href = imageDataURL;
- document.body.appendChild(downloadElement);
- downloadElement.click();
- downloadElement.remove();
- }
- }
-}
-//IMPORT/SAVE TAB
-function importCard(cardObject) {
- scryfallCard = cardObject;
- const importIndex = document.querySelector('#import-index');
- importIndex.innerHTML = null;
- var optionIndex = 0;
- cardObject.forEach(card => {
- if (card.type_line && card.type_line != 'Card') {
- var option = document.createElement('option');
- var title = `${card.name} `;
- if (document.querySelector('#importAllPrints').checked) {
- title += `(${card.set.toUpperCase()} #${card.collector_number})`;
- } else {
- title += `(${card.type_line})`
- }
- option.innerHTML = title;
- option.value = optionIndex;
- importIndex.appendChild(option);
- }
- optionIndex ++;
- });
- changeCardIndex();
-}
-
-function scryfallCardFromText(text) {
- var lines = text.trim().split("\n");
-
- if (lines.count == 0) {
- return {};
- }
-
- lines = lines.map(item => item.trim()).filter(item => item != "");
-
- var name = lines.shift();
- var manaCost;
- var manaCostStartIndex = name.indexOf("{");
- if (manaCostStartIndex > 0) {
- manaCost = name.substring(manaCostStartIndex).trim();
- name = name.substring(0, manaCostStartIndex).trim();
- }
-
- var cardObject = {
- "name": name,
- "lang": "en"
- };
-
- if (manaCost !== undefined) {
- cardObject.mana_cost = manaCost;
- }
-
- if (lines.count == 0) {
- return cardObject;
- }
-
- cardObject.type_line = lines.shift().trim();
-
- if (lines.count == 0) {
- return cardObject;
- }
-
- var regex = /[0-9+\-*]+\/[0-9+*]+/
- var match = lines[lines.length-1].match(regex);
- if (match) {
- var pt = match[0].split("/");
- cardObject.power = pt[0];
- cardObject.toughness = pt[1];
- lines.pop();
- }
-
- if (lines.count == 0) {
- return cardObject;
- }
-
- cardObject.oracle_text = lines.join("\n");
-
- return cardObject;
-}
-
-function changeCardIndex() {
- var cardToImport = scryfallCard[document.querySelector('#import-index').value];
- //text
- var langFontCode = "";
- if (cardToImport.lang == "ph") {langFontCode = "{fontphyrexian}"}
- var name = cardToImport.name || '';
- if (name.startsWith('A-')) { name = name.replace('A-', '{alchemy}'); }
- if (card.text.title) {card.text.title.text = langFontCode + curlyQuotes(name);}
- if (card.text.nickname) {card.text.nickname.text = cardToImport.flavor_name || '';}
- if (card.text.mana) {card.text.mana.text = cardToImport.mana_cost || '';}
- if (card.text.type) {card.text.type.text = langFontCode + cardToImport.type_line || '';}
-
- var italicExemptions = ['Boast', 'Cycling', 'Visit', 'Prize', 'I', 'II', 'III', 'IV', 'I, II', 'II, III', 'III, IV', 'I, II, III', 'II, III, IV', 'I, II, III, IV', '• Khans', '• Dragons', '• Mirran', '• Phyrexian', 'Prototype', 'Companion', 'To solve', 'Solved'];
- var rulesText = (cardToImport.oracle_text || '').replace(/(?:\((?:.*?)\)|[^"\n]+(?= — ))/g, function(a){
- if (italicExemptions.includes(a) || (cardToImport.keywords.indexOf('Spree') != -1 && a.startsWith('+'))) {return a;}
- return '{i}' + a + '{/i}';
- });
- rulesText = curlyQuotes(rulesText).replace(/{Q}/g, '{untap}').replace(/{\u221E}/g, "{inf}").replace(/• /g, '• {indent}');
- rulesText = rulesText.replace('(If this card is your chosen companion, you may put it into your hand from outside the game for {3} any time you could cast a sorcery.)', '(If this card is your chosen companion, you may put it into your hand from outside the game for {3} as a sorcery.)')
-
- if (card.text.rules) {
- if (card.version == 'pokemon') {
- if (cardToImport.type_line.toLowerCase().includes('creature')) {
- card.text.rules.text = langFontCode + rulesText;
- card.text.rulesnoncreature.text = '';
-
- card.text.middleStatTitle.text = 'power';
- card.text.rightStatTitle.text = 'toughness';
-
- } else if (cardToImport.type_line.toLowerCase().includes('planeswalker')) {
- card.text.rules.text = langFontCode + rulesText;
- card.text.rulesnoncreature.text = '';
-
- card.text.pt.text = '{' + (cardToImport.loyalty || '' + '}');
-
- card.text.middleStatTitle.text = '';
- card.text.rightStatTitle.text = 'loyalty';
- } else if (cardToImport.type_line.toLowerCase().includes('battle')) {
- card.text.rules.text = langFontCode + rulesText;
- card.text.rulesnoncreature.text = '';
-
- card.text.pt.text = '{' + (cardToImport.defense || '' + '}');
-
- card.text.middleStatTitle.text = '';
- card.text.rightStatTitle.text = 'defense';
- } else {
- card.text.rulesnoncreature.text = langFontCode + rulesText;
- card.text.rules.text = '';
-
- card.text.middleStatTitle.text = '';
- card.text.rightStatTitle.text = '';
- }
-
- } else {
- card.text.rules.text = langFontCode + rulesText;
- }
-
- if (cardToImport.flavor_text) {
- var flavorText = cardToImport.flavor_text;
- var flavorTextCounter = 1;
- while (flavorText.includes('*') || flavorText.includes('"')) {
- if (flavorTextCounter % 2) {
- flavorText = flavorText.replace('*', '{/i}');
- flavorText = flavorText.replace('"', '\u201c');
- } else {
- flavorText = flavorText.replace('*', '{i}');
- flavorText = flavorText.replace('"', '\u201d');
- }
- flavorTextCounter ++;
- }
-
- if (card.version == 'pokemon') {
- if (cardToImport.type_line.toLowerCase().includes('creature')) {
- if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
- card.text.rules.text += '{i}';
- } else {
- card.text.rules.text += '{flavor}';
- }
- card.text.rules.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
- } else {
- if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
- card.text.rulesnoncreature.text += '{i}';
- } else {
- card.text.rulesnoncreature.text += '{flavor}';
- }
- card.text.rulesnoncreature.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
- }
-
- } else {
- if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
- card.text.rules.text += '{i}';
- } else {
- card.text.rules.text += '{flavor}';
- }
- card.text.rules.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
- }
-
-
- }
- } else if (card.text.case) {
- rulesText = rulesText.replace(/(\r\n|\r|\n)/g, '//{bar}//');
- card.text.case.text = langFontCode + rulesText;
- }
-
- if (card.text.pt) {
- if (card.version == 'invocation') {
- card.text.pt.text = cardToImport.power + '\n' + cardToImport.toughness || '';
- } else if (card.version == 'pokemon') {
- card.text.middleStat.text = '{' + (cardToImport.power || '') + '}';
- card.text.pt.text = '{' + (cardToImport.toughness || '') + '}';
-
- if (card.text.middleStat && card.text.middleStat.text == '{}') {card.text.middleStat.text = '';}
- } else {
- card.text.pt.text = cardToImport.power + '/' + cardToImport.toughness || '';
- }
- }
- if (card.text.pt && card.text.pt.text == undefined + '/' + undefined) {card.text.pt.text = '';}
- if (card.text.pt && card.text.pt.text == undefined + '\n' + undefined) {card.text.pt.text = '';}
- if (card.text.pt && card.text.pt.text == '{}') {card.text.pt.text = '';}
- if (card.version.includes('planeswalker')) {
- card.text.loyalty.text = cardToImport.loyalty || '';
- var planeswalkerAbilities = cardToImport.oracle_text.split('\n');
- while (planeswalkerAbilities.length > 4) {
- var newAbility = planeswalkerAbilities[planeswalkerAbilities.length - 2] + '\n' + planeswalkerAbilities.pop();
- planeswalkerAbilities[planeswalkerAbilities.length - 1] = newAbility;
- }
- for (var i = 0; i < 4; i ++) {
- if (planeswalkerAbilities[i]) {
- var planeswalkerAbility = planeswalkerAbilities[i].replace(': ', 'splitstring').split('splitstring');
- if (!planeswalkerAbility[1]) {
- planeswalkerAbility = ['', planeswalkerAbility[0]];
- }
- card.text['ability' + i].text = planeswalkerAbility[1].replace('(', '{i}(').replace(')', '){/i}');
- if (card.version == 'planeswalkerTall' || card.version == 'planeswalkerCompleated') {
- document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.3572) / planeswalkerAbilities.length);
- } else {
- document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.2915) / planeswalkerAbilities.length);
- }
- document.querySelector('#planeswalker-cost-' + i).value = planeswalkerAbility[0].replace('\u2212', '-');
- } else {
- card.text['ability' + i].text = '';
- document.querySelector('#planeswalker-height-' + i).value = 0;
- }
- }
- planeswalkerEdited();
- } else if (card.version.includes('saga')) {
- card.text.ability0.text = cardToImport.oracle_text.replace('(', '{i}(').replace(')', '){/i}') || '';
- } else if (card.version.includes('battle')) {
- card.text.defense.text = cardToImport.defense || '';
- }
- document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
- document.querySelector('#text-editor-font-size').value = 0;
- //font size
- Object.keys(card.text).forEach(key => {
- card.text[key].fontSize = 0;
- });
- textEdited();
- //collector's info
- if (localStorage.getItem('enableImportCollectorInfo') == 'true') {
- document.querySelector('#info-number').value = cardToImport.collector_number || "";
- document.querySelector('#info-rarity').value = (cardToImport.rarity || "")[0].toUpperCase();
- document.querySelector('#info-set').value = (cardToImport.set || "").toUpperCase();
- document.querySelector('#info-language').value = (cardToImport.lang || "").toUpperCase();
- var setXhttp = new XMLHttpRequest();
- setXhttp.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- var setObject = JSON.parse(this.responseText)
- if (document.querySelector('#enableNewCollectorStyle').checked) {
- var number = document.querySelector('#info-number').value;
-
- while (number.length < 4) {
- number = '0' + number;
- }
-
- document.querySelector('#info-number').value = number;
-
- bottomInfoEdited();
- } else if (setObject.printed_size) {
- var number = document.querySelector('#info-number').value;
-
- while (number.length < 3) {
- number = '0' + number;
- }
-
- var printedSize = setObject.printed_size;
- while (printedSize.length < 3) {
- printedSize = '0' + printedSize;
- }
-
- if (parseInt(number) <= parseInt(printedSize)) {
- document.querySelector('#info-number').value = number + "/" + printedSize;
- } else {
- document.querySelector('#info-number').value = number;
- }
-
-
- bottomInfoEdited();
- }
- }
- }
- setXhttp.open('GET', "https://api.scryfall.com/sets/" + cardToImport.set, true);
- try {
- setXhttp.send();
- } catch {
- console.log('Scryfall API search failed.')
- }
- }
- //art
- document.querySelector('#art-name').value = cardToImport.name;
- fetchScryfallData(cardToImport.name, artFromScryfall, 'art');
- if (document.querySelector('#importAllPrints').checked) {
- // document.querySelector('#art-index').value = document.querySelector('#import-index').value;
- // changeArtIndex();
- }
- //set symbol
- if (!document.querySelector('#lockSetSymbolCode').checked) {
- document.querySelector('#set-symbol-code').value = cardToImport.set;
- }
- document.querySelector('#set-symbol-rarity').value = cardToImport.rarity.slice(0, 1);
- if (!document.querySelector('#lockSetSymbolURL').checked) {
- fetchSetSymbol();
- }
-}
-function loadAvailableCards(cardKeys = JSON.parse(localStorage.getItem('cardKeys'))) {
- if (!cardKeys) {
- cardKeys = [];
- cardKeys.sort();
- localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
- }
- document.querySelector('#load-card-options').innerHTML = 'None selected ';
- cardKeys.forEach(item => {
- var cardKeyOption = document.createElement('option');
- cardKeyOption.innerHTML = item;
- document.querySelector('#load-card-options').appendChild(cardKeyOption);
- });
-}
-function importChanged() {
- var unique = document.querySelector('#importAllPrints').checked ? 'prints' : '';
- fetchScryfallData(document.querySelector("#import-name").value, importCard, unique);
-}
-function saveCard(saveFromFile) {
- var cardKeys = JSON.parse(localStorage.getItem('cardKeys')) || [];
- var cardKey, cardToSave;
- if (saveFromFile) {
- cardKey = saveFromFile.key;
- } else {
- cardKey = getCardName();
- }
- if (!saveFromFile) {
- cardKey = prompt('Enter the name you would like to save your card under:', cardKey);
- if (!cardKey) {return null;}
- }
- cardKey = cardKey.trim();
- if (cardKeys.includes(cardKey)) {
- if (!confirm('Would you like to overwrite your card previously saved as "' + cardKey + '"?\n(Clicking "cancel" will affix a version number)')) {
- var originalCardKey = cardKey;
- var cardKeyNumber = 1;
- while (cardKeys.includes(cardKey)) {
- cardKey = originalCardKey + ' (' + cardKeyNumber + ')';
- cardKeyNumber ++;
- }
- }
- }
- if (saveFromFile) {
- cardToSave = saveFromFile.data;
- } else {
- cardToSave = JSON.parse(JSON.stringify(card));
- cardToSave.frames.forEach(frame => {
- delete frame.image;
- frame.masks.forEach(mask => delete mask.image);
- });
- }
- try {
- localStorage.setItem(cardKey, JSON.stringify(cardToSave));
- if (!cardKeys.includes(cardKey)) {
- cardKeys.push(cardKey);
- cardKeys.sort();
- localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
- loadAvailableCards(cardKeys);
- }
- } catch (error) {
- notify('You have exceeded your 5MB of local storage, and your card has failed to save. If you would like to continue saving cards, please download all saved cards, then delete all saved cards to free up space. Local storage is most often exceeded by uploading large images directly from your computer. If possible/convenient, using a URL avoids the need to save these large images. Apologies for the inconvenience.');
- }
-}
-async function loadCard(selectedCardKey) {
- //clear the draggable frames
- document.querySelector('#frame-list').innerHTML = null;
- //clear the existing card, then replace it with the new JSON
- card = {};
- card = JSON.parse(localStorage.getItem(selectedCardKey));
- //if the card was loaded properly...
- if (card) {
- //load values from card into html inputs
- document.querySelector('#info-number').value = card.infoNumber;
- document.querySelector('#info-rarity').value = card.infoRarity;
- document.querySelector('#info-set').value = card.infoSet;
- document.querySelector('#info-language').value = card.infoLanguage;
- document.querySelector('#info-note').value = card.infoNote;
- document.querySelector('#info-year').value = card.infoYear || date.getFullYear();
- artistEdited(card.infoArtist);
- document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
- document.querySelector('#text-editor-font-size').value = card.text[Object.keys(card.text)[selectedTextIndex]].fontSize || 0;
- loadTextOptions(card.text);
- document.querySelector('#art-x').value = scaleX(card.artX) - scaleWidth(card.marginX);
- document.querySelector('#art-y').value = scaleY(card.artY) - scaleHeight(card.marginY);
- document.querySelector('#art-zoom').value = card.artZoom * 100;
- document.querySelector('#art-rotate').value = card.artRotate || 0;
- uploadArt(card.artSource);
- document.querySelector('#setSymbol-x').value = scaleX(card.setSymbolX) - scaleWidth(card.marginX);
- document.querySelector('#setSymbol-y').value = scaleY(card.setSymbolY) - scaleHeight(card.marginY);
- document.querySelector('#setSymbol-zoom').value = card.setSymbolZoom * 100;
- uploadSetSymbol(card.setSymbolSource);
- document.querySelector('#watermark-x').value = scaleX(card.watermarkX) - scaleWidth(card.marginX);
- document.querySelector('#watermark-y').value = scaleY(card.watermarkY) - scaleHeight(card.marginY);
- document.querySelector('#watermark-zoom').value = card.watermarkZoom * 100;
- // document.querySelector('#watermark-left').value = card.watermarkLeft;
- // document.querySelector('#watermark-right').value = card.watermarkRight;
- document.querySelector('#watermark-opacity').value = card.watermarkOpacity * 100;
- document.getElementById("rounded-corners").checked = !card.noCorners;
- uploadWatermark(card.watermarkSource);
- card.frames.reverse();
- await card.frames.forEach(item => addFrame([], item));
- card.frames.reverse();
- if (card.onload) {
- await loadScript(card.onload);
- }
- card.manaSymbols.forEach(item => loadScript(item));
- //canvases
- var canvasesResized = false;
- canvasList.forEach(name => {
- if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
- sizeCanvas(name);
- canvasesResized = true;
- }
- });
- if (canvasesResized) {
- drawTextBuffer();
- drawFrames();
- bottomInfoEdited();
- watermarkEdited();
- }
- } else {
- notify(selectedCardKey + ' failed to load.', 5)
- }
-}
-function deleteCard() {
- var keyToDelete = document.querySelector('#load-card-options').value;
- if (keyToDelete) {
- var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
- cardKeys.splice(cardKeys.indexOf(keyToDelete), 1);
- cardKeys.sort();
- localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
- localStorage.removeItem(keyToDelete);
- loadAvailableCards(cardKeys);
- }
-}
-function deleteSavedCards() {
- if (confirm('WARNING:\n\nALL of your saved cards will be deleted! If you would like to save these cards, please make sure you have downloaded them first. There is no way to undo this.\n\n(Press "OK" to delete your cards)')) {
- var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
- cardKeys.forEach(key => localStorage.removeItem(key));
- localStorage.setItem('cardKeys', JSON.stringify([]));
- loadAvailableCards([]);
- }
-}
-async function downloadSavedCards() {
- var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
- if (cardKeys) {
- var allSavedCards = [];
- cardKeys.forEach(item => {
- allSavedCards.push({key:item, data:JSON.parse(localStorage.getItem(item))});
- });
- var download = document.createElement('a');
- download.href = URL.createObjectURL(new Blob([JSON.stringify(allSavedCards)], {type:'text'}));
- download.download = 'saved-cards.cardconjurer';
- document.body.appendChild(download);
- await download.click();
- download.remove();
- }
-}
-function uploadSavedCards(event) {
- var reader = new FileReader();
- reader.onload = function () {
- JSON.parse(reader.result).forEach(item => saveCard(item));
- }
- reader.readAsText(event.target.files[0]);
-}
-//TUTORIAL TAB
-function loadTutorialVideo() {
- var video = document.querySelector('.video > iframe');
- if (video.src == '') {
- video.src = 'https://www.youtube-nocookie.com/embed/e4tnOiub41g?rel=0';
- }
-}
-// GUIDELINES
-function drawNewGuidelines() {
- // clear
- guidelinesContext.clearRect(0, 0, guidelinesCanvas.width, guidelinesCanvas.height);
- // set opacity
- guidelinesContext.globalAlpha = 0.25;
- // textboxes
- guidelinesContext.fillStyle = 'blue';
- Object.entries(card.text).forEach(item => {
- guidelinesContext.fillRect(scaleX(item[1].x || 0), scaleY(item[1].y || 0), scaleWidth(item[1].width || 1), scaleHeight(item[1].height || 1));
- });
- // art
- guidelinesContext.fillStyle = 'green';
- guidelinesContext.fillRect(scaleX(card.artBounds.x), scaleY(card.artBounds.y), scaleWidth(card.artBounds.width), scaleHeight(card.artBounds.height));
- // watermark
- guidelinesContext.fillStyle = 'yellow';
- var watermarkWidth = scaleWidth(card.watermarkBounds.width);
- var watermarkHeight = scaleHeight(card.watermarkBounds.height);
- guidelinesContext.fillRect(scaleX(card.watermarkBounds.x) - watermarkWidth / 2, scaleY(card.watermarkBounds.y) - watermarkHeight / 2, watermarkWidth, watermarkHeight);
- // set symbol
- var setSymbolX = scaleX(card.setSymbolBounds.x);
- var setSymbolY = scaleY(card.setSymbolBounds.y);
- var setSymbolWidth = scaleWidth(card.setSymbolBounds.width);
- var setSymbolHeight = scaleHeight(card.setSymbolBounds.height);
- if (card.setSymbolBounds.vertical == 'center') {
- setSymbolY -= setSymbolHeight / 2;
- } else if (card.setSymbolBounds.vertical == 'bottom') {
- setSymbolY -= setSymbolHeight;
- }
- if (card.setSymbolBounds.horizontal == 'center') {
- setSymbolX -= setSymbolWidth / 2;
- } else if (card.setSymbolBounds.horizontal == 'right') {
- setSymbolX -= setSymbolWidth;
- }
- guidelinesContext.fillStyle = 'red';
- guidelinesContext.fillRect(setSymbolX, setSymbolY, setSymbolWidth, setSymbolHeight);
- // grid
- guidelinesContext.globalAlpha = 1;
- guidelinesContext.beginPath();
- guidelinesContext.strokeStyle = 'gray';
- guidelinesContext.lineWidth = 1;
- const boxPadding = 25;
- for (var x = 0; x <= card.width; x += boxPadding) {
- guidelinesContext.moveTo(x, 0);
- guidelinesContext.lineTo(x, card.height);
- }
- for (var y = 0; y <= card.height; y += boxPadding) {
- guidelinesContext.moveTo(0, y);
- guidelinesContext.lineTo(card.width, y);
- }
- guidelinesContext.stroke();
- //center lines
- guidelinesContext.beginPath();
- guidelinesContext.strokeStyle = 'black';
- guidelinesContext.lineWidth = 3;
- guidelinesContext.moveTo(card.width / 2, 0);
- guidelinesContext.lineTo(card.width / 2, card.height);
- guidelinesContext.moveTo(0, card.height / 2);
- guidelinesContext.lineTo(card.width, card.height / 2);
- guidelinesContext.stroke();
- //draw to card
- drawCard();
-}
-//HIGHLIGHT TRANSPARENCIES
-function toggleCardBackgroundColor(highlight) {
- if (highlight) {
- previewCanvas.style["background-color"] = "#ff007fff";
- } else {
- previewCanvas.style["background-color"] = "#0000";
- }
-}
-//Rounded Corners
-function setRoundedCorners(value) {
- card.noCorners = !value;
- drawCard();
-}
-//Various loaders
-function imageURL(url, destination, otherParams) {
- var imageurl = url;
- // If an image URL does not have HTTP in it, assume it's a local file in the repo local_art directory.
- if (!url.includes('http')) {
- imageurl = '/local_art/' + url;
- } else if (params.get('noproxy') != '') {
- //CORS PROXY LINKS
- //Previously: https://cors.bridged.cc/
- imageurl = 'https://corsproxy.io/?' + encodeURIComponent(url);
- }
- destination(imageurl, otherParams);
-}
-async function imageLocal(event, destination, otherParams) {
- var reader = new FileReader();
- reader.onload = function () {
- destination(reader.result, otherParams);
- }
- reader.onerror = function () {
- destination('/img/blank.png', otherParams);
- }
- await reader.readAsDataURL(event.target.files[0]);
-}
-function loadScript(scriptPath) {
- var script = document.createElement('script');
- script.setAttribute('type', 'text/javascript');
- script.onerror = function(){notify('A script failed to load, likely due to an update. Please reload your page. Sorry for the inconvenience.');}
- script.setAttribute('src', scriptPath);
- if (typeof script != 'undefined') {
- document.querySelectorAll('head')[0].appendChild(script);
- }
-}
-// Stretchable SVGs
-function stretchSVG(frameObject) {
- xhr = new XMLHttpRequest();
- xhr.open('GET', fixUri(frameObject.src), true);
- xhr.overrideMimeType('image/svg+xml');
- xhr.onload = function(e) {
- if (this.readyState == 4 && this.status == 200) {
- frameObject.image.src = 'data:image/svg+xml;charset=utf-8,' + stretchSVGReal((new XMLSerializer).serializeToString(this.responseXML.documentElement), frameObject);
- }
- }
- xhr.send();
-}
-function stretchSVGReal(data, frameObject) {
- var returnData = data;
- frameObject.stretch.forEach(stretch => {
- const change = stretch.change;
- const targets = stretch.targets;
- const name = stretch.name;
- const oldData = returnData.split(name + '" d="')[1].split('" style=')[0];
- var newData = '';
- const listData = oldData.split(/(?=[clmz])/gi);
- for (i = 0; i < listData.length; i ++) {
- const item = listData[i];
- if (targets.includes(i) || targets.includes(-i)) {
- let sign = 1;
- if (i != 0 && targets.includes(-i)) {sign = -1};
- if (item[0] == 'C' || item[0] == 'c') {
- newCoords = [];
- item.slice(1).split(' ').forEach(pair => {
- coords = pair.split(',');
- newCoords.push((scaleWidth(change[0]) * sign + parseFloat(coords[0])) + ',' + (scaleHeight(change[1]) * sign + parseFloat(coords[1])));
- });
- newData += item[0] + newCoords.join(' ');
- } else {
- const coords = item.slice(1).split(/[, ]/);
- newData += item[0] + (scaleWidth(change[0]) * sign + parseFloat(coords[0])) + ',' + (scaleHeight(change[1]) * sign + parseFloat(coords[1]))
- }
- } else {
- newData += item;
- }
- }
- returnData = returnData.replace(oldData, newData);
- });
- return returnData;
-}
-function processScryfallCard(card, responseCards) {
- if ('card_faces' in card) {
- card.card_faces.forEach(face => {
- face.set = card.set;
- face.rarity = card.rarity;
- face.collector_number = card.collector_number;
- face.lang = card.lang;
- if (card.lang != 'en') {
- face.oracle_text = face.printed_text;
- face.name = face.printed_name;
- face.type_line = face.printed_type_line;
- }
- responseCards.push(face);
- if (!face.image_uris) {
- face.image_uris = card.image_uris;
- }
- });
- } else {
- if (card.lang != 'en') {
- card.oracle_text = card.printed_text;
- card.name = card.printed_name;
- card.type_line = card.printed_type_line;
- }
- responseCards.push(card);
- }
-}
-
-function fetchScryfallCardByID(scryfallID, callback = console.log) {
- var xhttp = new XMLHttpRequest();
- xhttp.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- responseCards = [];
- importedCards = [JSON.parse(this.responseText)];
- importedCards.forEach(card => {
- processScryfallCard(card, responseCards);
- });
- callback(responseCards);
- } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
- notify(`No card found for "${cardName}" in ${cardLanguageSelect.options[cardLanguageSelect.selectedIndex].text}.`, 5);
- }
- }
- xhttp.open('GET', 'https://api.scryfall.com/cards/' + scryfallID, true);
- try {
- xhttp.send();
- } catch {
- console.log('Scryfall API search failed.')
- }
-}
-
-function fetchScryfallCardByCodeNumber(code, number, callback = console.log) {
- var xhttp = new XMLHttpRequest();
- xhttp.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- responseCards = [];
- importedCards = [JSON.parse(this.responseText)];
- importedCards.forEach(card => {
- processScryfallCard(card, responseCards);
- });
- callback(responseCards);
- } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
- notify('No card found for ' + code + ' #' + number, 5);
- }
- }
- xhttp.open('GET', 'https://api.scryfall.com/cards/' + code + '/' + number, true);
- try {
- xhttp.send();
- } catch {
- console.log('Scryfall API search failed.')
- }
-}
-
-//SCRYFALL STUFF MAY BE CHANGED IN THE FUTURE
-function fetchScryfallData(cardName, callback = console.log, unique = '') {
- var xhttp = new XMLHttpRequest();
- xhttp.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- responseCards = [];
- importedCards = JSON.parse(this.responseText).data;
- importedCards.forEach(card => {
- processScryfallCard(card, responseCards);
- });
- callback(responseCards);
- } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
- notify(`No cards found for "${cardName}" in ${cardLanguageSelect.options[cardLanguageSelect.selectedIndex].text}.`, 5);
- }
- }
- cardLanguageSelect = document.querySelector('#import-language');
- var cardLanguage = `lang%3D${cardLanguageSelect.value}`;
- var uniqueArt = '';
- if (unique) {
- uniqueArt = '&unique=' + unique;
- }
- var url = `https://api.scryfall.com/cards/search?order=released&include_extras=true${uniqueArt}&q=name%3D${cardName.replace(/ /g, '_')}%20${cardLanguage}`;
- xhttp.open('GET', url, true);
- try {
- xhttp.send();
- } catch {
- console.log('Scryfall API search failed.')
- }
-}
-
-function toggleTextTag(tag) {
- var element = document.getElementById('text-editor');
-
- var text = element.value;
-
- var start = element.selectionStart;
- var end = element.selectionEnd;
- var selection = text.substring(start, end);
-
- var openTag = '{' + tag + '}';
- var closeTag = '{/' + tag + '}';
-
- var prefix = text.substring(0, start);
- var suffix = text.substring(end);
-
- if (prefix.endsWith(openTag) && suffix.startsWith(closeTag)) {
- prefix = prefix.substring(0, prefix.length-openTag.length);
- suffix = suffix.substring(closeTag.length);
- } else if (selection.startsWith(openTag) && selection.endsWith(closeTag)) {
- selection = selection.substring(openTag.length, selection.length-closeTag.length);
- } else {
- selection = openTag + selection + closeTag;
- }
-
- element.value = prefix + selection + suffix;
-
- textEdited();
-}
-
-function toggleHighRes() {
- localStorage.setItem('high-res', document.querySelector('#high-res').checked);
- drawCard();
-}
-
-// INITIALIZATION
-
-// auto load frame version (user defaults)
-if (!localStorage.getItem('autoLoadFrameVersion')) {
- localStorage.setItem('autoLoadFrameVersion', document.querySelector('#autoLoadFrameVersion').checked);
-}
-document.querySelector('#autoLoadFrameVersion').checked = 'true' == localStorage.getItem('autoLoadFrameVersion');
-// document.querySelector('#high-res').checked = 'true' == localStorage.getItem('high-res');
-
-// collector info (user defaults)
-var defaultCollector = JSON.parse(localStorage.getItem('defaultCollector') || '{}');
-if ('number' in defaultCollector) {
- document.querySelector('#info-number').value = defaultCollector.number;
- document.querySelector('#info-note').value = defaultCollector.note;
- document.querySelector('#info-rarity').value = defaultCollector.rarity;
- document.querySelector('#info-set').value = defaultCollector.setCode;
- document.querySelector('#info-language').value = defaultCollector.lang;
- if (defaultCollector.starDot) {setTimeout(function(){defaultCollector.starDot = false; toggleStarDot();}, 500);}
-} else {
- document.querySelector('#info-number').value = date.getFullYear();
-}
-if (!localStorage.getItem('enableImportCollectorInfo')) {
- localStorage.setItem('enableImportCollectorInfo', 'false');
-} else {
- document.querySelector('#enableImportCollectorInfo').checked = (localStorage.getItem('enableImportCollectorInfo') == 'true');
-}
-if (!localStorage.getItem('enableNewCollectorStyle')) {
- localStorage.setItem('enableNewCollectorStyle', 'false');
-} else {
- document.querySelector('#enableNewCollectorStyle').checked = (localStorage.getItem('enableNewCollectorStyle') == 'true');
-}
-if (!localStorage.getItem('enableCollectorInfo')) {
- localStorage.setItem('enableCollectorInfo', 'true');
-} else {
- document.querySelector('#enableCollectorInfo').checked = (localStorage.getItem('enableCollectorInfo') == 'true');
-}
-if (!localStorage.getItem('autoFrame')) {
- localStorage.setItem('autoFrame', 'false');
-} else {
- document.querySelector('#autoFrame').value = localStorage.getItem('autoFrame');
-}
-if (!localStorage.getItem('autoFit')) {
- localStorage.setItem('autoFit', 'true');
-} else {
- document.querySelector('#art-update-autofit').checked = localStorage.getItem('autoFit');
-}
-
-// lock set symbol code (user defaults)
-if (!localStorage.getItem('lockSetSymbolCode')) {
- localStorage.setItem('lockSetSymbolCode', '');
-}
-if (localStorage.getItem('set-symbol-source')) {
- document.querySelector('#set-symbol-source').value = localStorage.getItem('set-symbol-source');
-}
-document.querySelector('#lockSetSymbolCode').checked = '' != localStorage.getItem('lockSetSymbolCode');
-if (document.querySelector('#lockSetSymbolCode').checked) {
- document.querySelector('#set-symbol-code').value = localStorage.getItem('lockSetSymbolCode');
- fetchSetSymbol();
-}
-
-// lock set symbol url (user defaults)
-if (!localStorage.getItem('lockSetSymbolURL')) {
- localStorage.setItem('lockSetSymbolURL', '');
-}
-document.querySelector('#lockSetSymbolURL').checked = '' != localStorage.getItem('lockSetSymbolURL');
-if (document.querySelector('#lockSetSymbolURL').checked) {
- setSymbol.src = localStorage.getItem('lockSetSymbolURL');
-}
-
-//bind inputs together
-bindInputs('#frame-editor-hsl-hue', '#frame-editor-hsl-hue-slider');
-bindInputs('#frame-editor-hsl-saturation', '#frame-editor-hsl-saturation-slider');
-bindInputs('#frame-editor-hsl-lightness', '#frame-editor-hsl-lightness-slider');
-bindInputs('#show-guidelines', '#show-guidelines-2', true);
-
-// Load / init whatever
-loadScript('/js/frames/groupStandard-3.js');
-loadAvailableCards();
-initDraggableArt();
+//URL Params
+var params = new URLSearchParams(window.location.search);
+const debugging = params.get('debug') != null;
+if (debugging) {
+ alert('debugging - 4.0');
+ document.querySelectorAll('.debugging').forEach(element => element.classList.remove('hidden'));
+}
+
+//To save the server from being overloaded? Maybe?
+function fixUri(input) {
+ /* --- DISABLED FOR LOCAL VERSION --
+ var prefix = 'https://card-conjurer.storage.googleapis.com';//'https://raw.githubusercontent.com/ImKyle4815/cardconjurer/remake';
+ if (input.includes(prefix) || input.includes('http') || input.includes('data:image') || window.location.href.includes('localhost')) {
+ return input;
+ } else {
+ return prefix + input; //input.replace('/img/frames', prefix + '/img/frames');
+ } */
+ return input;
+}
+function setImageUrl(image, source) {
+ image.crossOrigin = 'anonymous';
+ image.src = fixUri(source);
+}
+
+const baseWidth = 1500;
+const baseHeight = 2100;
+const highResScale = 1.34;
+// function getStandardWidth() {
+// var value = baseWidth;
+// if (localStorage.getItem('high-res') == 'true') {
+// value *= highResScale;
+// }
+// return value;
+// }
+// function getStandardHeight() {
+// var value = baseHeight;
+// if (localStorage.getItem('high-res') == 'true') {
+// value *= highResScale;
+// }
+// return value;
+// }
+function getStandardWidth() {
+ return 2010;
+}
+function getStandardHeight() {
+ return 2814;
+}
+
+//card object
+var card = {width:getStandardWidth(), height:getStandardHeight(), marginX:0, marginY:0, frames:[], artSource:fixUri('/img/blank.png'), artX:0, artY:0, artZoom:1, artRotate:0, setSymbolSource:fixUri('/img/blank.png'), setSymbolX:0, setSymbolY:0, setSymbolZoom:1, watermarkSource:fixUri('/img/blank.png'), watermarkX:0, watermarkY:0, watermarkZoom:1, watermarkLeft:'none', watermarkRight:'none', watermarkOpacity:0.4, version:'', manaSymbols:[]};
+//core images/masks
+const black = new Image(); black.crossOrigin = 'anonymous'; black.src = fixUri('/img/black.png');
+const blank = new Image(); blank.crossOrigin = 'anonymous'; blank.src = fixUri('/img/blank.png');
+const right = new Image(); right.crossOrigin = 'anonymous'; right.src = fixUri('/img/frames/maskRightHalf.png');
+const middle = new Image(); middle.crossOrigin = 'anonymous'; middle.src = fixUri('/img/frames/maskMiddleThird.png');
+const corner = new Image(); corner.crossOrigin = 'anonymous'; corner.src = fixUri('/img/frames/cornerCutout.png');
+//art
+art = new Image(); art.crossOrigin = 'anonymous'; art.src = blank.src;
+art.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
+art.onload = artEdited;
+//set symbol
+setSymbol = new Image(); setSymbol.crossOrigin = 'anonymous'; setSymbol.src = blank.src;
+setSymbol.onerror = function() {
+ if (this.src.includes('gatherer.wizards.com')) {
+ notify('Loading the set symbol from Gatherer failed. Please check this link to see if it exists. If it does, it may be necessary to manually download and upload the image. ', 5);
+ }
+ if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}
+}
+setSymbol.onload = setSymbolEdited;
+//watermark
+watermark = new Image(); watermark.crossOrigin = 'anonymous'; watermark.src = blank.src;
+watermark.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
+watermark.onload = watermarkEdited;
+//preview canvas
+var previewCanvas = document.querySelector('#previewCanvas');
+var previewContext = previewCanvas.getContext('2d');
+var canvasList = [];
+//frame/mask picker stuff
+var availableFrames = [];
+var selectedFrame = null;
+var selectedFrameIndex = 0;
+var selectedMaskIndex = 0;
+var selectedTextIndex = 0;
+var replacementMasks = {};
+var customCount = 0;
+var lastFrameClick = null;
+var lastMaskClick = null;
+//for imports
+var scryfallArt;
+var scryfallCard;
+//for text
+var drawTextBetweenFrames = false;
+var redrawFrames = false;
+var savedTextXPosition = 0;
+var savedTextXPosition2 = 0;
+var savedRollYPosition = null;
+var savedFont = null;
+var savedTextContents = {};
+//for misc
+var date = new Date();
+card.infoYear = date.getFullYear();
+document.querySelector("#info-year").value = card.infoYear;
+//to avoid rerunning special scripts (planeswalker, saga, etc...)
+
+var loadedVersions = [];
+//Card Object managament
+async function resetCardIrregularities({canvas = [getStandardWidth(), getStandardHeight(), 0, 0], resetOthers = true} = {}) {
+ //misc details
+ card.margins = false;
+ card.bottomInfoTranslate = {x:0, y:0};
+ card.bottomInfoRotate = 0;
+ card.bottomInfoZoom = 1;
+ card.bottomInfoColor = 'white';
+ replacementMasks = {};
+ //rotation
+ if (card.landscape) {
+ // previewContext.scale(card.width/card.height, card.height/card.width);
+ // previewContext.rotate(Math.PI / 2);
+ // previewContext.translate(0, -card.width / 2);
+ previewContext.setTransform(1, 0, 0, 1, 0, 0);
+ card.landscape = false;
+ }
+ //card size
+ card.width = canvas[0];
+ card.height = canvas[1];
+ card.marginX = canvas[2];
+ card.marginY = canvas[3];
+ //canvases
+ canvasList.forEach(name => {
+ if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
+ sizeCanvas(name);
+ }
+ });
+ if (resetOthers) {
+ setBottomInfoStyle();
+ //onload
+ card.onload = null;
+
+ card.hideBottomInfoBorder = false;
+ card.showsFlavorBar = true;
+ }
+}
+async function setBottomInfoStyle() {
+ if (document.querySelector('#enableNewCollectorStyle').checked) {
+ await loadBottomInfo({
+ midLeft: {text:'{elemidinfo-set} \u2022 {elemidinfo-language} {savex}{fontbelerenbsc}{fontsize' + scaleHeight(0.001) + '}{upinline' + scaleHeight(0.0005) + '}\uFFEE{savex2}{elemidinfo-artist}', x:0.0647, y:0.9548, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ topLeft: {text:'{elemidinfo-rarity} {kerning3}{elemidinfo-number}{kerning0}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ note: {text:'{loadx}{elemidinfo-note}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ bottomLeft: {text:'NOT FOR SALE', x:0.0647, y:0.9719, width:0.8707, height:0.0143, oneLine:true, font:'gothammedium', size:0.0143, color:card.bottomInfoColor, outlineWidth:0.003},
+ wizards: {name:'wizards', text:'{ptshift0,0.0172}\u2122 & \u00a9 {elemidinfo-year} Wizards of the Coast', x:0.0647, y:0.9377, width:0.8707, height:0.0167, oneLine:true, font:'mplantin', size:0.0162, color:card.bottomInfoColor, align:'right', outlineWidth:0.003},
+ bottomRight: {text:'{ptshift0,0.0172}CardConjurer.com', x:0.0647, y:0.9548, width:0.8707, height:0.0143, oneLine:true, font:'mplantin', size:0.0143, color:card.bottomInfoColor, align:'right', outlineWidth:0.003}
+ });
+ } else {
+ await loadBottomInfo({
+ midLeft: {text:'{elemidinfo-set} \u2022 {elemidinfo-language} {savex}{fontbelerenbsc}{fontsize' + scaleHeight(0.001) + '}{upinline' + scaleHeight(0.0005) + '}\uFFEE{savex2}{elemidinfo-artist}', x:0.0647, y:0.9548, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color: card.bottomInfoColor, outlineWidth:0.003},
+ topLeft: {text:'{elemidinfo-number}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ note: {text:'{loadx2}{elemidinfo-note}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ rarity: {text:'{loadx}{elemidinfo-rarity}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:card.bottomInfoColor, outlineWidth:0.003},
+ bottomLeft: {text:'NOT FOR SALE', x:0.0647, y:0.9719, width:0.8707, height:0.0143, oneLine:true, font:'gothammedium', size:0.0143, color:card.bottomInfoColor, outlineWidth:0.003},
+ wizards: {name:'wizards', text:'{ptshift0,0.0172}\u2122 & \u00a9 {elemidinfo-year} Wizards of the Coast', x:0.0647, y:0.9377, width:0.8707, height:0.0167, oneLine:true, font:'mplantin', size:0.0162, color:card.bottomInfoColor, align:'right', outlineWidth:0.003},
+ bottomRight: {text:'{ptshift0,0.0172}CardConjurer.com', x:0.0647, y:0.9548, width:0.8707, height:0.0143, oneLine:true, font:'mplantin', size:0.0143, color:card.bottomInfoColor, align:'right', outlineWidth:0.003}
+ });
+ }
+}
+//Canvas management
+function sizeCanvas(name, width = Math.round(card.width * (1 + 2 * card.marginX)), height = Math.round(card.height * (1 + 2 * card.marginY))) {
+ if (!window[name + 'Canvas']) {
+ window[name + 'Canvas'] = document.createElement('canvas');
+ window[name + 'Context'] = window[name + 'Canvas'].getContext('2d');
+ canvasList[canvasList.length] = name;
+ }
+ window[name + 'Canvas'].width = width;
+ window[name + 'Canvas'].height = height;
+ if (name == 'line') { //force true to view all canvases - must restore to name == 'line' for proper kerning adjustments
+ window[name + 'Canvas'].style = 'width: 20rem; height: 28rem; border: 1px solid red;';
+ const label = document.createElement('div');
+ label.innerHTML = name + ' If you can see this and don\'t want to, please clear your cache.';
+ label.appendChild(window[name + 'Canvas']);
+ label.classList = 'fake-hidden'; //Comment this out to view canvases
+ document.body.appendChild(label);
+ }
+}
+//create main canvases
+sizeCanvas('card');
+sizeCanvas('frame');
+sizeCanvas('frameMasking');
+sizeCanvas('frameCompositing');
+sizeCanvas('text');
+sizeCanvas('paragraph');
+sizeCanvas('line');
+sizeCanvas('watermark');
+sizeCanvas('bottomInfo');
+sizeCanvas('guidelines');
+sizeCanvas('prePT');
+//Scaling
+function scaleX(input) {
+ return Math.round((input + card.marginX) * card.width);
+}
+function scaleWidth(input) {
+ return Math.round(input * card.width);
+}
+function scaleY(input) {
+ return Math.round((input + card.marginY) * card.height);
+}
+function scaleHeight(input) {
+ return Math.round(input * card.height);
+}
+//Other nifty functions
+function getElementIndex(element) {
+ return Array.prototype.indexOf.call(element.parentElement.children, element);
+}
+function getCardName() {
+ if (card.text == undefined || card.text.title == undefined) {
+ return 'unnamed';
+ }
+ var imageName = card.text.title.text || 'unnamed';
+ if (card.text.nickname) {
+ imageName += ' (' + card.text.nickname.text + ')';
+ }
+ return imageName.replace(/\{[^}]+\}/g, '');
+}
+function getInlineCardName() {
+ if (card.text == undefined || card.text.title == undefined) {
+ return 'unnamed';
+ }
+ var imageName = card.text.title.text || 'unnamed';
+ if (card.text.nickname) {
+ imageName = card.text.nickname.text;
+ }
+ return imageName.replace(/\{[^}]+\}/g, '');
+}
+//UI
+function toggleCreatorTabs(event, target) {
+ Array.from(document.querySelector('#creator-menu-sections').children).forEach(element => element.classList.add('hidden'));
+ document.querySelector('#creator-menu-' + target).classList.remove('hidden');
+ selectSelectable(event);
+}
+function selectSelectable(event) {
+ var eventTarget = event.target.closest('.selectable');
+ Array.from(eventTarget.parentElement.children).forEach(element => element.classList.remove('selected'));
+ eventTarget.classList.add('selected');
+}
+function dragStart(event) {
+ Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
+ event.target.closest('.draggable').classList.add('dragging');
+}
+function dragEnd(event) {
+ Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
+}
+function touchMove(event) {
+ if (event.target.nodeName != 'H4') {
+ event.preventDefault();
+ }
+ var clientX = event.touches[0].clientX;
+ var clientY = event.touches[0].clientY;
+ Array.from(document.querySelector('.dragging').parentElement.children).forEach(element => {
+ var elementBounds = element.getBoundingClientRect();
+ if (clientY > elementBounds.top && clientY < elementBounds.bottom) {
+ dragOver(element, false);
+ }
+ })
+}
+function dragOver(event, drag=true) {
+ var eventTarget;
+ if (drag) {
+ eventTarget = event.target.closest('.draggable');
+ } else {
+ eventTarget = event;
+ }
+ var movingElement = document.querySelector('.dragging');
+ if (document.querySelector('.dragging') && !eventTarget.classList.contains('dragging') && eventTarget.parentElement == movingElement.parentElement) {
+ var parentElement = eventTarget.parentElement;
+ var elements = document.createDocumentFragment();
+ var movingElementPassed = false;
+ var movingElementOldIndex = -1;
+ var movingElementNewIndex = -1;
+ Array.from(parentElement.children).forEach((element, index) => {
+ if (element == eventTarget) {
+ movingElementNewIndex = index;
+ if(movingElementPassed) {
+ elements.appendChild(element.cloneNode(true));
+ elements.appendChild(movingElement.cloneNode(true));
+ } else {
+ elements.appendChild(movingElement.cloneNode(true));
+ elements.appendChild(element.cloneNode(true));
+ }
+ } else if(element != movingElement) {
+ elements.appendChild(element.cloneNode(true));
+ } else {
+ movingElementOldIndex = index;
+ movingElementPassed = true;
+ }
+ });
+ Array.from(elements.children).forEach(element => {
+ element.ondragstart = dragStart;
+ element.ontouchstart = dragStart;
+ element.ondragend = dragEnd;
+ element.ontouchend = dragEnd;
+ element.ondragover = dragOver;
+ element.ontouchmove = touchMove;
+ element.onclick = frameElementClicked;
+ element.children[3].onclick = removeFrame;
+ })
+ parentElement.innerHTML = null;
+ parentElement.appendChild(elements);
+ if (movingElementNewIndex >= 0) {
+ var originalMovingElement = card.frames[movingElementOldIndex];
+ card.frames.splice(movingElementOldIndex, 1);
+ card.frames.splice(movingElementNewIndex, 0, originalMovingElement);
+ drawFrames();
+ }
+ }
+}
+//Set Symbols
+const setSymbolAliases = new Map([
+ ["anb", "ana"],
+ ["tsb", "tsp"],
+ ["pmei", "sld"],
+]);
+//Mana Symbols
+const mana = new Map();""
+// var manaSymbols = [];
+loadManaSymbols(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
+ 'w', 'u', 'b', 'r', 'g', 'c', 'x', 'y', 'z', 't', 'untap', 'e', 's', 'oldtap', 'originaltap', 'purple', "a", "inf", "alchemy"]);
+loadManaSymbols(['wu', 'wb', 'ub', 'ur', 'br', 'bg', 'rg', 'rw', 'gw', 'gu', '2w', '2u', '2b', '2r', '2g', 'wp', 'up', 'bp', 'rp', 'gp', 'p',
+ 'wup', 'wbp', 'ubp', 'urp', 'brp', 'bgp', 'rgp', 'rwp', 'gwp', 'gup', 'purplew', 'purpleu', 'purpleb', 'purpler', 'purpleg',
+ '2purple', 'purplep'], [1.2, 1.2]);
+loadManaSymbols(['bar.png', 'whitebar.png']);
+loadManaSymbols(['chaos'], [1.2, 1]);
+loadManaSymbols(['tk'], [0.8, 1]);
+loadManaSymbols(['planeswalker'], [0.6, 1.2]);
+loadManaSymbols(['+1', '+2', '+3', '+4', '+5', '+6', '+7', '+8', '+9', '-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '+0'], [1.6, 1]);
+function loadManaSymbols(manaSymbolPaths, size = [1, 1]) {
+ manaSymbolPaths.forEach(item => {
+ var manaSymbol = {};
+ if (typeof item == 'string') {
+ manaSymbol.name = item.split('.')[0];
+ manaSymbol.path = item;
+ } else {
+ manaSymbol.name = item[0].split('.')[0];
+ manaSymbol.path = item[0];
+ }
+ if (manaSymbol.name.includes('/')) {
+ manaSymbol.name = manaSymbol.name.split('/');
+ manaSymbol.name = manaSymbol.name[manaSymbol.name.length - 1];
+ }
+ if (typeof item != 'string') {
+ manaSymbol.back = item[1];
+ manaSymbol.backs = item[2];
+ for (var i = 0; i < item[2]; i ++) {
+ loadManaSymbols([manaSymbol.path.replace(manaSymbol.name, 'back' + i + item[1])])
+ }
+ }
+ manaSymbol.width = size[0];
+ manaSymbol.height = size[1];
+ manaSymbol.image = new Image();
+ manaSymbol.image.crossOrigin = 'anonymous';
+ var manaSymbolPath = '/img/manaSymbols/' + manaSymbol.path;
+ if (!manaSymbolPath.includes('.png')) {
+ manaSymbolPath += '.svg';
+ }
+ manaSymbol.image.src = fixUri(manaSymbolPath);
+ mana.set(manaSymbol.name, manaSymbol);
+ // manaSymbols.push(manaSymbol);
+ });
+}
+function findManaSymbolIndex(string) {
+ return mana.get(key) || -1;
+}
+function getManaSymbol(key) {
+ return mana.get(key);
+}
+//FRAME TAB
+function drawFrames() {
+ frameContext.clearRect(0, 0, frameCanvas.width, frameCanvas.height);
+ var frameToDraw = card.frames.slice().reverse();
+ var haveDrawnPrePTCanvas = false;
+ frameToDraw.forEach(item => {
+ if (item.image) {
+ if (!haveDrawnPrePTCanvas && drawTextBetweenFrames && item.name.includes('Power/Toughness')) {
+ haveDrawnPrePTCanvas = true;
+ frameContext.globalCompositeOperation = 'source-over';
+ frameContext.globalAlpha = 1;
+ frameContext.drawImage(prePTCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
+ }
+ frameContext.globalCompositeOperation = item.mode || 'source-over';
+ frameContext.globalAlpha = item.opacity / 100 || 1;
+ if (item.opacity == 0) {
+ frameContext.globalAlpha = 0;
+ }
+ var bounds = item.bounds || {};
+ var ogBounds = item.ogBounds || bounds;
+ frameX = Math.round(scaleX(bounds.x || 0));
+ frameY = Math.round(scaleY(bounds.y || 0));
+ frameWidth = Math.round(scaleWidth(bounds.width || 1));
+ frameHeight = Math.round(scaleHeight(bounds.height || 1));
+ frameMaskingContext.globalCompositeOperation = 'source-over';
+ frameMaskingContext.drawImage(black, 0, 0, frameMaskingCanvas.width, frameMaskingCanvas.height);
+ frameMaskingContext.globalCompositeOperation = 'source-in';
+ item.masks.forEach(mask => frameMaskingContext.drawImage(mask.image, scaleX((bounds.x || 0) - (ogBounds.x || 0) - ((ogBounds.x || 0) * ((bounds.width || 1) / (ogBounds.width || 1) - 1))), scaleY((bounds.y || 0) - (ogBounds.y || 0) - ((ogBounds.y || 0) * ((bounds.height || 1) / (ogBounds.height || 1) - 1))), scaleWidth((bounds.width || 1) / (ogBounds.width || 1)), scaleHeight((bounds.height || 1) / (ogBounds.height || 1))));
+ if (item.preserveAlpha) { //preserves alpha, and blends colors using an alpha that only cares about the mask(s), and the user-set opacity value
+ //draw the image onto a separate canvas to view its unaltered state
+ frameCompositingContext.clearRect(0, 0, frameCanvas.width, frameCanvas.height);
+ frameCompositingContext.drawImage(item.image, frameX, frameY, frameWidth, frameHeight);
+ //create pixel arrays for the existing image, new image, and alpha mask
+ var existingData = frameContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height)
+ var existingPixels = existingData.data;
+ var newPixels = frameCompositingContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height).data;
+ var maskPixels = frameMaskingContext.getImageData(0, 0, frameCanvas.width, frameCanvas.height).data;
+ const functionalAlphaMultiplier = frameContext.globalAlpha / 255;
+ //manually blends colors, basing blending-alpha on the masks and desired draw-opacity, but preserving alpha
+ for (var i = 0; i < existingPixels.length; i += 4) {
+ const functionalAlpha = maskPixels[i + 3] * functionalAlphaMultiplier //functional alpha = alpha ignoring source image
+ if (newPixels[i + 3] > 0) { //Only blend if the new image has alpha
+ existingPixels[ i ] = existingPixels[ i ] * (1 - functionalAlpha) + newPixels[ i ] * functionalAlpha; //RED
+ existingPixels[i + 1] = existingPixels[i + 1] * (1 - functionalAlpha) + newPixels[i + 1] * functionalAlpha; //GREEN
+ existingPixels[i + 2] = existingPixels[i + 2] * (1 - functionalAlpha) + newPixels[i + 2] * functionalAlpha; //BLUE
+ }
+ }
+ frameContext.putImageData(existingData, 0, 0);
+ } else {
+ //mask the image
+ frameMaskingContext.drawImage(item.image, frameX, frameY, frameWidth, frameHeight);
+ //color overlay
+ if (item.colorOverlayCheck) {frameMaskingContext.globalCompositeOperation = 'source-in'; frameMaskingContext.fillStyle = item.colorOverlay; frameMaskingContext.fillRect(0, 0, frameMaskingCanvas.width, frameMaskingCanvas.height);}
+ //HSL adjustments
+ if (item.hslHue || item.hslSaturation || item.hslLightness) {
+ hsl(frameMaskingCanvas, item.hslHue || 0, item.hslSaturation || 0, item.hslLightness || 0);
+ }
+ //erase mode
+ if (item.erase) {frameContext.globalCompositeOperation = 'destination-out';}
+ frameContext.drawImage(frameMaskingCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
+ }
+ }
+ });
+ if (!haveDrawnPrePTCanvas && drawTextBetweenFrames) {
+ haveDrawnPrePTCanvas = true;
+ frameContext.globalCompositeOperation = 'source-over';
+ frameContext.globalAlpha = 1;
+ frameContext.drawImage(prePTCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
+ }
+ drawCard();
+}
+function loadFramePacks(framePackOptions = []) {
+ document.querySelector('#selectFramePack').innerHTML = null;
+ framePackOptions.forEach(item => {
+ var framePackOption = document.createElement('option');
+ framePackOption.innerHTML = item.name;
+ if (item.value == 'disabled') {
+ framePackOption.disabled = true;
+ } else {
+ framePackOption.value = item.value;
+ }
+ document.querySelector('#selectFramePack').appendChild(framePackOption);
+ });
+ loadScript("/js/frames/pack" + document.querySelector('#selectFramePack').value + ".js");
+}
+function loadFramePack(frameOptions = availableFrames) {
+ resetDoubleClick();
+ document.querySelector('#frame-picker').innerHTML = null;
+ frameOptions.forEach(item => {
+ var frameOption = document.createElement('div');
+ frameOption.classList = 'frame-option hidden';
+ frameOption.onclick = frameOptionClicked;
+ var frameOptionImage = document.createElement('img');
+ frameOption.appendChild(frameOptionImage);
+ frameOptionImage.onload = function() {
+ this.parentElement.classList.remove('hidden');
+ }
+ if (!item.noThumb && !item.src.includes('/img/black.png')) {
+ frameOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
+ } else {
+ frameOptionImage.src = fixUri(item.src);
+ }
+ document.querySelector('#frame-picker').appendChild(frameOption);
+
+ })
+ document.querySelector('#mask-picker').innerHTML = '';
+ document.querySelector('#frame-picker').children[0].click();
+ if (localStorage.getItem('autoLoadFrameVersion') == 'true') {
+ document.querySelector('#loadFrameVersion').click();
+ }
+}
+function autoLoadFrameVersion() {
+ localStorage.setItem('autoLoadFrameVersion', document.querySelector('#autoLoadFrameVersion').checked);
+}
+function frameOptionClicked(event) {
+ const button = doubleClick(event, 'frame');
+ const clickedFrameOption = event.target.closest('.frame-option');
+ const newFrameIndex = getElementIndex(clickedFrameOption);
+ if (newFrameIndex != selectedFrameIndex || document.querySelector('#mask-picker').innerHTML == '') {
+ resetDoubleClick();
+ Array.from(document.querySelectorAll('.frame-option.selected')).forEach(element => element.classList.remove('selected'));
+ clickedFrameOption.classList.add('selected');
+ selectedFrameIndex = newFrameIndex;
+ if (!availableFrames[selectedFrameIndex].noDefaultMask) {
+ document.querySelector('#mask-picker').innerHTML = 'No Mask
';
+ } else {
+ document.querySelector('#mask-picker').innerHTML = '';
+ }
+ document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', No Mask)';
+ if (availableFrames[selectedFrameIndex].masks) {
+ availableFrames[selectedFrameIndex].masks.forEach(item => {
+ const maskOption = document.createElement('div');
+ maskOption.classList = 'mask-option hidden';
+ maskOption.onclick = maskOptionClicked;
+ const maskOptionImage = document.createElement('img');
+ maskOption.appendChild(maskOptionImage);
+ maskOptionImage.onload = function() {
+ this.parentElement.classList.remove('hidden');
+ }
+ maskOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
+ const maskOptionLabel = document.createElement('p');
+ maskOptionLabel.innerHTML = item.name;
+ maskOption.appendChild(maskOptionLabel);
+ document.querySelector('#mask-picker').appendChild(maskOption);
+ });
+ }
+ const firstChild = document.querySelector('#mask-picker').firstChild;
+ firstChild.classList.add('selected');
+ firstChild.click();
+ } else if (button) { button.click(); resetDoubleClick(); }
+}
+function maskOptionClicked(event) {
+ var button = doubleClick(event, 'mask');
+ const clickedMaskOption = event.target.closest('.mask-option');
+ (document.querySelector('.mask-option.selected').classList || document.querySelector('body').classList).remove('selected');
+ clickedMaskOption.classList.add('selected');
+ const newMaskIndex = getElementIndex(clickedMaskOption)
+ if (newMaskIndex != selectedMaskIndex) { button = null; }
+ selectedMaskIndex = newMaskIndex;
+ var selectedMaskName = 'No Mask'
+ if (selectedMaskIndex > 0) {selectedMaskName = availableFrames[selectedFrameIndex].masks[selectedMaskIndex - 1].name;}
+ document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', ' + selectedMaskName + ')';
+ if (button) { button.click(); resetDoubleClick(); }
+}
+function resetDoubleClick() {
+ lastFrameClick, lastMaskClick = null, null;
+}
+function doubleClick(event, maskOrFrame) {
+ const currentClick = (new Date()).getTime();
+ var lastClick = null;
+ if (maskOrFrame == 'mask') {
+ lastClick = lastMaskClick;
+ lastMaskClick = currentClick;
+ } else {
+ lastClick = lastFrameClick + 0;
+ lastFrameClick = currentClick + 0;
+ }
+ if (lastClick && lastClick + 500 > currentClick) {
+ var buttonID = null;
+ if (event.shiftKey) {
+ buttonID = '#addToRightHalf';
+ } else if (event.ctrlKey) {
+ buttonID = '#addToLeftHalf';
+ } else if (event.altKey) {
+ buttonID = '#addToMiddleThird';
+ } else {
+ buttonID = '#addToFull';
+ }
+ return document.querySelector(buttonID);
+ }
+ return null;
+}
+function cardFrameProperties(colors, manaCost, typeLine, power, style) {
+ var colors = colors.map(color => color.toUpperCase())
+ if ([
+ ['U', 'W'],
+ ['B', 'W'],
+ ['R', 'B'],
+ ['G', 'B'],
+ ['B', 'U'],
+ ['R', 'U'],
+ ['G', 'R'],
+ ['W', 'R'],
+ ['W', 'G'],
+ ['U', 'G']
+ ].map(arr => JSON.stringify(arr) === JSON.stringify(colors)).includes(true)) {
+ colors.reverse();
+ }
+
+ var isHybrid = manaCost.includes('/');
+
+ var rules;
+ if (style == 'Seventh') {
+ if (typeLine.includes('Land')) {
+ if (colors.length == 0 || colors.length > 2) {
+ rules = 'L';
+ } else {
+ rules = colors[0] + 'L';
+ }
+ } else {
+ if (colors.length == 1) {
+ rules = colors[0];
+ } else if (colors.length >=2) {
+ rules = 'M';
+ } else if (typeLine.includes("Artifact")) {
+ rules = 'A';
+ } else {
+ rules = 'C';
+ }
+ }
+
+ } else {
+ if (typeLine.includes('Land')) {
+ if (colors.length == 0) {
+ rules = 'L';
+ } else if (colors.length > 2) {
+ rules = 'ML';
+ } else {
+ rules = colors[0] + 'L';
+ }
+ } else if (colors.length > 2) {
+ if (style == 'Etched' && typeLine.includes('Artifact')) {
+ rules = 'A';
+ } else {
+ rules = 'M';
+ }
+ } else if (colors.length != 0) {
+ rules = colors[0];
+ } else if (style == 'Borderless' && !typeLine.includes('Artifact')) {
+ rules = 'C';
+ } else {
+ rules = 'A';
+ }
+ }
+
+ var rulesRight;
+ if (colors.length == 2) {
+ if (typeLine.includes('Land')) {
+ rulesRight = colors[1] + 'L';
+ } else if (style != 'Seventh') {
+ rulesRight = colors[1];
+ }
+ }
+
+ var pinline = rules;
+ var pinlineRight = rulesRight;
+
+ if (style == 'Seventh' && typeLine.includes('Land') && colors.length >= 2) {
+ pinline = 'L';
+ pinlineRight = null;
+ }
+
+ var typeTitle;
+ if (colors.length >= 2) {
+ if (isHybrid || typeLine.includes('Land')) {
+ if (colors.length >= 3) {
+ typeTitle = 'M';
+ } else {
+ typeTitle = 'L';
+ }
+ } else {
+ typeTitle = 'M';
+ }
+ } else if (typeLine.includes('Land')) {
+ if (colors.length == 0) {
+ typeTitle = 'L';
+ } else if (style == 'Etched') {
+ if (colors.length > 2) {
+ typeTitle = 'M';
+ } else if (colors.length == 1) {
+ typeTitle = colors[0];
+ } else {
+ typeTitle = 'L';
+ }
+ } else {
+ typeTitle = colors[0] + 'L';
+ }
+ } else if (colors.length == 1) {
+ typeTitle = colors[0];
+ } else if (style == 'Borderless' && !typeLine.includes('Artifact')) {
+ typeTitle = 'C';
+ } else {
+ typeTitle = 'A';
+ }
+
+ var pt;
+ if (power) {
+ if (typeLine.includes('Vehicle')) {
+ pt = 'V';
+ } else if (typeTitle == 'L') {
+ pt = 'C';
+ } else {
+ pt = typeTitle;
+ }
+ }
+
+ var frame;
+ if (style == 'Seventh') {
+ if (typeLine.includes('Land')) {
+ frame = 'L'
+ } else {
+ frame = pinline;
+ }
+ } else if (typeLine.includes('Land')) {
+ if (style == 'Etched') {
+ if (colors.length > 2) {
+ frame = 'M';
+ } else if (colors.length > 0) {
+ frame = colors[0];
+ } else {
+ frame = 'L';
+ }
+ } else {
+ frame = 'L';
+ }
+ } else if (typeLine.includes('Vehicle')) {
+ frame = 'V';
+ } else if (typeLine.includes('Artifact')) {
+ frame = 'A';
+ } else if (colors.length > 2) {
+ frame = 'M';
+ } else if (colors.length == 2) {
+ if (isHybrid || style == 'Etched') {
+ frame = colors[0];
+ } else {
+ frame = 'M';
+ }
+ } else if (colors.length == 1) {
+ frame = colors[0];
+ } else {
+ frame = 'L';
+ }
+
+ var frameRight;
+ if (!(typeLine.includes('Vehicle') || typeLine.includes('Artifact'))) {
+ if (colors.length == 2 && (isHybrid || style == 'Etched')) {
+ frameRight = colors[1];
+ }
+ }
+
+ return {
+ 'pinline': pinline,
+ 'pinlineRight': pinlineRight,
+ 'rules': rules,
+ 'rulesRight': rulesRight,
+ 'typeTitle': typeTitle,
+ 'pt': pt,
+ 'frame': frame,
+ 'frameRight': frameRight
+ }
+}
+var autoFramePack;
+function autoFrame() {
+ var frame = document.querySelector('#autoFrame').value;
+ if (frame == 'false') { autoFramePack = null; return; }
+
+ var colors = [];
+ if (card.text.type.text.toLowerCase().includes('land')) {
+ var rules = card.text.rules.text;
+ var flavorIndex = rules.indexOf('{flavor}');
+ if (flavorIndex == -1) {
+ flavorIndex = rules.indexOf('{oldflavor}');
+ }
+ if (flavorIndex != -1) {
+ rules = rules.substring(0, flavorIndex);
+ }
+
+ var lines = rules.split('\n');
+
+ lines.forEach(function(line) {
+ var addIndex = line.indexOf('Add');
+ var length = 3;
+ if (addIndex == -1) {
+ addIndex = line.toLowerCase().indexOf(' add');
+ length = 4;
+ }
+ if (addIndex != -1) {
+ var upToAdd = line.substring(addIndex+length).toLowerCase();
+ ['W', 'U', 'B', 'R', 'G'].forEach(function (color) {
+ if (upToAdd.includes('{' + color.toLowerCase() + '}')) {
+ colors.push(color);
+ }
+ });
+ }
+ });
+
+ if (!colors.includes('W') && (rules.toLowerCase().includes('plains') || card.text.type.text.toLowerCase().includes('plains'))) {
+ colors.push('W');
+ }
+ if (!colors.includes('U') && (rules.toLowerCase().includes('island') || card.text.type.text.toLowerCase().includes('island'))) {
+ colors.push('U');
+ }
+ if (!colors.includes('B') && (rules.toLowerCase().includes('swamp') || card.text.type.text.toLowerCase().includes('swamp'))) {
+ colors.push('B');
+ }
+ if (!colors.includes('R') && (rules.toLowerCase().includes('mountain') || card.text.type.text.toLowerCase().includes('mountain'))) {
+ colors.push('R');
+ }
+ if (!colors.includes('G') && (rules.toLowerCase().includes('forest') || card.text.type.text.toLowerCase().includes('forest'))) {
+ colors.push('G');
+ }
+
+ if (rules.toLowerCase().includes('search') && colors.length == 0) {
+ // TODO: This doesn't match Bog Wreckage
+ if (rules.includes('into your hand') || (rules.includes('tapped') && !(rules.toLowerCase().includes('enters the battlefield tapped')) && !(rules.toLowerCase().includes('untap')))) {
+ colors = [];
+ } else if (colors.length == 0) {
+ colors = ['W', 'U', 'B', 'R', 'G'];
+ }
+ }
+
+ if (rules.includes('any color') || rules.includes('any one color') || rules.includes('choose a color') || rules.includes('any combination of colors')) {
+ colors = ['W', 'U', 'B', 'R', 'G'];
+ }
+
+
+ } else {
+ colors = [...new Set(card.text.mana.text.toUpperCase().split('').filter(char => ['W', 'U', 'B', 'R', 'G'].includes(char)))];
+ }
+
+ var group;
+ if (frame == 'M15Regular-1') {
+ autoM15Frame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Standard-3';
+ } else if (frame == 'M15RegularNew') {
+ autoM15NewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Accurate';
+ } else if (frame == 'M15Eighth') {
+ autoM15EighthFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Custom';
+ } else if (frame == 'M15EighthUB') {
+ autoM15EighthUBFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Custom';
+ } else if (frame == 'UB') {
+ autoUBFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Showcase-5';
+ } else if (frame == 'UBNew') {
+ autoUBNewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Accurate';
+ } else if (frame == 'FullArtNew') {
+ autoFullArtNewFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Accurate';
+ } else if (frame == 'Circuit') {
+ autoCircuitFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ group = 'Custom';
+ } else if (frame == 'Etched') {
+ group = 'Showcase-5';
+ autoEtchedFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ } else if (frame == 'Praetors') {
+ group = 'Showcase-5';
+ autoPhyrexianFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ } else if (frame == 'Seventh') {
+ group = 'Misc-2';
+ autoSeventhEditionFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ } else if (frame == 'M15BoxTopper') {
+ group = 'Showcase-5';
+ autoExtendedArtFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, false);
+ } else if (frame == 'M15ExtendedArtShort') {
+ group = 'Showcase-5';
+ autoExtendedArtFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, true);
+ } else if (frame == '8th') {
+ group = 'Misc-2';
+ auto8thEditionFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text, false);
+ } else if (frame == 'Borderless') {
+ group = 'Showcase-5';
+ autoBorderlessFrame(colors, card.text.mana.text, card.text.type.text, card.text.pt.text);
+ }
+
+ if (autoFramePack != frame) {
+ loadScript('/js/frames/pack' + frame + '.js');
+ autoFramePack = frame;
+ }
+}
+async function autoUBFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp') || frame.name.includes('Gold Holo Stamp'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+
+ // Set frames
+
+ if (type_line.toLowerCase().includes('legendary')) {
+ if (properties.pinlineRight) {
+ frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Crown', true));
+ }
+ frames.push(makeUBFrameByLetter(properties.pinline, "Crown", false));
+ frames.push(makeUBFrameByLetter(properties.pinline, "Crown Border Cover", false));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Stamp', true));
+ }
+ frames.push(makeUBFrameByLetter(properties.pinline, "Stamp", false));
+ if (properties.pt) {
+ frames.push(makeUBFrameByLetter(properties.pt, 'PT', false));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeUBFrameByLetter(properties.pinlineRight, 'Pinline', true));
+ }
+ frames.push(makeUBFrameByLetter(properties.pinline, 'Pinline', false));
+ frames.push(makeUBFrameByLetter(properties.typeTitle, 'Type', false));
+ frames.push(makeUBFrameByLetter(properties.typeTitle, 'Title', false));
+ if (properties.pinlineRight) {
+ frames.push(makeUBFrameByLetter(properties.rulesRight, 'Rules', true));
+ }
+ frames.push(makeUBFrameByLetter(properties.rules, 'Rules', false));
+ if (properties.frameRight) {
+ frames.push(makeUBFrameByLetter(properties.frameRight, 'Frame', true));
+ }
+ frames.push(makeUBFrameByLetter(properties.frame, 'Frame', false));
+ frames.push(makeUBFrameByLetter(properties.frame, 'Border', false));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoUBNewFrame(colors, mana_cost, type_line, power) {
+ autoM15NewFrame(colors, mana_cost, type_line, power, 'ub');
+}
+async function autoFullArtNewFrame(colors, mana_cost, type_line, power) {
+ autoM15NewFrame(colors, mana_cost, type_line, power, 'fullart');
+}
+async function autoCircuitFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp') || frame.name.includes('Gold Holo Stamp'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+
+ // Set frames
+
+ if (type_line.toLowerCase().includes('legendary')) {
+ if (properties.pinlineRight) {
+ frames.push(makeCircuitFrameByLetter(properties.pinlineRight, 'Crown', true));
+ }
+ frames.push(makeCircuitFrameByLetter(properties.pinline, "Crown", false));
+ frames.push(makeCircuitFrameByLetter(properties.pinline, "Crown Border Cover", false));
+ }
+ if (properties.pt) {
+ frames.push(makeCircuitFrameByLetter(properties.pt, 'PT', false));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeCircuitFrameByLetter(properties.pinlineRight, 'Pinline', true));
+ }
+ frames.push(makeCircuitFrameByLetter(properties.pinline, 'Pinline', false));
+ frames.push(makeCircuitFrameByLetter(properties.typeTitle, 'Type', false));
+ frames.push(makeCircuitFrameByLetter(properties.typeTitle, 'Title', false));
+ if (properties.pinlineRight) {
+ frames.push(makeCircuitFrameByLetter(properties.rulesRight, 'Rules', true));
+ }
+ frames.push(makeCircuitFrameByLetter(properties.rules, 'Rules', false));
+ if (properties.frameRight) {
+ frames.push(makeCircuitFrameByLetter(properties.frameRight, 'Frame', true));
+ }
+ frames.push(makeCircuitFrameByLetter(properties.frame, 'Frame', false));
+ frames.push(makeCircuitFrameByLetter(properties.frame, 'Border', false));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoM15Frame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Crown', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, "Crown", false, style));
+ frames.push(makeM15FrameByLetter(properties.pinline, "Crown Border Cover", false, style));
+ }
+ if (properties.pt) {
+ frames.push(makeM15FrameByLetter(properties.pt, 'PT', false, style));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Pinline', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, 'Pinline', false, style));
+ frames.push(makeM15FrameByLetter(properties.typeTitle, 'Type', false, style));
+ frames.push(makeM15FrameByLetter(properties.typeTitle, 'Title', false, style));
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.rulesRight, 'Rules', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.rules, 'Rules', false, style));
+ if (properties.frameRight) {
+ frames.push(makeM15FrameByLetter(properties.frameRight, 'Frame', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.frame, 'Frame', false, style));
+ frames.push(makeM15FrameByLetter(properties.frame, 'Border', false, style));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoM15NewFrame(colors, mana_cost, type_line, power, style = 'regular') {
+ var frames;
+ if (style == 'ub') {
+ frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('Gray Holo Stamp'));
+ } else {
+ frames = card.frames.filter(frame => frame.name.includes('Extension'));
+ }
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+ if (style != 'ub' && style != 'fullart') {
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
+ }
+
+ frames.push(makeM15NewFrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Crown', true, style));
+ }
+ frames.push(makeM15NewFrameByLetter(properties.pinline, "Crown", false, style));
+ frames.push(makeM15NewFrameByLetter(properties.pinline, "Crown Border Cover", false, style));
+ }
+
+ if (style == 'ub') {
+ if (properties.pinlineRight) {
+ frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Stamp', true, style));
+ }
+ frames.push(makeM15NewFrameByLetter(properties.pinline, "Stamp", false, style));
+ }
+
+ if (properties.pt) {
+ frames.push(makeM15NewFrameByLetter(properties.pt, 'PT', false, style));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeM15NewFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
+ }
+ frames.push(makeM15NewFrameByLetter(properties.pinline, 'Pinline', false, style));
+ frames.push(makeM15NewFrameByLetter(properties.typeTitle, 'Type', false, style));
+ frames.push(makeM15NewFrameByLetter(properties.typeTitle, 'Title', false, style));
+ if (properties.pinlineRight) {
+ frames.push(makeM15NewFrameByLetter(properties.rulesRight, 'Rules', true, style));
+ }
+ frames.push(makeM15NewFrameByLetter(properties.rules, 'Rules', false, style));
+ if (properties.frameRight) {
+ frames.push(makeM15NewFrameByLetter(properties.frameRight, 'Frame', true, style));
+ }
+ frames.push(makeM15NewFrameByLetter(properties.frame, 'Frame', false, style));
+ frames.push(makeM15NewFrameByLetter(properties.frame, 'Border', false, style));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoM15EighthFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeM15FrameByLetter(properties.pinlineRight, 'Crown', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, "Crown", false, style));
+ frames.push(makeM15FrameByLetter(properties.pinline, "Crown Border Cover", false, style));
+ }
+ if (properties.pt) {
+ frames.push(makeM15EighthFrameByLetter(properties.pt, 'PT', false, style));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
+ }
+ frames.push(makeM15EighthFrameByLetter(properties.pinline, 'Pinline', false, style));
+ frames.push(makeM15EighthFrameByLetter(properties.typeTitle, 'Type', false, style));
+ frames.push(makeM15EighthFrameByLetter(properties.typeTitle, 'Title', false, style));
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthFrameByLetter(properties.rulesRight, 'Rules', true, style));
+ }
+ frames.push(makeM15EighthFrameByLetter(properties.rules, 'Rules', false, style));
+ if (properties.frameRight) {
+ frames.push(makeM15EighthFrameByLetter(properties.frameRight, 'Frame', true, style));
+ }
+ frames.push(makeM15EighthFrameByLetter(properties.frame, 'Frame', false, style));
+ frames.push(makeM15EighthFrameByLetter(properties.frame, 'Border', false, style));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoM15EighthUBFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Crown', true, style));
+ }
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinline, "Crown", false, style));
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinline, "Crown Border Cover", false, style));
+ }
+ if (properties.pt) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.pt, 'PT', false, style));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinlineRight, 'Pinline', true, style));
+ }
+ frames.push(makeM15EighthUBFrameByLetter(properties.pinline, 'Pinline', false, style));
+ frames.push(makeM15EighthUBFrameByLetter(properties.typeTitle, 'Type', false, style));
+ frames.push(makeM15EighthUBFrameByLetter(properties.typeTitle, 'Title', false, style));
+ if (properties.pinlineRight) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.rulesRight, 'Rules', true, style));
+ }
+ frames.push(makeM15EighthUBFrameByLetter(properties.rules, 'Rules', false, style));
+ if (properties.frameRight) {
+ frames.push(makeM15EighthUBFrameByLetter(properties.frameRight, 'Frame', true, style));
+ }
+ frames.push(makeM15EighthUBFrameByLetter(properties.frame, 'Frame', false, style));
+ frames.push(makeM15EighthUBFrameByLetter(properties.frame, 'Border', false, style));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoBorderlessFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Borderless');
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Inner Crown', true));
+ }
+ frames.push(makeM15FrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Crown', true));
+ }
+ frames.push(makeBorderlessFrameByLetter(properties.pinline, "Crown", false, style));
+ frames.push(makeBorderlessFrameByLetter(properties.pinline, "Legend Crown Outline", false))
+ frames.push(makeBorderlessFrameByLetter(properties.pinline, "Crown Border Cover", false));
+ }
+ if (properties.pt) {
+ frames.push(makeBorderlessFrameByLetter(properties.pt, 'PT', false));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeBorderlessFrameByLetter(properties.pinlineRight, 'Pinline', true));
+ }
+ frames.push(makeBorderlessFrameByLetter(properties.pinline, 'Pinline', false));
+ frames.push(makeBorderlessFrameByLetter(properties.typeTitle, 'Type', false));
+ frames.push(makeBorderlessFrameByLetter(properties.typeTitle, 'Title', false));
+ frames.push(makeBorderlessFrameByLetter(properties.rules, 'Rules', false));
+ frames.push(makeBorderlessFrameByLetter(properties.frame, 'Border', false));
+
+ // if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ // card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ // }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function auto8thEditionFrame(colors, mana_cost, type_line, power, colorshifted = false) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+
+ // Set frames
+ if (properties.pt) {
+ frames.push(make8thEditionFrameByLetter(properties.pt, 'PT', false, colorshifted));
+ }
+ if (properties.pinlineRight) {
+ frames.push(make8thEditionFrameByLetter(properties.pinlineRight, 'Pinline', true, colorshifted));
+ }
+ frames.push(make8thEditionFrameByLetter(properties.pinline, 'Pinline', false, colorshifted));
+ frames.push(make8thEditionFrameByLetter(properties.typeTitle, 'Type', false, colorshifted));
+ frames.push(make8thEditionFrameByLetter(properties.typeTitle, 'Title', false, colorshifted));
+ if (properties.pinlineRight) {
+ frames.push(make8thEditionFrameByLetter(properties.rulesRight, 'Rules', true, colorshifted));
+ }
+ frames.push(make8thEditionFrameByLetter(properties.rules, 'Rules', false, colorshifted));
+ if (properties.frameRight) {
+ frames.push(make8thEditionFrameByLetter(properties.frameRight, 'Frame', true, colorshifted));
+ }
+ frames.push(make8thEditionFrameByLetter(properties.frame, 'Frame', false, colorshifted));
+ frames.push(make8thEditionFrameByLetter(properties.frame, 'Border', false, colorshifted));
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoExtendedArtFrame(colors, mana_cost, type_line, power, short) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power);
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+ if (type_line.includes('Legendary')) {
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown Outline", false, style, short));
+
+ if (style == 'Nyx') {
+ if (properties.pinlineRight) {
+ frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Inner Crown', true, style, short));
+ }
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, 'Inner Crown', false, style, short));
+ }
+
+ if (properties.pinlineRight) {
+ frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Crown', true, style, short));
+ }
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown", false, style, short));
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Crown Border Cover", false, style, short));
+ } else {
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, "Title Cutout", false, style, short));
+ }
+ if (properties.pt) {
+ frames.push(makeExtendedArtFrameByLetter(properties.pt, 'PT', false, style, short));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makeExtendedArtFrameByLetter(properties.pinlineRight, 'Pinline', true, style, short));
+ }
+ frames.push(makeExtendedArtFrameByLetter(properties.pinline, 'Pinline', false, style, short));
+ frames.push(makeExtendedArtFrameByLetter(properties.typeTitle, 'Type', false, style, short));
+ frames.push(makeExtendedArtFrameByLetter(properties.typeTitle, 'Title', false, style, short));
+ if (properties.pinlineRight) {
+ frames.push(makeExtendedArtFrameByLetter(properties.rulesRight, 'Rules', true, style, short));
+ }
+ frames.push(makeExtendedArtFrameByLetter(properties.rules, 'Rules', false, style, short));
+ if (properties.frameRight) {
+ frames.push(makeExtendedArtFrameByLetter(properties.frameRight, 'Frame', true, style, short));
+ }
+ frames.push(makeExtendedArtFrameByLetter(properties.frame, 'Frame', false, style, short));
+ frames.push(makeExtendedArtFrameByLetter(properties.frame, 'Border', false, style, short));
+
+ if (card.text.pt && type_line.includes('Vehicle') && !card.text.pt.text.includes('fff')) {
+ card.text.pt.text = '{fontcolor#fff}' + card.text.pt.text;
+ }
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoEtchedFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Etched');
+ var style = 'regular';
+ if (type_line.toLowerCase().includes('snow')) {
+ style = 'snow';
+ } else if (type_line.toLowerCase().includes('enchantment creature') || type_line.toLowerCase().includes('enchantment artifact')) {
+ style = 'Nyx';
+ }
+
+ // Set frames
+
+ if (type_line.includes('Legendary')) {
+ if (style == 'Nyx') {
+ if (properties.frameRight) {
+ frames.push(makeEtchedFrameByLetter(properties.pinlineRight, 'Inner Crown', true));
+ }
+ frames.push(makeEtchedFrameByLetter(properties.pinline, 'Inner Crown', false, style));
+ }
+
+ if (properties.frameRight) {
+ frames.push(makeEtchedFrameByLetter(properties.frameRight, 'Crown', true));
+ }
+ frames.push(makeEtchedFrameByLetter(properties.frame, "Crown", false));
+ frames.push(makeEtchedFrameByLetter(properties.frame, "Crown Border Cover", false));
+ }
+ if (properties.pt) {
+ frames.push(makeEtchedFrameByLetter(properties.pt, 'PT', false));
+ }
+ frames.push(makeEtchedFrameByLetter(properties.typeTitle, 'Type', false));
+ frames.push(makeEtchedFrameByLetter(properties.typeTitle, 'Title', false));
+ if (properties.pinlineRight) {
+ frames.push(makeEtchedFrameByLetter(properties.rulesRight, 'Rules', true));
+ }
+ frames.push(makeEtchedFrameByLetter(properties.rules, 'Rules', false));
+ if (properties.frameRight) {
+ frames.push(makeEtchedFrameByLetter(properties.frameRight, 'Frame', true, style));
+ }
+ frames.push(makeEtchedFrameByLetter(properties.frame, 'Frame', false, style));
+ frames.push(makeEtchedFrameByLetter(properties.frame, 'Border', false));
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoPhyrexianFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Phyrexian');
+
+ // Set frames
+
+ if (type_line.toLowerCase().includes('legendary')) {
+ if (properties.pinlineRight) {
+ frames.push(makePhyrexianFrameByLetter(properties.pinlineRight, 'Crown', true));
+ }
+ frames.push(makePhyrexianFrameByLetter(properties.pinline, "Crown", false));
+ }
+ if (properties.pt) {
+ frames.push(makePhyrexianFrameByLetter(properties.pt, 'PT', false));
+ }
+ if (properties.pinlineRight) {
+ frames.push(makePhyrexianFrameByLetter(properties.pinlineRight, 'Pinline', true));
+ }
+ frames.push(makePhyrexianFrameByLetter(properties.pinline, 'Pinline', false));
+ frames.push(makePhyrexianFrameByLetter(properties.typeTitle, 'Type', false));
+ frames.push(makePhyrexianFrameByLetter(properties.typeTitle, 'Title', false));
+ if (properties.pinlineRight) {
+ frames.push(makePhyrexianFrameByLetter(properties.rulesRight, 'Rules', true));
+ }
+ frames.push(makePhyrexianFrameByLetter(properties.rules, 'Rules', false));
+ if (properties.frameRight) {
+ frames.push(makePhyrexianFrameByLetter(properties.frameRight, 'Frame', true));
+ }
+ frames.push(makePhyrexianFrameByLetter(properties.frame, 'Frame', false));
+ frames.push(makePhyrexianFrameByLetter(properties.frame, 'Border', false));
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+async function autoSeventhEditionFrame(colors, mana_cost, type_line, power) {
+ var frames = card.frames.filter(frame => frame.name.includes('Extension') || frame.name.includes('DCI Star'));
+
+ //clear the draggable frames
+ card.frames = [];
+ document.querySelector('#frame-list').innerHTML = null;
+
+ var properties = cardFrameProperties(colors, mana_cost, type_line, power, 'Seventh');
+
+ // Set frames
+ frames.push(makeSeventhEditionFrameByLetter(properties.pinline, 'Pinline', false));
+ if (properties.rulesRight) {
+ frames.push(makeSeventhEditionFrameByLetter(properties.rulesRight, 'Rules', true));
+ }
+ frames.push(makeSeventhEditionFrameByLetter(properties.rules, 'Rules', false));
+ frames.push(makeSeventhEditionFrameByLetter(properties.frame, 'Frame', false));
+ frames.push(makeSeventhEditionFrameByLetter(properties.pinline, 'Textbox Pinline', false));
+ frames.push(makeSeventhEditionFrameByLetter(properties.frame, 'Border', false));
+
+ card.frames = frames;
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+}
+function makeM15FrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/crowns/m15Crown' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1667,
+ 'width': 0.9454,
+ 'x': 0.0274,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' ' + mask + ' (' + style + ')',
+ 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0239,
+ 'width': 0.672,
+ 'x': 0.164,
+ 'y': 0.0239
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/m15/' + style.toLowerCase() + '/m15Frame' + letter + '.png',
+ }
+
+ if (style == 'snow') {
+ frame.src = frame.src.replace('m15Frame' + letter, letter.toLowerCase());
+ } else {
+ if (letter.includes('L') && letter.length > 1) {
+ frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
+ }
+
+ if (style == 'Nyx') {
+ frame.src = frame.src.replace('.png', 'Nyx.png');
+ }
+ }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+
+function makeM15NewFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if (letter.length == 2) {
+ letter = letter.split("").reverse().join("");
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[1];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {x:0, y:0, width:1, height:137/2814}
+ }
+ }
+
+ if (mask == "Crown") {
+ var framePath = '';
+ if (style == 'ub') {
+ framePath = 'ub/';
+ }
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/' + framePath + 'crowns/new/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {x:44/2010, y:53/2814, width:1922/2010, height:493/2814}
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' ' + mask + ' (' + style + ')',
+ 'src': '/img/frames/m15/innerCrowns/new/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {x:329/2010, y:70/2814, width:1353/2010, height:64/2814}
+ };
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ } else if (mask == "Stamp") {
+ if (style == 'ub') {
+ var frame = {
+ 'name': frameName + ' Holo Stamp',
+ 'src': '/img/frames/m15/new/ub/stamp/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {x:857/2015, y:2534/2814, width:299/2015, height:137/2814}
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+ }
+
+ if (mask == 'PT') {
+ var path = '/img/frames/m15/regular/m15PT';
+ if (style == 'ub') {
+ path = '/img/frames/m15/ub/pt/';
+ letter = letter.toLowerCase();
+ }
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': path + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var stylePath = '';
+ if (style != 'regular') {
+ stylePath = style.toLowerCase() + '/';
+ }
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/m15/new/' + stylePath + letter.toLowerCase() + '.png',
+ }
+
+ // if (letter.includes('L') && letter.length > 1) {
+ // frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
+ // }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/new/' + mask.toLowerCase() + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeM15EighthFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/crowns/m15Crown' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1667,
+ 'width': 0.9454,
+ 'x': 0.0274,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' ' + mask + ' (' + style + ')',
+ 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0239,
+ 'width': 0.672,
+ 'x': 0.164,
+ 'y': 0.0239
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 1901/2100
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/custom/m15-eighth/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
+ }
+
+ if (style != 'regular') {
+ frame.name = style.charAt(0).toUpperCase() + style.slice(1) + ' ' + frame.name;
+ }
+
+ if (mask) {
+ if (mask.toLowerCase() == 'border' || mask.toLowerCase() == 'frame') {
+ frame.masks = [
+ {
+ 'src': '/img/frames/custom/m15-eighth/regular/' + mask + '.png',
+ 'name': mask
+ }
+ ]
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeM15EighthUBFrameByLetter(letter, mask = false, maskToRightHalf = false) {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1667,
+ 'width': 0.9454,
+ 'x': 0.0274,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' ' + mask + ' (' + style + ')',
+ 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0239,
+ 'width': 0.672,
+ 'x': 0.164,
+ 'y': 0.0239
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/ub/pt/' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 1901/2100
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/custom/m15-eighth/ub/' + letter.toLowerCase() + '.png',
+ }
+
+ if (mask) {
+ if (mask.toLowerCase() == 'border' || mask.toLowerCase() == 'frame') {
+ frame.masks = [
+ {
+ 'src': '/img/frames/custom/m15-eighth/regular/' + mask + '.png',
+ 'name': mask
+ }
+ ]
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeBorderlessFrameByLetter(letter, mask = false, maskToRightHalf = false, style) {
+ letter = letter.toUpperCase();
+
+ if (letter == 'V') {
+ letter = 'A';
+ }
+
+ if (letter == 'ML') {
+ letter = 'M';
+ } else if (letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Legend Crown Outline") {
+ return {
+ 'name': 'Legend Crown Outline',
+ 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1062,
+ 'width': 0.944,
+ 'x': 0.028,
+ 'y': 0.0172
+ }
+ };
+ }
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'erase': true,
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/crowns/m15Crown' + letter + 'Floating.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1024,
+ 'width': 0.9387,
+ 'x': 0.0307,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' ' + mask + ' (' + style + ')',
+ 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0239,
+ 'width': 0.672,
+ 'x': 0.164,
+ 'y': 0.0239
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/borderless/pt/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.066666666666,
+ 'width': 0.182666666666,
+ 'x': 0.764,
+ 'y': 0.8861904761904762
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/m15/borderless/m15GenericShowcaseFrame' + letter + '.png',
+ }
+
+ if (letter.includes('L') && letter.length > 1) {
+ frame.src = frame.src.replace(('m15GenericShowcaseFrame' + letter), 'l' + letter[0].toLowerCase())
+ }
+
+ if (mask) {
+ if (mask == 'Pinline') {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/genericShowcase/m15GenericShowcaseMask' + mask + '.png',
+ 'name': mask
+ }
+ ];
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ];
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function make8thEditionFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if (mask == 'PT') {
+ if (letter.length > 1) {
+ letter = letter[0];
+ } else if (letter == 'C') {
+ letter = 'L';
+ }
+ }
+
+ if (letter == 'V') {
+ letter = 'A';
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/8th/pt/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0839,
+ 'width': 0.2147,
+ 'x': 0.7227,
+ 'y': 0.8796
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/8th/' + letter.toLowerCase() + '.png',
+ }
+
+ if (letter.includes('L') && letter.length > 1) {
+ frame.src = frame.src.replace(('m15Frame' + letter), 'l' + letter[0].toLowerCase())
+ }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/8th/' + mask.toLowerCase() + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (mask == 'Border') {
+ frame.masks[0].src = frame.masks[0].src.replace('.png', '.svg');
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeExtendedArtFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular', short = false) {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Legend Crown Outline") {
+ return {
+ 'name': 'Legend Crown Outline',
+ 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1062,
+ 'width': 0.944,
+ 'x': 0.028,
+ 'y': 0.0172
+ }
+ };
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/crowns/m15Crown' + letter + 'Floating.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1024,
+ 'width': 0.9387,
+ 'x': 0.0307,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Crown Outline") {
+ var frame = {
+ 'name': 'Legend Crown Outline',
+ 'src': '/img/frames/m15/crowns/m15CrownFloatingOutline.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1062,
+ 'width': 0.944,
+ 'x': 0.028,
+ 'y': 0.0172
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + '(' + style + ')' + mask,
+ 'src': '/img/frames/m15/innerCrowns/m15InnerCrown' + letter + style + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0239,
+ 'width': 0.672,
+ 'x': 0.164,
+ 'y': 0.0239
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/regular/m15PT' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame'
+ }
+
+ if (style != 'regular') {
+ frame.src = '/img/frames/extended/regular/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png';
+ if (short) {
+ frame.src = frame.src.replace('/regular/', '/shorter/');
+ }
+ } else if (short) {
+ frame.src = '/img/frames/m15/boxTopper/short/' + letter.toLowerCase() + '.png';
+ } else {
+ frame.src = '/img/frames/m15/boxTopper/m15BoxTopperFrame' + letter + '.png';
+ }
+
+ if (mask) {
+ if (mask == 'Title Cutout') {
+ if (short) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/extended/shorter/titleCutout.png',
+ 'name': 'Title Cutout'
+ }
+ ]
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/boxTopper/m15BoxTopperTitleCutout.png',
+ 'name': 'Title Cutout'
+ }
+ ]
+ }
+ } else if (short && ['Frame', 'Rules', 'Type', 'Pinline'].includes(mask)) {
+ var extension = mask == 'Type' ? '.png' : '.svg';
+
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/boxTopper/short/' + mask.toLowerCase().replace('rules', 'text') + extension,
+ 'name': mask
+ }
+ ]
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeUBFrameByLetter(letter, mask = false, maskToRightHalf = false) {
+ letter = letter.toUpperCase();
+
+ if (letter == 'C') {
+ letter = 'L';
+ }
+
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1667,
+ 'width': 0.9454,
+ 'x': 0.0274,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ } else if (mask == "Stamp") {
+ var frame = {
+ 'name': frameName + ' Holo Stamp',
+ 'src': '/img/frames/m15/ub/regular/stamp/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0486,
+ 'width': 0.1494,
+ 'x': 0.4254,
+ 'y': 0.9005
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/ub/pt/' + (letter == 'L' ? 'C' : letter).toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/m15/ub/regular/' + letter.toLowerCase() + '.png',
+ }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeCircuitFrameByLetter(letter, mask = false, maskToRightHalf = false) {
+ letter = letter.toUpperCase();
+
+ if (letter == 'C') {
+ letter = 'L';
+ }
+
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land',
+ 'ML': 'Multicolored Land'
+ }
+
+ if ((mask.includes('Crown') || mask == 'PT' || mask.includes('Stamp')) && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Border Cover',
+ 'src': '/img/black.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0177,
+ 'width': 0.9214,
+ 'x': 0.0394,
+ 'y': 0.0277
+ }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/m15/ub/crowns/m15Crown' + letter + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.1667,
+ 'width': 0.9454,
+ 'x': 0.0274,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/ub/pt/' + (letter == 'L' ? 'C' : letter).toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/custom/circuit/' + letter.toLowerCase() + '.png',
+ }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeEtchedFrameByLetter(letter, mask = false, maskToRightHalf = false, style = 'regular') {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle'
+ }
+
+ if (mask == 'PT' && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ if (letter == 'ML') {
+ letter = 'M';
+ } else if (letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ } else if (letter == 'V' && mask == 'Crown') {
+ letter = 'A';
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown Border Cover") {
+ return {
+ 'name': 'Legend Crown Cover',
+ 'src': '/img/frames/etched/regular/crowns/cover.svg',
+ 'masks': [],
+ 'bounds': { }
+ }
+ }
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legend Crown',
+ 'src': '/img/frames/etched/regular/crowns/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.092,
+ 'width': 0.9387,
+ 'x': 0.0307,
+ 'y': 0.0191
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == "Inner Crown") {
+ var frame = {
+ 'name': frameName + ' Inner Crown',
+ 'src': '/img/frames/etched/regular/innerCrowns/' + style.toLowerCase() + '/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {x:244/1500, y:51/2100, width:1012/1500, height:64/2100}
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/etched/regular/pt/' + letter.toLowerCase() + '.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0733,
+ 'width': 0.188,
+ 'x': 0.7573,
+ 'y': 0.8848
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/etched/regular/' + letter.toLowerCase() + '.png',
+ }
+
+ if (style != 'regular') {
+ frame.src = frame.src.replace('/regular/', '/regular/' + style.toLowerCase() + '/');
+ frame.name = frame.name += ' (' + style +')';
+ }
+
+ if (mask) {
+ frame.masks = [
+ {
+ 'src': '/img/frames/etched/regular/' + mask.toLowerCase() + '.svg',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makePhyrexianFrameByLetter(letter, mask = false, maskToRightHalf = false) {
+ if (letter == 'C' || letter == 'V') {
+ letter = 'L';
+ }
+
+ if (mask == 'Rules') {
+ mask = 'Rules Text';
+ }
+
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land'
+ }
+
+ if (mask == 'PT' && letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ if (letter == 'ML') {
+ letter = 'M';
+ } else if (letter.includes('L') && letter.length > 1) {
+ letter = letter[0];
+ }
+
+ var frameName = frameNames[letter];
+
+ if (mask == "Crown") {
+ var frame = {
+ 'name': frameName + ' Legendary Crown',
+ 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + 'Crown.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 100/2100,
+ 'width': 1,
+ 'x': 0,
+ 'y': 0
+ }
+ }
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ return frame;
+ }
+
+ if (mask == 'PT') {
+ return {
+ 'name': frameName + ' Power/Toughness',
+ 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + 'pt.png',
+ 'masks': [],
+ 'bounds': {
+ 'height': 0.0772,
+ 'width': 0.212,
+ 'x': 0.746,
+ 'y': 0.8858
+ }
+ }
+ }
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/m15/praetors/' + letter.toLowerCase() + '.png',
+ }
+
+ if (mask == 'Type' || mask == 'Title') {
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/regular/m15Mask' + mask + '.png',
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else if (mask) {
+ var extension = "png";
+ var name = mask.toLowerCase();
+ if (mask == 'Frame') {
+ extension = 'svg';
+ } else if (mask == 'Rules Text') {
+ extension = 'svg';
+ name = 'text';
+ }
+
+ frame.masks = [
+ {
+ 'src': '/img/frames/m15/praetors/' + name + '.' + extension,
+ 'name': mask
+ }
+ ]
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+function makeSeventhEditionFrameByLetter(letter, mask = false, maskToRightHalf = false) {
+ letter = letter.toUpperCase();
+ var frameNames = {
+ 'W': 'White',
+ 'U': 'Blue',
+ 'B': 'Black',
+ 'R': 'Red',
+ 'G': 'Green',
+ 'M': 'Multicolored',
+ 'A': 'Artifact',
+ 'L': 'Land',
+ 'C': 'Colorless',
+ 'V': 'Vehicle',
+ 'WL': 'White Land',
+ 'UL': 'Blue Land',
+ 'BL': 'Black Land',
+ 'RL': 'Red Land',
+ 'GL': 'Green Land'
+ }
+
+ if (letter == 'V') {
+ letter = 'A';
+ }
+
+ if (letter == 'ML') {
+ letter = 'L';
+ }
+
+ var frameName = frameNames[letter];
+
+ var frame = {
+ 'name': frameName + ' Frame',
+ 'src': '/img/frames/seventh/regular/' + letter.toLowerCase() + '.png'
+ };
+
+ if (mask) {
+ if (mask == 'Textbox Pinline') {
+ frame.masks = [
+ {
+ 'src': '/img/frames/seventh/regular/trim.svg',
+ 'name': 'Textbox Pinline'
+ }
+ ]
+ } else {
+ frame.masks = [
+ {
+ 'src': '/img/frames/seventh/regular/' + mask.toLowerCase() + '.svg',
+ 'name': mask
+ }
+ ]
+ }
+
+ if (maskToRightHalf) {
+ frame.masks.push({
+ 'src': '/img/frames/maskRightHalf.png',
+ 'name': 'Right Half'
+ });
+ }
+ } else {
+ frame.masks = [];
+ }
+
+ return frame;
+}
+async function addFrame(additionalMasks = [], loadingFrame = false) {
+ var frameToAdd = JSON.parse(JSON.stringify(availableFrames[selectedFrameIndex]));
+ var maskThumbnail = true;
+ if (!loadingFrame) {
+ // The frame is being added manually by the user, so we must process which mask(s) they have selected
+ var noDefaultMask = 0;
+ if (frameToAdd.noDefaultMask) {noDefaultMask = 1;}
+ if (frameToAdd.masks && selectedMaskIndex + noDefaultMask > 0) {
+ frameToAdd.masks = frameToAdd.masks.slice(selectedMaskIndex - 1 + noDefaultMask, selectedMaskIndex + noDefaultMask);
+ } else {
+ frameToAdd.masks = [];
+ maskThumbnail = false;
+ }
+ additionalMasks.forEach(item => {
+ if (item.name in replacementMasks) {
+ item.src = replacementMasks[item.name];
+ }
+ frameToAdd.masks.push(item);
+ });
+ // Likewise, we now add any complementary frames
+ if ('complementary' in frameToAdd && frameToAdd.masks.length == 0) {
+ if (typeof frameToAdd.complementary == 'number') {
+ frameToAdd.complementary = [frameToAdd.complementary];
+ }
+ const realFrameIndex = selectedFrameIndex;
+ for (const index of frameToAdd.complementary) {
+ selectedFrameIndex = index;
+ await addFrame();
+ }
+ selectedFrameIndex = realFrameIndex;
+ }
+ } else {
+ frameToAdd = loadingFrame;
+ if (frameToAdd.masks.length == 0 || (frameToAdd.masks[0].src.includes('/img/frames/mask'))) {
+ maskThumbnail = false;
+ }
+ }
+ frameToAdd.masks.forEach(item => {
+ item.image = new Image();
+ item.image.crossOrigin = 'anonymous';
+ item.image.src = blank.src;
+ item.image.onload = drawFrames;
+ item.image.src = fixUri(item.src);
+ });
+ frameToAdd.image = new Image();
+ frameToAdd.image.crossOrigin = 'anonymous'
+ frameToAdd.image.src = blank.src;
+ frameToAdd.image.onload = drawFrames;
+ if ('stretch' in frameToAdd) {
+ stretchSVG(frameToAdd);
+ } else {
+ frameToAdd.image.src = fixUri(frameToAdd.src);
+ }
+ if (!loadingFrame) {
+ card.frames.unshift(frameToAdd);
+ }
+ var frameElement = document.createElement('div');
+ frameElement.classList = 'draggable frame-element';
+ frameElement.draggable = 'true';
+ frameElement.ondragstart = dragStart;
+ frameElement.ondragend = dragEnd;
+ frameElement.ondragover = dragOver;
+ frameElement.ontouchstart = dragStart;
+ frameElement.ontouchend = dragEnd;
+ frameElement.ontouchmove = touchMove;
+ frameElement.onclick = frameElementClicked;
+ var frameElementImage = document.createElement('img');
+ if (frameToAdd.noThumb || frameToAdd.src.includes('/img/black.png')) {
+ frameElementImage.src = fixUri(frameToAdd.src);
+ } else {
+ frameElementImage.src = fixUri(frameToAdd.src.replace('.png', 'Thumb.png'));
+ }
+ frameElement.appendChild(frameElementImage);
+ var frameElementMask = document.createElement('img');
+ if (maskThumbnail) {
+ frameElementMask.src = fixUri(frameToAdd.masks[0].src.replace('.png', 'Thumb.png'));
+ } else {
+ frameElementMask.src = black.src;
+ }
+ frameElement.appendChild(frameElementMask);
+ var frameElementLabel = document.createElement('h4');
+ frameElementLabel.innerHTML = frameToAdd.name;
+ frameToAdd.masks.forEach(item => frameElementLabel.innerHTML += ', ' + item.name);
+ frameElement.appendChild(frameElementLabel);
+ var frameElementClose = document.createElement('h4');
+ frameElementClose.innerHTML = 'X';
+ frameElementClose.classList = 'frame-element-close';
+ frameElementClose.onclick = removeFrame;
+ frameElement.appendChild(frameElementClose);
+ document.querySelector('#frame-list').prepend(frameElement);
+ bottomInfoEdited();
+}
+function removeFrame(event) {
+ card.frames.splice(getElementIndex(event.target.parentElement), 1);
+ event.target.parentElement.remove();
+ drawFrames();
+ bottomInfoEdited();
+}
+function frameElementClicked(event) {
+ if (!event.target.classList.contains('frame-element-close')) {
+ var selectedFrameElement = event.target.closest('.frame-element');
+ selectedFrame = card.frames[Array.from(selectedFrameElement.parentElement.children).indexOf(selectedFrameElement)];
+ document.querySelector('#frame-element-editor').classList.add('opened');
+ selectedFrame.bounds = selectedFrame.bounds || {};
+ if (selectedFrame.ogBounds == undefined) {
+ selectedFrame.ogBounds = JSON.parse(JSON.stringify(selectedFrame.bounds));
+ }
+ // Basic manipulations
+ document.querySelector('#frame-editor-x').value = scaleWidth(selectedFrame.bounds.x || 0);
+ document.querySelector('#frame-editor-x').onchange = (event) => {selectedFrame.bounds.x = (event.target.value / card.width); drawFrames();}
+ document.querySelector('#frame-editor-y').value = scaleHeight(selectedFrame.bounds.y || 0);
+ document.querySelector('#frame-editor-y').onchange = (event) => {selectedFrame.bounds.y = (event.target.value / card.height); drawFrames();}
+ document.querySelector('#frame-editor-width').value = scaleWidth(selectedFrame.bounds.width || 1);
+ document.querySelector('#frame-editor-width').onchange = (event) => {selectedFrame.bounds.width = (event.target.value / card.width); drawFrames();}
+ document.querySelector('#frame-editor-height').value = scaleHeight(selectedFrame.bounds.height || 1);
+ document.querySelector('#frame-editor-height').onchange = (event) => {selectedFrame.bounds.height = (event.target.value / card.height); drawFrames();}
+ document.querySelector('#frame-editor-opacity').value = selectedFrame.opacity || 100;
+ document.querySelector('#frame-editor-opacity').onchange = (event) => {selectedFrame.opacity = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-erase').checked = selectedFrame.erase || false;
+ document.querySelector('#frame-editor-erase').onchange = (event) => {selectedFrame.erase = event.target.checked; drawFrames();}
+ document.querySelector('#frame-editor-alpha').checked = selectedFrame.preserveAlpha || false;
+ document.querySelector('#frame-editor-alpha').onchange = (event) => {selectedFrame.preserveAlpha = event.target.checked; drawFrames();}
+ document.querySelector('#frame-editor-color-overlay-check').checked = selectedFrame.colorOverlayCheck || false;
+ document.querySelector('#frame-editor-color-overlay-check').onchange = (event) => {selectedFrame.colorOverlayCheck = event.target.checked; drawFrames();}
+ document.querySelector('#frame-editor-color-overlay').value = selectedFrame.colorOverlay || false;
+ document.querySelector('#frame-editor-color-overlay').onchange = (event) => {selectedFrame.colorOverlay = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-hue').value = selectedFrame.hslHue || 0;
+ document.querySelector('#frame-editor-hsl-hue-slider').value = selectedFrame.hslHue || 0;
+ document.querySelector('#frame-editor-hsl-hue').onchange = (event) => {selectedFrame.hslHue = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-hue-slider').onchange = (event) => {selectedFrame.hslHue = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-saturation').value = selectedFrame.hslSaturation || 0;
+ document.querySelector('#frame-editor-hsl-saturation-slider').value = selectedFrame.hslSaturation || 0;
+ document.querySelector('#frame-editor-hsl-saturation').onchange = (event) => {selectedFrame.hslSaturation = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-saturation-slider').onchange = (event) => {selectedFrame.hslSaturation = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-lightness').value = selectedFrame.hslLightness || 0;
+ document.querySelector('#frame-editor-hsl-lightness-slider').value = selectedFrame.hslLightness || 0;
+ document.querySelector('#frame-editor-hsl-lightness').onchange = (event) => {selectedFrame.hslLightness = event.target.value; drawFrames();}
+ document.querySelector('#frame-editor-hsl-lightness-slider').onchange = (event) => {selectedFrame.hslLightness = event.target.value; drawFrames();}
+ // Removing masks
+ const selectMaskElement = document.querySelector('#frame-editor-masks');
+ selectMaskElement.innerHTML = null;
+ const maskOptionNone = document.createElement('option');
+ maskOptionNone.disabled = true;
+ maskOptionNone.innerHTML = 'None Selected';
+ selectMaskElement.appendChild(maskOptionNone);
+ selectedFrame.masks.forEach(mask => {
+ const maskOption = document.createElement('option');
+ maskOption.innerHTML = mask.name;
+ selectMaskElement.appendChild(maskOption);
+ });
+ selectMaskElement.selectedIndex = 0;
+ }
+}
+function frameElementMaskRemoved() {
+ const selectElement = document.querySelector('#frame-editor-masks');
+ const selectedOption = selectElement.value;
+ if (selectedOption != 'None Selected') {
+ selectElement.remove(selectElement.selectedIndex);
+ selectElement.selectedIndex = 0;
+ selectedFrame.masks.forEach(mask => {
+ if (mask.name == selectedOption) {
+ selectedFrame.masks = selectedFrame.masks.filter(item => item.name != selectedOption);
+ drawFrames();
+ }
+ });
+ }
+}
+function uploadMaskOption(imageSource) {
+ const uploadedMask = {name:`Uploaded Image (${customCount})`, src:imageSource, noThumb:true, image: new Image()};
+ customCount ++;
+ selectedFrame.masks.push(uploadedMask);
+ uploadedMask.image.onload = drawFrames;
+ uploadedMask.image.src = imageSource;
+}
+function uploadFrameOption(imageSource) {
+ const uploadedFrame = {name:`Uploaded Image (${customCount})`, src:imageSource, noThumb:true};
+ customCount ++;
+ availableFrames.push(uploadedFrame);
+ loadFramePack();
+}
+function hsl(canvas, inputH, inputS, inputL) {
+ //adjust inputs
+ var hue = parseInt(inputH) / 360;
+ var saturation = parseInt(inputS) / 100;
+ var lightness = parseInt(inputL) / 100;
+ //create needed objects
+ var context = canvas.getContext('2d')
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
+ var pixels = imageData.data;
+ //for every pixel...
+ for (var i = 0; i < pixels.length; i += 4) {
+ //grab rgb
+ var r = pixels[i];
+ var g = pixels[i + 1];
+ var b = pixels[i + 2];
+ //convert to hsl
+ var res = rgbToHSL(r, g, b);
+ h = res[0];
+ s = res[1];
+ l = res[2];
+ //make adjustments
+ h += hue;
+ while (h > 1) {h --;}
+ s = Math.min(Math.max(s + saturation, 0), 1);
+ l = Math.min(Math.max(l + lightness, 0), 1);
+ //convert back to rgb
+ res = hslToRGB(h, s, l);
+ r = res[0];
+ g = res[1];
+ b = res[2];
+ //and reassign
+ pixels[i] = r;
+ pixels[i + 1] = g;
+ pixels[i + 2] = b;
+ }
+ //then put the new image data back
+ context.putImageData(imageData, 0, 0);
+}
+function croppedCanvas(oldCanvas, sensitivity = 0) {
+ var oldContext = oldCanvas.getContext('2d');
+ var newCanvas = document.createElement('canvas');
+ var newContext = newCanvas.getContext('2d');
+ var pixels = oldContext.getImageData(0, 0, oldCanvas.width, oldCanvas.height).data;
+ var pixX = [];
+ var pixY = [];
+ for (var x = 0; x < oldCanvas.width; x += 1) {
+ for (var y = 0; y < oldCanvas.height; y += 1) {
+ if (pixels[(y * oldCanvas.width + x) * 4 + 3] > sensitivity) {
+ pixX.push(x);
+ pixY.push(y);
+ }
+ }
+ }
+ pixX.sort(function(a, b) { return a - b });
+ pixY.sort(function(a, b) { return a - b });
+ var n = pixX.length - 1;
+ var newWidth = 1 + pixX[n] - pixX[0];
+ var newHeight = 1 + pixY[n] - pixY[0];
+ newCanvas.width = newWidth;
+ newCanvas.height = newHeight;
+ newContext.putImageData(oldCanvas.getContext('2d').getImageData(pixX[0], pixY[0], newWidth, newHeight), 0, 0);
+ return newCanvas;
+}
+/*
+shoutout to https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion for providing the hsl-rgb conversion algorithms
+*/
+function rgbToHSL(r, g, b){
+ r /= 255, g /= 255, b /= 255;
+ var max = Math.max(r, g, b), min = Math.min(r, g, b);
+ var h, s, l = (max + min) / 2;
+
+ if(max == min){
+ h = s = 0; // achromatic
+ }else{
+ var d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch(max){
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+
+ return [h, s, l];
+}
+function hslToRGB(h, s, l){
+ var r, g, b;
+
+ if(s == 0){
+ r = g = b = l; // achromatic
+ }else{
+ var hue2rgb = function hue2rgb(p, q, t){
+ if(t < 0) t += 1;
+ if(t > 1) t -= 1;
+ if(t < 1/6) return p + (q - p) * 6 * t;
+ if(t < 1/2) return q;
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+ }
+
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3);
+ }
+
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
+}
+//TEXT TAB
+var writingText;
+var autoFrameTimer;
+function loadTextOptions(textObject, replace=true) {
+ var oldCardText = card.text || {};
+ Object.entries(oldCardText).forEach(item => {
+ savedTextContents[item[0]] = oldCardText[item[0]].text;
+ });
+ if (replace) {
+ card.text = textObject;
+ } else {
+ Object.keys(textObject).forEach(key => {
+ card.text[key] = textObject[key];
+ });
+ }
+ document.querySelector('#text-options').innerHTML = null;
+ Object.entries(card.text).forEach(item => {
+ if (oldCardText[item[0]]) {
+ card.text[item[0]].text = oldCardText[item[0]].text;
+ } else if (savedTextContents[item[0]]) {
+ card.text[item[0]].text = savedTextContents[item[0]];
+ }
+ var textOptionElement = document.createElement('h4');
+ textOptionElement.innerHTML = item[1].name;
+ textOptionElement.classList = 'selectable text-option'
+ textOptionElement.onclick = textOptionClicked;
+ document.querySelector('#text-options').appendChild(textOptionElement);
+ });
+ document.querySelector('#text-options').firstChild.click();
+ drawTextBuffer();
+ drawNewGuidelines();
+}
+function textOptionClicked(event) {
+ selectedTextIndex = getElementIndex(event.target);
+ document.querySelector('#text-editor').value = Object.entries(card.text)[selectedTextIndex][1].text;
+ document.querySelector('#text-editor-font-size').value = Object.entries(card.text)[selectedTextIndex][1].fontSize;
+ selectSelectable(event);
+}
+function textboxEditor() {
+ var selectedTextbox = card.text[Object.keys(card.text)[selectedTextIndex]];
+ document.querySelector('#textbox-editor').classList.add('opened');
+ document.querySelector('#textbox-editor-x').value = scaleWidth(selectedTextbox.x || 0);
+ document.querySelector('#textbox-editor-x').onchange = (event) => {selectedTextbox.x = (event.target.value / card.width); textEdited();}
+ document.querySelector('#textbox-editor-y').value = scaleHeight(selectedTextbox.y || 0);
+ document.querySelector('#textbox-editor-y').onchange = (event) => {selectedTextbox.y = (event.target.value / card.height); textEdited();}
+ document.querySelector('#textbox-editor-width').value = scaleWidth(selectedTextbox.width || 1);
+ document.querySelector('#textbox-editor-width').onchange = (event) => {selectedTextbox.width = (event.target.value / card.width); textEdited();}
+ document.querySelector('#textbox-editor-height').value = scaleHeight(selectedTextbox.height || 1);
+ document.querySelector('#textbox-editor-height').onchange = (event) => {selectedTextbox.height = (event.target.value / card.height); textEdited();}
+}
+function textEdited() {
+ card.text[Object.keys(card.text)[selectedTextIndex]].text = curlyQuotes(document.querySelector('#text-editor').value);
+ drawTextBuffer();
+ autoFrameBuffer();
+}
+function fontSizedEdited() {
+ card.text[Object.keys(card.text)[selectedTextIndex]].fontSize = document.querySelector('#text-editor-font-size').value;
+ drawTextBuffer();
+}
+function drawTextBuffer() {
+ clearTimeout(writingText);
+ writingText = setTimeout(drawText, 500);
+}
+function autoFrameBuffer() {
+ clearTimeout(autoFrameTimer);
+ autoFrameTimer = setTimeout(autoFrame, 500);
+}
+async function drawText() {
+ textContext.clearRect(0, 0, textCanvas.width, textCanvas.height);
+ prePTContext.clearRect(0, 0, prePTCanvas.width, prePTCanvas.height);
+ drawTextBetweenFrames = false;
+ for (var textObject of Object.entries(card.text)) {
+ await writeText(textObject[1], textContext);
+ continue;
+ }
+ if (drawTextBetweenFrames || redrawFrames) {
+ drawFrames();
+ if (!drawTextBetweenFrames) {
+ redrawFrames = false;
+ }
+ } else {
+ drawCard();
+ }
+}
+var justifyWidth = 90;
+function writeText(textObject, targetContext) {
+ //Most bits of info about text loaded, with defaults when needed
+ var textX = scaleX(textObject.x) || scaleX(0);
+ var textY = scaleY(textObject.y) || scaleY(0);
+ var textWidth = scaleWidth(textObject.width) || scaleWidth(1);
+ var textHeight = scaleHeight(textObject.height) || scaleHeight(1);
+ var startingTextSize = scaleHeight(textObject.size) || scaleHeight(0.038);
+ var textFontHeightRatio = 0.7;
+ var textBounded = textObject.bounded || true;
+ var textOneLine = textObject.oneLine || false;
+ var textManaCost = textObject.manaCost || false;
+ var textAllCaps = textObject.allCaps || false;
+ var textManaSpacing = scaleWidth(textObject.manaSpacing) || 0;
+ //Buffers the canvases accordingly
+ var canvasMargin = 300;
+ paragraphCanvas.width = textWidth + 2 * canvasMargin;
+ paragraphCanvas.height = textHeight + 2 * canvasMargin;
+ lineCanvas.width = textWidth + 2 * canvasMargin;
+ lineCanvas.height = startingTextSize + 2 * canvasMargin;
+ //Preps the text string
+ var splitString = '6GJt7eL8';
+ var rawText = textObject.text
+ if (document.querySelector('#hide-reminder-text').checked && textObject.name && textObject.name != 'Title' && textObject.name != 'Type' && textObject.name != 'Mana Cost' && textObject.name != 'Power/Toughness') {
+ var rulesText = rawText;
+ var flavorText = '';
+ var flavorIndex = rawText.indexOf('{flavor}') || rawText.indexOf('///');
+ if (flavorIndex >= 0) {
+ flavorText = rawText.substring(flavorIndex);
+ rulesText = rawText.substring(0, flavorIndex);
+ }
+
+ rulesText = rulesText.replace(/\([^\)]+\)/g, '');
+
+ rawText = rulesText + flavorText;
+ }
+ if (textAllCaps) {
+ rawText = rawText.toUpperCase();
+ }
+ if ((textObject.name == 'wizards' || textObject.name == 'copyright') && params.get('copyright') != null && (params.get('copyright') != '' || card.margins)) {
+ rawText = params.get('copyright'); //so people using CC for custom card games without WotC's IP can customize their copyright info
+ if (rawText == 'none') { rawText = ''; }
+ }
+ if (rawText.toLowerCase().includes('{cardname}') || rawText.toLowerCase().includes('~')) {
+ rawText = rawText.replace(/{cardname}|~/ig, getInlineCardName());
+ }
+ if (document.querySelector('#info-artist').value == '') {
+ rawText = rawText.replace('\uFFEE{savex2}{elemidinfo-artist}', '');
+ }
+ if (rawText.includes('///')) {
+ rawText = rawText.replace(/\/\/\//g, '{flavor}');
+ }
+ if (rawText.includes('//')) {
+ rawText = rawText.replace(/\/\//g, '{lns}');
+ }
+ if (card.version == 'pokemon') {
+ rawText = rawText.replace(/{flavor}/g, '{oldflavor}{fontsize-20}{fontgillsansbolditalic}');
+ } else if (card.version == 'dossier') {
+ rawText = rawText.replace(/{flavor}(.*)/g, function(v) { return '{/indent}{lns}{bar}{lns}{fixtextalign}' + v.replace(/{flavor}/g, '').toUpperCase(); });
+ } else if (!card.showsFlavorBar) {
+ rawText = rawText.replace(/{flavor}/g, '{oldflavor}');
+ }
+ rawText = rawText.replace(/ - /g, ' — ');
+ var splitText = rawText.replace(/\n/g, '{line}').replace(/{-}/g, '\u2014').replace(/{divider}/g, '{/indent}{lns}{bar}{lns}{fixtextalign}').replace(/{flavor}/g, '{/indent}{lns}{bar}{lns}{fixtextalign}{i}').replace(/{oldflavor}/g, '{/indent}{lns}{lns}{up30}{i}').replace(/{/g, splitString + '{').replace(/}/g, '}' + splitString).replace(/ /g, splitString + ' ' + splitString).split(splitString);
+ splitText = splitText.filter(item => item);
+ if (textObject.manaCost) {
+ splitText = splitText.filter(item => item != ' ');
+ }
+ if (textObject.vertical) {
+ newSplitText = [];
+ splitText.forEach((item, index) => {
+ if (item.includes('{') && item.includes('}')) {
+ newSplitText.push(item);
+ } else if (item == ' ') {
+ newSplitText.push(`{down${scaleHeight(0.01)}}`);
+ } else {
+ item.split('').forEach(char => {
+ if (char == '’') {
+ newSplitText.push(`{right${startingTextSize * 0.6}}`, '’', '{lns}', `{up${startingTextSize * 0.75}}`);
+ } else if (textManaCost && index == splitText.length-1) {
+ newSplitText.push(char);
+ } else {
+ newSplitText.push(char, '{lns}');
+ }
+ });
+ // newSplitText = newSplitText.concat(item.split(''));
+ }
+ });
+ splitText = newSplitText;
+ }
+ // if (textManaCost && textObject.arcStart > 0) {
+ // splitText.reverse();
+ // }
+ splitText.push('');
+ //Manages the redraw loop
+ var drawingText = true;
+ //Repeatedly tries to draw the text at smaller and smaller sizes until it fits
+ outerloop: while (drawingText) {
+ //Rest of the text info loaded that may have been changed by a previous attempt at drawing the text
+ var textColor = textObject.color || 'black';
+ var textFont = textObject.font || 'mplantin';
+ var textAlign = textObject.align || 'left';
+ var textJustify = textObject.justify || 'left';
+ var textShadowColor = textObject.shadow || 'black';
+ var textShadowOffsetX = scaleWidth(textObject.shadowX) || 0;
+ var textShadowOffsetY = scaleHeight(textObject.shadowY) || 0;
+ var textShadowBlur = scaleHeight(textObject.shadowBlur) || 0;
+ var textArcRadius = scaleHeight(textObject.arcRadius) || 0;
+ var manaSymbolColor = textObject.manaSymbolColor || null;
+ var textRotation = textObject.rotation || 0;
+ if (textArcRadius > 0) {
+ //Buffers the canvases accordingly
+ var canvasMargin = 300 + textArcRadius;
+ paragraphCanvas.width = textWidth + 2 * canvasMargin;
+ paragraphCanvas.height = textHeight + 2 * canvasMargin;
+ lineCanvas.width = textWidth + 2 * canvasMargin;
+ lineCanvas.height = startingTextSize + 2 * canvasMargin;
+ }
+ var textArcStart = textObject.arcStart || 0;
+ //Variables for tracking text position/size/font
+ var currentX = 0;
+ var startingCurrentX = 0;
+ var currentY = 0;
+ var lineY = 0;
+ var newLine = false;
+ var textFontExtension = '';
+ var textFontStyle = textObject.fontStyle || '';
+ var manaPlacementCounter = 0;
+ var realTextAlign = textAlign;
+ savedRollYPosition = null;
+ var savedRollColor = 'black';
+ var drawToPrePTCanvas = false;
+ var widestLineWidth = 0;
+ //variables that track various... things?
+ var textSize = startingTextSize;
+ var newLineSpacing = (textObject.lineSpacing || 0) * textSize;
+ var ptShift = [0, 0];
+ var permaShift = [0, 0];
+ var fillJustify = false;
+ //Finish prepping canvases
+ paragraphContext.clearRect(0, 0, paragraphCanvas.width, paragraphCanvas.height);
+ lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
+ lineContext.letterSpacing = (scaleWidth(textObject.kerning) || 0) + 'px';
+ // if (textFont == 'goudymedieval') {
+ // lineCanvas.style.letterSpacing = '3.5px';
+ // }
+ textSize += parseInt(textObject.fontSize || '0');
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ lineContext.fillStyle = textColor;
+ lineContext.shadowColor = textShadowColor;
+ lineContext.shadowOffsetX = textShadowOffsetX;
+ lineContext.shadowOffsetY = textShadowOffsetY;
+ lineContext.shadowBlur = textShadowBlur;
+ lineContext.strokeStyle = textObject.outlineColor || 'black';
+ var textOutlineWidth = scaleHeight(textObject.outlineWidth) || 0;
+
+ var hideBottomInfoBorder = card.hideBottomInfoBorder || false;
+ if (hideBottomInfoBorder && ['midLeft', 'topLeft', 'note', 'bottomLeft', 'wizards', 'bottomRight', 'rarity'].includes(textObject.name)) {
+ textOutlineWidth = 0;
+ }
+ lineContext.lineWidth = textOutlineWidth;
+ //Begin looping through words/codes
+ innerloop: for (word of splitText) {
+ var wordToWrite = word;
+ if (wordToWrite.includes('{') && wordToWrite.includes('}') || textManaCost || savedFont) {
+ var possibleCode = wordToWrite.toLowerCase().replace('{', '').replace('}', '');
+ wordToWrite = null;
+ if (possibleCode == 'line') {
+ newLine = true;
+ startingCurrentX = 0;
+ newLineSpacing = textSize * 0.35;
+ } else if (possibleCode == 'lns' || possibleCode == 'linenospace') {
+ newLine = true;
+ } else if (possibleCode == 'bar') {
+ var barWidth = textWidth * 0.96;
+ var barHeight = scaleHeight(0.03);
+ var barImageName = 'bar';
+ var barDistance = 0;
+ realTextAlign = textAlign;
+ textAlign = 'left';
+ if (card.version == 'cartoony') {
+ barImageName = 'cflavor';
+ barWidth = scaleWidth(0.8547);
+ barHeight = scaleHeight(0.0458);
+ barDistance = -0.23;
+ newLineSpacing = textSize * -0.23;
+ textSize -= scaleHeight(0.0086);
+ }
+ lineContext.drawImage(getManaSymbol(barImageName).image, canvasMargin + (textWidth - barWidth) / 2, canvasMargin + barDistance * textSize, barWidth, barHeight);
+ } else if (possibleCode == 'i') {
+ if (textFont == 'gilllsans' || textFont == 'neosans') {
+ textFontExtension = 'italic';
+ } else if (textFont == 'mplantin') {
+ textFontExtension = 'i';
+ textFontStyle = textFontStyle.replace('italic ', '');
+ } else {
+ textFontExtension = '';
+ if (!textFontStyle.includes('italic')) {textFontStyle += 'italic ';}
+ }
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ } else if (possibleCode == '/i') {
+ textFontExtension = '';
+ textFontStyle = textFontStyle.replace('italic ', '');
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ } else if (possibleCode == 'bold') {
+ if (textFont == 'gillsans') {
+ textFontExtension = 'bold';
+ } else {
+ if (!textFontStyle.includes('bold')) {textFontStyle += 'bold ';}
+ }
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ } else if (possibleCode == '/bold') {
+ if (textFont == 'gillsans') {
+ textFontExtension = '';
+ } else {
+ textFontStyle = textFontStyle.replace('bold ', '');
+ }
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ } else if (possibleCode == 'left') {
+ textAlign = 'left';
+ } else if (possibleCode == 'center') {
+ textAlign = 'center';
+ } else if (possibleCode == 'right') {
+ textAlign = 'right';
+ } else if (possibleCode == 'justify-left') {
+ textJustify = 'left';
+ } else if (possibleCode == 'justify-center') {
+ textJustify = 'center';
+ } else if (possibleCode == 'justify-right') {
+ textJustify = 'right';
+ } else if (possibleCode.includes('conditionalcolor')) {
+ var codeParams = possibleCode.split(":");
+ for (var eligibleFrame of codeParams[1].split(",")) {
+ eligibleFrame = eligibleFrame.replace(/_/g, " ");
+ if (card.frames.findIndex(element => element.name.toLowerCase().includes(eligibleFrame)) != -1) {
+ textColor = codeParams[2];
+ lineContext.fillStyle = textColor;
+ }
+ }
+ } else if (possibleCode.includes('fontcolor')) {
+ textColor = possibleCode.replace('fontcolor', '');
+ lineContext.fillStyle = textColor;
+ } else if (possibleCode.includes('fontsize')) {
+ if (possibleCode.slice(-2) === "pt") {
+ textSize = (parseInt(possibleCode.replace('fontsize', '').replace('pt', '')) * 600 / 72) || 0;
+ } else {
+ textSize += parseInt(possibleCode.replace('fontsize', '')) || 0;
+ }
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ } else if (possibleCode.includes('font') || savedFont) {
+ textFont = word.replace('{font', '').replace('}', '');
+ if (savedFont) {
+ textFont = savedFont;
+ wordToWrite = word;
+ }
+ textFontExtension = '';
+ textFontStyle = '';
+ lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
+ savedFont = null;
+ } else if (possibleCode.includes('outlinecolor')) {
+ lineContext.strokeStyle = possibleCode.replace('outlinecolor', '');
+ } else if (possibleCode.includes('outline')) {
+ textOutlineWidth = parseInt(possibleCode.replace('outline', ''));
+ lineContext.lineWidth = textOutlineWidth;
+ } else if (possibleCode.includes('upinline')) {
+ lineY -= parseInt(possibleCode.replace('upinline', '')) || 0;
+ } else if (possibleCode.substring(0, 2) == 'up' && possibleCode != 'up') {
+ currentY -= parseInt(possibleCode.replace('up', '')) || 0;
+ } else if (possibleCode.includes('down')) {
+ currentY += parseInt(possibleCode.replace('down', '')) || 0;
+ } else if (possibleCode.includes('left')) {
+ currentX -= parseInt(possibleCode.replace('left', '')) || 0;
+ } else if (possibleCode.includes('right')) {
+ currentX += parseInt(possibleCode.replace('right', '')) || 0;
+ } else if (possibleCode.includes('shadow')) {
+ if (possibleCode.includes('color')) {
+ textShadowColor = possibleCode.replace('shadowcolor', '');
+ lineContext.shadowColor = textShadowColor;
+ } else if (possibleCode.includes('blur')) {
+ textShadowBlur = parseInt(possibleCode.replace('shadowblur', '')) || 0;
+ lineContext.shadowBlur = textShadowBlur
+ } else if (possibleCode.includes('shadowx')) {
+ textShadowOffsetX = parseInt(possibleCode.replace('shadowx', '')) || 0;
+ lineContext.shadowOffsetX = textShadowOffsetX;
+ } else if (possibleCode.includes('shadowy')) {
+ textShadowOffsetY = parseInt(possibleCode.replace('shadowy', '')) || 0;
+ lineContext.shadowOffsetY = textShadowOffsetY;
+ } else {
+ textShadowOffsetX = parseInt(possibleCode.replace('shadow', '')) || 0;
+ textShadowOffsetY = textShadowOffsetX;
+ lineContext.shadowOffsetX = textShadowOffsetX;
+ lineContext.shadowOffsetY = textShadowOffsetY;
+ }
+ } else if (possibleCode == 'planechase') {
+ var planechaseHeight = textSize * 1.8;
+ lineContext.drawImage(getManaSymbol('chaos').image, currentX + canvasMargin, canvasMargin, planechaseHeight * 1.2, planechaseHeight);
+ currentX += planechaseHeight * 1.3;
+ startingCurrentX += planechaseHeight * 1.3;
+ } else if (possibleCode == 'indent') {
+ startingCurrentX += currentX;
+ currentY -= 10;
+ } else if (possibleCode == '/indent') {
+ startingCurrentX = 0;
+ } else if (possibleCode.includes('elemid')) {
+ if (document.querySelector('#' + word.replace('{elemid', '').replace('}', ''))) {
+ wordToWrite = document.querySelector('#' + word.replace('{elemid', '').replace('}', '')).value || '';
+ }
+ if (word.includes('set')) {
+ var bottomTextSubstring = card.bottomInfo.midLeft.text.substring(0, card.bottomInfo.midLeft.text.indexOf(' {savex}')).replace('{elemidinfo-set}', document.querySelector('#info-set').value || '').replace('{elemidinfo-language}', document.querySelector('#info-language').value || '');
+ justifyWidth = lineContext.measureText(bottomTextSubstring).width;
+ } else if (word.includes('number') && wordToWrite.includes('/') && card.version != 'pokemon') {
+ fillJustify = true;
+ wordToWrite = Array.from(wordToWrite).join(' ');
+ }
+ } else if (possibleCode == 'savex') {
+ savedTextXPosition = currentX;
+ } else if (possibleCode == 'loadx') {
+ if (savedTextXPosition > currentX) {
+ currentX = savedTextXPosition;
+ }
+ } else if (possibleCode == 'savex2') {
+ savedTextXPosition2 = currentX;
+ } else if (possibleCode == 'loadx2') {
+ if (savedTextXPosition2 > currentX) {
+ currentX = savedTextXPosition2;
+ }
+ } else if (possibleCode.includes('ptshift')) {
+ if (card.frames.findIndex(element => element.name.toLowerCase().includes('power/toughness')) >= 0 || card.version.includes('planeswalker') || ['commanderLegends', 'm21', 'mysticalArchive', 'customDualLands', 'feuerAmeiseKaldheim'].includes(card.version)) {
+ ptShift[0] = scaleWidth(parseFloat(possibleCode.replace('ptshift', '').split(',')[0]));
+ ptShift[1] = scaleHeight(parseFloat(possibleCode.split(',')[1]));
+ }
+ } else if (possibleCode.includes('rollcolor')) {
+ savedRollColor = possibleCode.replace('rollcolor', '') || 'black';
+ } else if (possibleCode.includes('roll')) {
+ drawTextBetweenFrames = true;
+ redrawFrames = true;
+ drawToPrePTCanvas = true;
+ if (savedRollYPosition == null) {
+ savedRollYPosition = currentY;
+ } else {
+ savedRollYPosition = -1;
+ }
+ savedFont = textFont;
+ lineContext.font = textFontStyle + textSize + 'px ' + 'belerenb' + textFontExtension;
+ wordToWrite = possibleCode.replace('roll', '');
+ } else if (possibleCode.includes('permashift')) {
+ permaShift = [parseFloat(possibleCode.replace('permashift', '').split(',')[0]), parseFloat(possibleCode.split(',')[1])];
+ } else if (possibleCode.includes('arcradius')) {
+ textArcRadius = parseInt(possibleCode.replace('arcradius', '')) || 0;
+ } else if (possibleCode.includes('arcstart')) {
+ textArcStart = parseFloat(possibleCode.replace('arcstart', '')) || 0;
+ } else if (possibleCode.includes('rotate')) {
+ textRotation = parseInt(possibleCode.replace('rotate', '')) % 360;
+ } else if (possibleCode === 'manacolordefault') {
+ manaSymbolColor = null;
+ } else if (possibleCode.includes('manacolor')) {
+ manaSymbolColor = possibleCode.replace('manacolor', '') || 'white';
+ } else if (possibleCode.includes('fixtextalign')) {
+ textAlign = realTextAlign;
+ } else if (possibleCode.includes('kerning')) {
+ lineContext.letterSpacing = possibleCode.replace('kerning', '') + 'px';
+ lineContext.font = lineContext.font; //necessary for the letterspacing update to be recognized
+ } else if (getManaSymbol(possibleCode.replaceAll('/', '')) != undefined || getManaSymbol(possibleCode.replaceAll('/', '').split('').reverse().join('')) != undefined) {
+ possibleCode = possibleCode.replaceAll('/', '')
+ var manaSymbol;
+ if (textObject.manaPrefix && (getManaSymbol(textObject.manaPrefix + possibleCode) != undefined || getManaSymbol(textObject.manaPrefix + possibleCode.split('').reverse().join('')) != undefined)) {
+ manaSymbol = getManaSymbol(textObject.manaPrefix + possibleCode) || getManaSymbol(textObject.manaPrefix + possibleCode.split('').reverse().join(''));
+ } else {
+ manaSymbol = getManaSymbol(possibleCode) || getManaSymbol(possibleCode.split('').reverse().join(''));
+ }
+ var manaSymbolSpacing = textSize * 0.04 + textManaSpacing;
+ var manaSymbolWidth = manaSymbol.width * textSize * 0.78;
+ var manaSymbolHeight = manaSymbol.height * textSize * 0.78;
+ var manaSymbolX = currentX + canvasMargin + manaSymbolSpacing;
+ var manaSymbolY = canvasMargin + textSize * 0.34 - manaSymbolHeight / 2;
+ if (textObject.manaPlacement) {
+ manaSymbolX = scaleWidth(textObject.manaPlacement.x[manaPlacementCounter] || 0) + canvasMargin;
+ manaSymbolY = canvasMargin;
+ currentY = scaleHeight(textObject.manaPlacement.y[manaPlacementCounter] || 0);
+ manaPlacementCounter ++;
+ newLine = true;
+ } else if (textObject.manaLayout) {
+ var layoutOption = 0;
+ var manaSymbolCount = splitText.length - 1;
+ while (textObject.manaLayout[layoutOption].max < manaSymbolCount && layoutOption < textObject.manaLayout.length - 1) {
+ layoutOption ++;
+ }
+ var manaLayout = textObject.manaLayout[layoutOption];
+ if (manaLayout.pos[manaPlacementCounter] == undefined) {
+ manaLayout.pos[manaPlacementCounter] = [0, 0];
+ }
+ manaSymbolX = scaleWidth(manaLayout.pos[manaPlacementCounter][0] || 0) + canvasMargin;
+ manaSymbolY = canvasMargin;
+ currentY = scaleHeight(manaLayout.pos[manaPlacementCounter][1] || 0);
+ manaPlacementCounter ++;
+ manaSymbolWidth *= manaLayout.size;
+ manaSymbolHeight *= manaLayout.size;
+ newLine = true;
+ }
+ if (textObject.manaImageScale) {
+ currentX -= (textObject.manaImageScale - 1) * manaSymbolWidth;
+ manaSymbolX -= (textObject.manaImageScale - 1) / 2 * manaSymbolWidth;
+ manaSymbolY -= (textObject.manaImageScale - 1) / 2 * manaSymbolHeight;
+ manaSymbolWidth *= textObject.manaImageScale;
+ manaSymbolHeight *= textObject.manaImageScale;
+ }
+ //fake shadow begins
+ var fakeShadow = lineCanvas.cloneNode();
+ var fakeShadowContext = fakeShadow.getContext('2d');
+ fakeShadowContext.clearRect(0, 0, fakeShadow.width, fakeShadow.height);
+ var backImage = null;
+ if (manaSymbol.backs) {
+ backImage = getManaSymbol('back' + Math.floor(Math.random() * manaSymbol.backs) + manaSymbol.back).image;
+ }
+ if (textArcRadius > 0) {
+ if (manaSymbol.backs) {
+ fakeShadowContext.drawImageArc(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
+ }
+ fakeShadowContext.drawImageArc(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
+ } else if (manaSymbolColor) {
+ fakeShadowContext.fillImage(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, manaSymbolColor);
+ } else {
+ if (manaSymbol.backs) {
+ fakeShadowContext.drawImage(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
+ }
+ fakeShadowContext.drawImage(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
+ }
+ lineContext.drawImage(fakeShadow, 0, 0);
+ //fake shadow ends (thanks, safari)
+ currentX += manaSymbolWidth + manaSymbolSpacing * 2;
+ } else {
+ wordToWrite = word;
+ }
+ }
+
+ if (wordToWrite && lineContext.font.endsWith('belerenb')) {
+ wordToWrite = wordToWrite.replace(/f(?:\s|$)/g, '\ue006').replace(/h(?:\s|$)/g, '\ue007').replace(/m(?:\s|$)/g, '\ue008').replace(/n(?:\s|$)/g, '\ue009').replace(/k(?:\s|$)/g, '\ue00a');
+ }
+
+ //if the word goes past the max line width, go to the next line
+ if (wordToWrite && lineContext.measureText(wordToWrite).width + currentX >= textWidth && textArcRadius == 0) {
+ if (textOneLine && startingTextSize > 1) {
+ //doesn't fit... try again at a smaller text size?
+ startingTextSize -= 1;
+ continue outerloop;
+ }
+ newLine = true;
+ }
+ //if we need a new line, go to the next line
+ if ((newLine && !textOneLine) || splitText.indexOf(word) == splitText.length - 1) {
+ var horizontalAdjust = 0
+ if (textAlign == 'center') {
+ horizontalAdjust = (textWidth - currentX) / 2;
+ } else if (textAlign == 'right') {
+ horizontalAdjust = textWidth - currentX;
+ }
+ if (currentX > widestLineWidth) {
+ widestLineWidth = currentX;
+ }
+ paragraphContext.drawImage(lineCanvas, horizontalAdjust, currentY);
+ lineY = 0;
+ lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
+ // boxes for 'roll a d20' cards
+ if (savedRollYPosition != null && (newLineSpacing != 0 || !(newLine && !textOneLine))) {
+ if (savedRollYPosition != -1) {
+ paragraphContext.globalCompositeOperation = 'destination-over';
+ paragraphContext.globalAlpha = 0.25;
+ paragraphContext.fillStyle = savedRollColor;
+ paragraphContext.fillRect(canvasMargin - textSize * 0.1, savedRollYPosition + canvasMargin - textSize * 0.28, paragraphCanvas.width - 2 * canvasMargin + textSize * 0.2, currentY - savedRollYPosition + textSize * 1.3);
+ paragraphContext.globalCompositeOperation = 'source-over';
+ paragraphContext.globalAlpha = 1;
+ savedRollYPosition = -1;
+ } else {
+ savedRollYPosition = null;
+ }
+ }
+ //reset
+ currentX = startingCurrentX;
+ currentY += textSize + newLineSpacing;
+ newLineSpacing = (textObject.lineSpacing || 0) * textSize;
+ newLine = false;
+ }
+ //if there's a word to write, it's not a space on a new line, and it's allowed to write words, then we write the word
+ if (wordToWrite && (currentX != startingCurrentX || wordToWrite != ' ') && !textManaCost) {
+ var justifySettings = {
+ maxSpaceSize: 6,
+ minSpaceSize: 0
+ };
+
+ if (textArcRadius > 0) {
+ lineContext.fillTextArc(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, textArcRadius, textArcStart, currentX, textOutlineWidth);
+ } else {
+ if (textOutlineWidth >= 1) {
+ if (fillJustify) {
+ lineContext.strokeJustifyText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, justifyWidth, justifySettings);
+ } else {
+ lineContext.strokeText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
+ }
+ }
+ if (fillJustify) {
+ lineContext.fillJustifyText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, justifyWidth, justifySettings);
+ } else {
+ lineContext.fillText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
+ }
+ }
+
+ if (fillJustify) {
+ currentX += lineContext.measureJustifiedText(wordToWrite, justifyWidth, justifySettings);
+ } else {
+ currentX += lineContext.measureText(wordToWrite).width;
+ }
+ }
+ if (currentY > textHeight && textBounded && !textOneLine && startingTextSize > 1 && textArcRadius == 0) {
+ //doesn't fit... try again at a smaller text size?
+ startingTextSize -= 1;
+ continue outerloop;
+ }
+ if (splitText.indexOf(word) == splitText.length - 1) {
+ //should manage vertical centering here
+ var verticalAdjust = 0;
+ if (!textObject.noVerticalCenter) {
+ verticalAdjust = (textHeight - currentY + textSize * 0.15) / 2;
+ }
+ var finalHorizontalAdjust = 0;
+ const horizontalAdjustUnit = (textWidth - widestLineWidth) / 2;
+ if (textJustify == 'right' && textAlign != 'right') {
+ finalHorizontalAdjust = 2 * horizontalAdjustUnit;
+ if (textAlign == 'center') {
+ finalHorizontalAdjust = horizontalAdjustUnit;
+ }
+ } else if (textJustify == 'center' && textAlign != 'center') {
+ finalHorizontalAdjust = horizontalAdjustUnit;
+ if (textAlign == 'right') {
+ finalHorizontalAdjust = - horizontalAdjustUnit;
+ }
+ }
+ var trueTargetContext = targetContext;
+ if (drawToPrePTCanvas) {
+ trueTargetContext = prePTContext;
+ }
+ if (textRotation) {
+ trueTargetContext.save();
+ trueTargetContext
+ const shapeX = textX + ptShift[0];
+ const shapeY = textY + ptShift[1];
+ trueTargetContext.translate(shapeX, shapeY);
+ trueTargetContext.rotate(Math.PI * textRotation / 180);
+ trueTargetContext.drawImage(paragraphCanvas, permaShift[0] - canvasMargin + finalHorizontalAdjust, verticalAdjust - canvasMargin + permaShift[1]);
+ trueTargetContext.restore();
+ } else {
+ trueTargetContext.drawImage(paragraphCanvas, textX - canvasMargin + ptShift[0] + permaShift[0] + finalHorizontalAdjust, textY - canvasMargin + verticalAdjust + ptShift[1] + permaShift[1]);
+ }
+ drawingText = false;
+ }
+ }
+ }
+}
+CanvasRenderingContext2D.prototype.fillTextArc = function(text, x, y, radius, startRotation, distance = 0, outlineWidth = 0) {
+ this.save();
+ this.translate(x - distance + scaleWidth(0.5), y + radius);
+ this.rotate(startRotation + widthToAngle(distance, radius));
+ for (var i = 0; i < text.length; i++) {
+ var letter = text[i];
+ if (outlineWidth >= 1) {
+ this.strokeText(letter, 0, -radius);
+ }
+ this.fillText(letter, 0, -radius);
+ this.rotate(widthToAngle(this.measureText(letter).width, radius));
+ }
+ this.restore();
+}
+CanvasRenderingContext2D.prototype.drawImageArc = function(image, x, y, width, height, radius, startRotation, distance = 0) {
+ this.save();
+ this.translate(x - distance + scaleWidth(0.5), y + radius);
+ this.rotate(startRotation + widthToAngle(distance, radius));
+ this.drawImage(image, 0, -radius, width, height);
+ this.restore();
+}
+CanvasRenderingContext2D.prototype.fillImage = function(image, x, y, width, height, color = 'white', margin = 10) {
+ var canvas = document.createElement('canvas');
+ canvas.width = width + margin * 2;
+ canvas.height = height + margin * 2;
+ var context = canvas.getContext('2d');
+ context.drawImage(image, margin, margin, width, height);
+ context.globalCompositeOperation = 'source-in';
+ context.fillStyle = pinlineColors(color);
+ context.fillRect(0, 0, width + margin * 2, height + margin * 2);
+ this.drawImage(canvas, x - margin, y - margin, width + margin * 2, height + margin * 2);
+}
+
+const FILL = 0; //const to indicate filltext render
+const STROKE = 1;
+const MEASURE = 2;
+var maxSpaceSize = 3; // Multiplier for max space size. If greater then no justification applied
+var minSpaceSize = 0.5; // Multiplier for minimum space size
+function renderTextJustified(ctx, text, x, y, width, renderType) {
+ var splitChar = " ";
+
+ var words, wordsWidth, count, spaces, spaceWidth, adjSpace, renderer, i, textAlign, useSize, totalWidth;
+ textAlign = ctx.textAlign;
+ ctx.textAlign = "left";
+ wordsWidth = 0;
+ words = text.split(splitChar).map(word => {
+ var w = ctx.measureText(word).width;
+ wordsWidth += w;
+ return {
+ width: w,
+ word: word
+ };
+ });
+ // count = num words, spaces = number spaces, spaceWidth normal space size
+ // adjSpace new space size >= min size. useSize Reslting space size used to render
+ count = words.length;
+ spaces = count - 1;
+ spaceWidth = ctx.measureText(splitChar).width;
+ adjSpace = Math.max(spaceWidth * minSpaceSize, (width - wordsWidth) / spaces);
+ useSize = adjSpace > spaceWidth * maxSpaceSize ? spaceWidth : adjSpace;
+ totalWidth = wordsWidth + useSize * spaces;
+ if (renderType === MEASURE) { // if measuring return size
+ ctx.textAlign = textAlign;
+ return totalWidth;
+ }
+ renderer = renderType === FILL ? ctx.fillText.bind(ctx) : ctx.strokeText.bind(ctx); // fill or stroke
+ switch(textAlign) {
+ case "right":
+ x -= totalWidth;
+ break;
+ case "end":
+ x += width - totalWidth;
+ break;
+ case "center": // intentional fall through to default
+ x -= totalWidth / 2;
+ default:
+ }
+ if (useSize === spaceWidth) { // if space size unchanged
+ renderer(text, x, y);
+ } else {
+ for(i = 0; i < count; i += 1) {
+ renderer(words[i].word,x,y);
+ x += words[i].width;
+ x += useSize;
+ }
+ }
+ ctx.textAlign = textAlign;
+}
+
+// Parse vet and set settings object.
+function justifiedTextSettings(settings) {
+ var min,max;
+ var vetNumber = (num, defaultNum) => {
+ num = num !== null && num !== null && !isNaN(num) ? num : defaultNum;
+ if(num < 0){
+ num = defaultNum;
+ }
+ return num;
+ }
+ if(settings === undefined || settings === null){
+ return;
+ }
+ max = vetNumber(settings.maxSpaceSize, maxSpaceSize);
+ min = vetNumber(settings.minSpaceSize, minSpaceSize);
+ if(min > max){
+ return;
+ }
+ minSpaceSize = min;
+ maxSpaceSize = max;
+}
+CanvasRenderingContext2D.prototype.fillJustifyText = function(text, x, y, width, settings) {
+ justifiedTextSettings(settings);
+ renderTextJustified(this, text, x, y, width, FILL);
+}
+CanvasRenderingContext2D.prototype.strokeJustifyText = function(text, x, y, width, settings){
+ justifiedTextSettings(settings);
+ renderTextJustified(this, text, x, y, width, STROKE);
+}
+CanvasRenderingContext2D.prototype.measureJustifiedText = function(text, width, settings) {
+ justifiedTextSettings(settings);
+ renderTextJustified(this, text, 0, 0, width, MEASURE);
+}
+
+function widthToAngle(width, radius) {
+ return width / radius;
+}
+function curlyQuotes(input) {
+ return input.replace(/ '/g, ' ‘').replace(/^'/, '‘').replace(/'/g, '’').replace(/ "/g, ' “').replace(/" /g, '” ').replace(/\."/, '.”').replace(/"$/, '”').replace(/"\)/g, '”)').replace(/"/g, '“');
+}
+function pinlineColors(color) {
+ return color.replace('white', '#fcfeff').replace('blue', '#0075be').replace('black', '#272624').replace('red', '#ef3827').replace('green', '#007b43')
+}
+async function addTextbox(textboxType) {
+ if (textboxType == 'Nickname' && !card.text.nickname && card.text.title) {
+ await loadTextOptions({nickname: {name:'Nickname', text:card.text.title.text, x:0.14, y:0.1129, width:0.72, height:0.0243, oneLine:true, font:'mplantini', size:0.0229, color:'white', shadowX:0.0014, shadowY:0.001, align:'center'}}, false);
+ var nickname = card.text.title;
+ nickname.name = 'Nickname';
+ card.text.title = card.text.nickname;
+ card.text.title.name = 'Title';
+ card.text.nickname = nickname;
+ } else if (textboxType == 'Power/Toughness' && !card.text.pt) {
+ loadTextOptions({pt: {name:'Power/Toughness', text:'', x:0.7928, y:0.902, width:0.1367, height:0.0372, size:0.0372, font:'belerenbsc', oneLine:true, align:'center'}}, false);
+ } else if (textboxType == 'DateStamp' && !card.text.dateStamp) {
+ loadTextOptions({dateStamp: {name:'Date Stamp', text:'', x:0.11, y:0.5072, width:0.78, height:0.0286, size:0.0286, font:'belerenb', oneLine:true, align:'right', color:'#ffd35b', shadowX:-0.0007, shadowY:-0.001}}, false);
+ }
+}
+//ART TAB
+function uploadArt(imageSource, otherParams) {
+ art.src = imageSource;
+ if (otherParams && otherParams == 'autoFit') {
+ art.onload = function() {
+ autoFitArt();
+ art.onload = artEdited;
+ };
+ }
+}
+function artEdited() {
+ card.artSource = art.src;
+ card.artX = document.querySelector('#art-x').value / card.width;
+ card.artY = document.querySelector('#art-y').value / card.height;
+ card.artZoom = document.querySelector('#art-zoom').value / 100;
+ card.artRotate = document.querySelector('#art-rotate').value;
+ drawCard();
+}
+function autoFitArt() {
+ document.querySelector('#art-rotate').value = 0;
+ if (art.width / art.height > scaleWidth(card.artBounds.width) / scaleHeight(card.artBounds.height)) {
+ document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - scaleHeight(card.marginY));
+ document.querySelector('#art-zoom').value = (scaleHeight(card.artBounds.height) / art.height * 100).toFixed(1);
+ document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - (document.querySelector('#art-zoom').value / 100 * art.width - scaleWidth(card.artBounds.width)) / 2 - scaleWidth(card.marginX));
+ } else {
+ document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - scaleWidth(card.marginX));
+ document.querySelector('#art-zoom').value = (scaleWidth(card.artBounds.width) / art.width * 100).toFixed(1);
+ document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - (document.querySelector('#art-zoom').value / 100 * art.height - scaleHeight(card.artBounds.height)) / 2 - scaleHeight(card.marginY));
+ }
+ artEdited();
+}
+
+function centerArtX() {
+ document.querySelector('#art-rotate').value = 0;
+ if (art.width / art.height > scaleWidth(card.artBounds.width) / scaleHeight(card.artBounds.height)) {
+ document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - (document.querySelector('#art-zoom').value / 100 * art.width - scaleWidth(card.artBounds.width)) / 2 - scaleWidth(card.marginX));
+ } else {
+ document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - scaleWidth(card.marginX));
+ }
+ artEdited();
+}
+
+function centerArtY() {
+ document.querySelector('#art-rotate').value = 0;
+ document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - (document.querySelector('#art-zoom').value / 100 * art.height - scaleHeight(card.artBounds.height)) / 2 - scaleHeight(card.marginY));
+ artEdited();
+}
+
+function artFromScryfall(scryfallResponse) {
+ scryfallArt = []
+ const artIndex = document.querySelector('#art-index');
+ artIndex.innerHTML = null;
+ var optionIndex = 0;
+ scryfallResponse.forEach(card => {
+ if (card.image_uris && (card.object == 'card' || card.type_line != 'Card') && card.artist) {
+ scryfallArt.push(card);
+ var option = document.createElement('option');
+ option.innerHTML = `${card.name} (${card.set.toUpperCase()} - ${card.artist})`;
+ option.value = optionIndex;
+ artIndex.appendChild(option);
+ optionIndex ++;
+ }
+ });
+
+ if (document.querySelector('#importAllPrints').checked) {
+ // If importing unique prints, the art should change to match the unique print selected.
+
+ // First we find the illustration ID of the imported print
+ var illustrationID = scryfallCard[document.querySelector('#import-index').value].illustration_id;
+
+ // Find all unique arts for that card
+ var artIllustrations = scryfallArt.map(card => card.illustration_id);
+
+ // Find the art that matches the selected print
+ var index = artIllustrations.indexOf(illustrationID);
+ if (index < 0) {
+ // Couldn't find art
+ index = 0;
+ }
+
+ // Use that art
+ artIndex.value = index;
+ }
+
+ changeArtIndex();
+}
+function changeArtIndex() {
+ const artIndexValue = document.querySelector('#art-index').value;
+ if (artIndexValue != 0 || artIndexValue == '0') {
+ const scryfallCardForArt = scryfallArt[artIndexValue];
+ uploadArt(scryfallCardForArt.image_uris.art_crop, 'autoFit');
+ artistEdited(scryfallCardForArt.artist);
+ if (params.get('mtgpics') != null) {
+ imageURL(`https://www.mtgpics.com/pics/art/${scryfallCardForArt.set.toLowerCase()}/${("00" + scryfallCardForArt.collector_number).slice(-3)}.jpg`, tryMTGPicsArt);
+ }
+ }
+}
+function tryMTGPicsArt(src) {
+ var attemptedImage = new Image();
+ attemptedImage.onload = function() {
+ if (this.complete) {
+ art.onload = function() {
+ autoFitArt();
+ art.onload = artEdited;
+ };
+ art.src = this.src;
+ }
+ }
+ attemptedImage.src = src;
+}
+function initDraggableArt() {
+ previewCanvas.onmousedown = artStartDrag;
+ previewCanvas.onmousemove = artDrag;
+ previewCanvas.onmouseout = artStopDrag;
+ previewCanvas.onmouseup = artStopDrag;
+ draggingArt = false;
+ lastArtDragTime = 0;
+}
+function artStartDrag(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ startX = parseInt(e.clientX);
+ startY = parseInt(e.clientY);
+ draggingArt = true;
+}
+function artDrag(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (draggingArt && Date.now() > lastArtDragTime + 25) {
+ lastArtDragTime = Date.now();
+ if (e.shiftKey || e.ctrlKey) {
+ startX = parseInt(e.clientX);
+ const endY = parseInt(e.clientY);
+ if (e.ctrlKey) {
+ document.querySelector('#art-rotate').value = Math.round((parseFloat(document.querySelector('#art-rotate').value) - (startY - endY) / 10) % 360 * 10) / 10;
+ } else {
+ document.querySelector('#art-zoom').value = Math.round((parseFloat(document.querySelector('#art-zoom').value) * (1.002 ** (startY - endY))) * 10) / 10;
+ }
+ startY = endY;
+ artEdited();
+ } else {
+ const endX = parseInt(e.clientX);
+ const endY = parseInt(e.clientY);
+ var changeX = (endX - startX) * 2;
+ var changeY = (endY - startY) * 2;
+ if (card.landscape) {
+ const temp = changeX;
+ changeX = -changeY;
+ changeY = temp;
+ }
+ document.querySelector('#art-x').value = parseInt(document.querySelector('#art-x').value) + changeX;
+ document.querySelector('#art-y').value = parseInt(document.querySelector('#art-y').value) + changeY;
+ startX = endX;
+ startY = endY;
+ artEdited();
+ }
+
+ }
+}
+function artStopDrag(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (draggingArt) {
+ draggingArt = false;
+ }
+}
+//SET SYMBOL TAB
+function uploadSetSymbol(imageSource, otherParams) {
+ setSymbol.src = imageSource;
+ if (otherParams && otherParams == 'resetSetSymbol') {
+ setSymbol.onload = function() {
+ resetSetSymbol();
+ setSymbol.onload = setSymbolEdited;
+ };
+ }
+}
+function setSymbolEdited() {
+ card.setSymbolSource = setSymbol.src;
+ if (document.querySelector('#lockSetSymbolURL').checked) {
+ localStorage.setItem('lockSetSymbolURL', card.setSymbolSource);
+ }
+ localStorage.setItem('set-symbol-source', document.querySelector('#set-symbol-source').value);
+ card.setSymbolX = document.querySelector('#setSymbol-x').value / card.width;
+ card.setSymbolY = document.querySelector('#setSymbol-y').value / card.height;
+ card.setSymbolZoom = document.querySelector('#setSymbol-zoom').value / 100;
+ drawCard();
+}
+function resetSetSymbol() {
+ if (card.setSymbolBounds == undefined) {
+ return;
+ }
+ document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x));
+ document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y));
+ var setSymbolZoom;
+ if (setSymbol.width / setSymbol.height > scaleWidth(card.setSymbolBounds.width) / scaleHeight(card.setSymbolBounds.height)) {
+ setSymbolZoom = (scaleWidth(card.setSymbolBounds.width) / setSymbol.width * 100).toFixed(1);
+ } else {
+ setSymbolZoom = (scaleHeight(card.setSymbolBounds.height) / setSymbol.height * 100).toFixed(1);
+ }
+ document.querySelector('#setSymbol-zoom').value = setSymbolZoom;
+ if (card.setSymbolBounds.horizontal == 'center') {
+ document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) / 2 - scaleWidth(card.marginX));
+ } else if (card.setSymbolBounds.horizontal == 'right') {
+ document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) - scaleWidth(card.marginX));
+ }
+ if (card.setSymbolBounds.vertical == 'center') {
+ document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) / 2 - scaleHeight(card.marginY));
+ } else if (card.setSymbolBounds.vertical == 'bottom') {
+ document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) - scaleHeight(card.marginY));
+ }
+ setSymbolEdited();
+}
+function fetchSetSymbol() {
+ var setCode = document.querySelector('#set-symbol-code').value.toLowerCase() || 'cmd';
+ if (document.querySelector('#lockSetSymbolCode').checked) {
+ localStorage.setItem('lockSetSymbolCode', setCode);
+ }
+ var setRarity = document.querySelector('#set-symbol-rarity').value.toLowerCase().replace('uncommon', 'u').replace('common', 'c').replace('rare', 'r').replace('mythic', 'm') || 'c';
+ if (['sld', 'a22', 'a23', 'j22'].includes(setCode.toLowerCase())) {
+ uploadSetSymbol(fixUri(`/img/setSymbols/custom/${setCode.toLowerCase()}-${setRarity}.png`), 'resetSetSymbol');
+ } else if (['cc', 'logan', 'joe'].includes(setCode.toLowerCase())) {
+ uploadSetSymbol(fixUri(`/img/setSymbols/custom/${setCode.toLowerCase()}-${setRarity}.svg`), 'resetSetSymbol');
+ } else if (document.querySelector("#set-symbol-source").value == 'gatherer') {
+ if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
+ uploadSetSymbol('http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=' + setCode + '&size=large&rarity=' + setRarity, 'resetSetSymbol');
+ } else if (document.querySelector("#set-symbol-source").value == 'hexproof') {
+ if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
+ uploadSetSymbol('https://api.hexproof.io/symbols/set/' + setCode + '/' + setRarity, 'resetSetSymbol');
+ } else {
+ var extension = 'svg';
+ if (['moc', 'ltr', 'ltc', 'cmm', 'who', 'scd', 'woe', 'wot', 'woc', 'lci', 'lcc', 'mkm', 'mkc', 'otj', 'otc'].includes(setCode.toLowerCase())) {
+ extension = 'png';
+ }
+ if (setSymbolAliases.has(setCode.toLowerCase())) setCode = setSymbolAliases.get(setCode.toLowerCase());
+ uploadSetSymbol(fixUri(`/img/setSymbols/official/${setCode.toLowerCase()}-${setRarity}.` + extension), 'resetSetSymbol');
+ }
+}
+function lockSetSymbolCode() {
+ var savedValue = '';
+ if (document.querySelector('#lockSetSymbolCode').checked) {
+ savedValue = document.querySelector('#set-symbol-code').value;
+ }
+ localStorage.setItem('lockSetSymbolCode', savedValue);
+}
+function lockSetSymbolURL() {
+ var savedValue = '';
+ if (document.querySelector('#lockSetSymbolURL').checked) {
+ savedValue = card.setSymbolSource;
+ }
+ localStorage.setItem('lockSetSymbolURL', savedValue);
+}
+//WATERMARK TAB
+function uploadWatermark(imageSource, otherParams) {
+ watermark.src = imageSource;
+ if (otherParams && otherParams == 'resetWatermark') {
+ watermark.onload = function() {
+ resetWatermark();
+ watermark.onload = watermarkEdited;
+ };
+ }
+}
+function watermarkLeftColor(c) {
+ card.watermarkLeft = c;
+ watermarkEdited();
+}
+function watermarkRightColor(c) {
+ card.watermarkRight = c;
+ watermarkEdited();
+}
+function watermarkEdited() {
+ card.watermarkSource = watermark.src;
+ card.watermarkX = document.querySelector('#watermark-x').value / card.width;
+ card.watermarkY = document.querySelector('#watermark-y').value / card.height;
+ card.watermarkZoom = document.querySelector('#watermark-zoom').value / 100;
+ if (card.watermarkLeft == "none" && document.querySelector('#watermark-left').value != "none") {
+ card.watermarkLeft = document.querySelector('#watermark-left').value;
+ }
+ // card.watermarkLeft = document.querySelector('#watermark-left').value;
+ // card.watermarkRight = document.querySelector('#watermark-right').value;
+ card.watermarkOpacity = document.querySelector('#watermark-opacity').value / 100;
+ watermarkContext.globalCompositeOperation = 'source-over';
+ watermarkContext.globalAlpha = 1;
+ watermarkContext.clearRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
+ if (card.watermarkLeft != 'none' && !card.watermarkSource.includes('/blank.png') && card.watermarkZoom > 0) {
+ if (card.watermarkRight != 'none') {
+ watermarkContext.drawImage(right, scaleX(0), scaleY(0), scaleWidth(1), scaleHeight(1));
+ watermarkContext.globalCompositeOperation = 'source-in';
+ if (card.watermarkRight == 'default') {
+ watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
+ } else {
+ watermarkContext.fillStyle = card.watermarkRight;
+ watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
+ }
+ watermarkContext.globalCompositeOperation = 'destination-over';
+ }
+ if (card.watermarkLeft == 'default') {
+ watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
+ } else {
+ watermarkContext.fillStyle = card.watermarkLeft;
+ watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
+ }
+ watermarkContext.globalCompositeOperation = 'destination-in';
+ watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
+ watermarkContext.globalAlpha = card.watermarkOpacity;
+ watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
+ }
+ drawCard();
+}
+function resetWatermark() {
+ var watermarkZoom;
+ if (watermark.width / watermark.height > scaleWidth(card.watermarkBounds.width) / scaleHeight(card.watermarkBounds.height)) {
+ watermarkZoom = (scaleWidth(card.watermarkBounds.width) / watermark.width * 100).toFixed(1);
+ } else {
+ watermarkZoom = (scaleHeight(card.watermarkBounds.height) / watermark.height * 100).toFixed(1);
+ }
+ document.querySelector('#watermark-zoom').value = watermarkZoom;
+ document.querySelector('#watermark-x').value = Math.round(scaleX(card.watermarkBounds.x) - watermark.width * watermarkZoom / 200 - scaleWidth(card.marginX));
+ document.querySelector('#watermark-y').value = Math.round(scaleY(card.watermarkBounds.y) - watermark.height * watermarkZoom / 200 - scaleHeight(card.marginY));
+ watermarkEdited();
+}
+//svg cropper
+function getSetSymbolWatermark(url, targetImage = watermark) {
+ if (!url.includes('/')) {
+ url = 'https://cdn.jsdelivr.net/npm/keyrune/svg/' + url + '.svg';
+ }
+ xhttp = new XMLHttpRequest();
+ xhttp.open('GET', url, true);
+ xhttp.overrideMimeType('image/svg+xml');
+ xhttp.onload = function(event) {
+ if (this.readyState == 4 && this.status == 200) {
+ var svg = document.body.appendChild(xhttp.responseXML.documentElement);
+ var box = svg.getBBox(svg);
+ svg.setAttribute('viewBox', [box.x, box.y, box.width, box.height].join(' '));
+ svg.setAttribute('width', box.width);
+ svg.setAttribute('height', box.height);
+ uploadWatermark('data:image/svg+xml,' + encodeURIComponent(svg.outerHTML), 'resetWatermark');
+ svg.remove();
+ } else if (this.status == 404) {
+ throw new Error('Improper Set Code');
+ }
+ }
+ xhttp.send();
+}
+//Bottom Info Tab
+async function loadBottomInfo(textObjects = []) {
+ await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
+ card.bottomInfo = null;
+ card.bottomInfo = textObjects;
+ await bottomInfoEdited();
+ bottomInfoEdited();
+}
+async function bottomInfoEdited() {
+ await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
+ card.infoNumber = document.querySelector('#info-number').value;
+ card.infoRarity = document.querySelector('#info-rarity').value;
+ card.infoSet = document.querySelector('#info-set').value;
+ card.infoLanguage = document.querySelector('#info-language').value;
+ card.infoArtist = document.querySelector('#info-artist').value;
+ card.infoYear = document.querySelector('#info-year').value;
+ card.infoNote = document.querySelector('#info-note').value;
+
+ if (document.querySelector('#enableCollectorInfo').checked) {
+ for (var textObject of Object.entries(card.bottomInfo)) {
+ if (["NOT FOR SALE", "Wizards of the Coast", "CardConjurer.com", "cardconjurer.com"].some(v => textObject[1].text.includes(v))) {
+ continue;
+ } else {
+ textObject[1].name = textObject[0];
+ await writeText(textObject[1], bottomInfoContext);
+ }
+ continue;
+ }
+ }
+
+ drawCard();
+}
+function artistEdited(value) {
+ document.querySelector('#art-artist').value = value;
+ document.querySelector('#info-artist').value = value;
+ bottomInfoEdited();
+}
+function toggleStarDot() {
+ for (var key of Object.keys(card.bottomInfo)) {
+ var text = card.bottomInfo[key].text
+ if (text.includes('*')) {
+ card.bottomInfo[key].text = text.replace('*', ' \u2022 ');
+ } else {
+ card.bottomInfo[key].text = text.replace(' \u2022 ', '*');
+ }
+ }
+ defaultCollector.starDot = !defaultCollector.starDot;
+ bottomInfoEdited();
+}
+function enableNewCollectorInfoStyle() {
+ localStorage.setItem('enableNewCollectorStyle', document.querySelector('#enableNewCollectorStyle').checked);
+ setBottomInfoStyle();
+ bottomInfoEdited();
+}
+function enableCollectorInfo() {
+ localStorage.setItem('enableCollectorInfo', document.querySelector('#enableCollectorInfo').checked);
+ bottomInfoEdited();
+}
+function enableImportCollectorInfo() {
+ localStorage.setItem('enableImportCollectorInfo', document.querySelector('#enableImportCollectorInfo').checked);
+}
+function setAutoFrame() {
+ var value = document.querySelector('#autoFrame').value;
+ localStorage.setItem('autoFrame', value);
+
+ if (value !== 'false') {
+ document.querySelector('#autoLoadFrameVersion').checked = true;
+ localStorage.setItem('autoLoadFrameVersion', 'true');
+ }
+
+ autoFrame();
+}
+function setAutofit() {
+ localStorage.setItem('autoFit', document.querySelector('#art-update-autofit').checked);
+}
+function removeDefaultCollector() {
+ defaultCollector = {}; //{number: year, rarity:'P', setCode:'MTG', lang:'EN', starDot:false};
+ localStorage.removeItem('defaultCollector'); //localStorage.setItem('defaultCollector', JSON.stringify(defaultCollector));
+}
+function setDefaultCollector() {
+ starDot = defaultCollector.starDot;
+ defaultCollector = {
+ number: document.querySelector('#info-number').value,
+ rarity: document.querySelector('#info-rarity').value,
+ setCode: document.querySelector('#info-set').value,
+ lang: document.querySelector('#info-language').value,
+ note: document.querySelector('#info-note').value,
+ starDot: starDot
+ };
+ localStorage.setItem('defaultCollector', JSON.stringify(defaultCollector));
+}
+//DRAWING THE CARD (putting it all together)
+function drawCard() {
+ // reset
+ cardContext.globalCompositeOperation = 'source-over';
+ cardContext.clearRect(0, 0, cardCanvas.width, cardCanvas.height);
+ // art
+ cardContext.save();
+ cardContext.translate(scaleX(card.artX), scaleY(card.artY));
+ cardContext.rotate(Math.PI / 180 * (card.artRotate || 0));
+ if (document.querySelector('#grayscale-art').checked) {
+ cardContext.filter='grayscale(1)';
+ }
+ cardContext.drawImage(art, 0, 0, art.width * card.artZoom, art.height * card.artZoom);
+ cardContext.restore();
+ // frame elements
+ if (card.version.includes('planeswalker') && typeof planeswalkerPreFrameCanvas !== "undefined") {
+ cardContext.drawImage(planeswalkerPreFrameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ }
+ cardContext.drawImage(frameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ if (card.version.toLowerCase().includes('planeswalker') && typeof planeswalkerPostFrameCanvas !== "undefined") {
+ cardContext.drawImage(planeswalkerPostFrameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ } else if (card.version.toLowerCase().includes('planeswalker') && typeof planeswalkerCanvas !== "undefined") {
+ cardContext.drawImage(planeswalkerCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ } else if (card.version.toLowerCase().includes('qrcode') && typeof qrCodeCanvas !== "undefined") {
+ cardContext.drawImage(qrCodeCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ } // REMOVE/DELETE PLANESWALKERCANVAS AFTER A FEW WEEKS
+ // guidelines
+ if (document.querySelector('#show-guidelines').checked) {
+ cardContext.drawImage(guidelinesCanvas, scaleX(card.marginX) / 2, scaleY(card.marginY) / 2, cardCanvas.width, cardCanvas.height);
+ }
+ // watermark
+ cardContext.drawImage(watermarkCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ // custom elements for sagas, classes, and dungeons
+ if (card.version.toLowerCase().includes('saga') && typeof sagaCanvas !== "undefined") {
+ cardContext.drawImage(sagaCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ } else if (card.version.toLowerCase().includes('class') && typeof classCanvas !== "undefined") {
+ cardContext.drawImage(classCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ } else if (card.version.toLowerCase().includes('dungeon') && typeof dungeonCanvas !== "undefined") {
+ cardContext.drawImage(dungeonCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ }
+ // text
+ cardContext.drawImage(textCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ // set symbol
+ cardContext.drawImage(setSymbol, scaleX(card.setSymbolX), scaleY(card.setSymbolY), setSymbol.width * card.setSymbolZoom, setSymbol.height * card.setSymbolZoom)
+ // bottom info
+ if (card.bottomInfoTranslate) {
+ cardContext.save();
+ cardContext.rotate(Math.PI / 180 * (card.bottomInfoRotate || 0));
+ cardContext.translate(card.bottomInfoTranslate.x || 0, card.bottomInfoTranslate.y || 0);
+ cardContext.drawImage(bottomInfoCanvas, 0, 0, cardCanvas.width * (card.bottomInfoZoom || 1), cardCanvas.height * (card.bottomInfoZoom || 1));
+ cardContext.restore();
+ } else {
+ cardContext.drawImage(bottomInfoCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
+ }
+
+
+ // cutout the corners
+ cardContext.globalCompositeOperation = 'destination-out';
+ if (!card.noCorners && (card.marginX == 0 && card.marginY == 0)) {
+ var w = card.version == 'battle' ? 2100 : getStandardWidth();
+
+ cardContext.drawImage(corner, 0, 0, scaleWidth(59/w), scaleWidth(59/w));
+ cardContext.rotate(Math.PI / 2);
+ cardContext.drawImage(corner, 0, -card.width, scaleWidth(59/w), scaleWidth(59/w));
+ cardContext.rotate(Math.PI / 2);
+ cardContext.drawImage(corner, -card.width, -card.height, scaleWidth(59/w), scaleWidth(59/w));
+ cardContext.rotate(Math.PI / 2);
+ cardContext.drawImage(corner, -card.height, 0, scaleWidth(59/w), scaleWidth(59/w));
+ cardContext.rotate(Math.PI / 2);
+ }
+ // show preview
+ previewContext.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
+ previewContext.drawImage(cardCanvas, 0, 0, previewCanvas.width, previewCanvas.height);
+}
+//DOWNLOADING
+function downloadCard(alt = false, jpeg = false) {
+ if (card.infoArtist.replace(/ /g, '') == '' && !card.artSource.includes('/img/blank.png') && !card.artZoom == 0) {
+ notify('You must credit an artist before downloading!', 5);
+ } else {
+ // Prep file information
+ var imageDataURL;
+ var imageName = getCardName();
+ if (jpeg) {
+ imageDataURL = cardCanvas.toDataURL('image/jpeg', 0.8);
+ imageName = imageName + '.jpeg';
+ } else {
+ imageDataURL = cardCanvas.toDataURL('image/png');
+ imageName = imageName + '.png';
+ }
+ // Download image
+ if (alt) {
+ const newWindow = window.open('about:blank');
+ setTimeout(function(){
+ newWindow.document.body.appendChild(newWindow.document.createElement('img')).src = imageDataURL;
+ newWindow.document.querySelector('img').style = 'max-height: 100vh; max-width: 100vw;';
+ newWindow.document.body.style = 'padding: 0; margin: 0; text-align: center; background-color: #888;';
+ newWindow.document.title = imageName;
+ }, 0);
+ } else {
+ const downloadElement = document.createElement('a');
+ downloadElement.download = imageName;
+ downloadElement.target = '_blank';
+ downloadElement.href = imageDataURL;
+ document.body.appendChild(downloadElement);
+ downloadElement.click();
+ downloadElement.remove();
+ }
+ }
+}
+//IMPORT/SAVE TAB
+function importCard(cardObject) {
+ scryfallCard = cardObject;
+ const importIndex = document.querySelector('#import-index');
+ importIndex.innerHTML = null;
+ var optionIndex = 0;
+ cardObject.forEach(card => {
+ if (card.type_line && card.type_line != 'Card') {
+ var option = document.createElement('option');
+ var title = `${card.name} `;
+ if (document.querySelector('#importAllPrints').checked) {
+ title += `(${card.set.toUpperCase()} #${card.collector_number})`;
+ } else {
+ title += `(${card.type_line})`
+ }
+ option.innerHTML = title;
+ option.value = optionIndex;
+ importIndex.appendChild(option);
+ }
+ optionIndex ++;
+ });
+ changeCardIndex();
+}
+
+function scryfallCardFromText(text) {
+ var lines = text.trim().split("\n");
+
+ if (lines.count == 0) {
+ return {};
+ }
+
+ lines = lines.map(item => item.trim()).filter(item => item != "");
+
+ var name = lines.shift();
+ var manaCost;
+ var manaCostStartIndex = name.indexOf("{");
+ if (manaCostStartIndex > 0) {
+ manaCost = name.substring(manaCostStartIndex).trim();
+ name = name.substring(0, manaCostStartIndex).trim();
+ }
+
+ var cardObject = {
+ "name": name,
+ "lang": "en"
+ };
+
+ if (manaCost !== undefined) {
+ cardObject.mana_cost = manaCost;
+ }
+
+ if (lines.count == 0) {
+ return cardObject;
+ }
+
+ cardObject.type_line = lines.shift().trim();
+
+ if (lines.count == 0) {
+ return cardObject;
+ }
+
+ var regex = /[0-9+\-*]+\/[0-9+*]+/
+ var match = lines[lines.length-1].match(regex);
+ if (match) {
+ var pt = match[0].split("/");
+ cardObject.power = pt[0];
+ cardObject.toughness = pt[1];
+ lines.pop();
+ }
+
+ if (lines.count == 0) {
+ return cardObject;
+ }
+
+ cardObject.oracle_text = lines.join("\n");
+
+ return cardObject;
+}
+
+function changeCardIndex() {
+ var cardToImport = scryfallCard[document.querySelector('#import-index').value];
+ //text
+ var langFontCode = "";
+ if (cardToImport.lang == "ph") {langFontCode = "{fontphyrexian}"}
+ var name = cardToImport.name || '';
+ if (name.startsWith('A-')) { name = name.replace('A-', '{alchemy}'); }
+
+ if (card.text.title) {
+ if (card.version == 'wanted') {
+ var subtitle = '';
+ var index = name.indexOf(', ');
+
+ if (index > 0) {
+ card.text.subtitle.text = langFontCode + curlyQuotes(name.substring(index+2));
+ card.text.title.text = langFontCode + curlyQuotes(name.substring(0, index+1));
+ } else {
+ card.text.title.text = langFontCode + curlyQuotes(name);
+ card.text.subtitle.text = '';
+ }
+ } else {
+ card.text.title.text = langFontCode + curlyQuotes(name);
+ }
+ }
+
+ if (card.text.nickname) {card.text.nickname.text = cardToImport.flavor_name || '';}
+ if (card.text.mana) {card.text.mana.text = cardToImport.mana_cost || '';}
+ if (card.text.type) {card.text.type.text = langFontCode + cardToImport.type_line || '';}
+
+ var italicExemptions = ['Boast', 'Cycling', 'Visit', 'Prize', 'I', 'II', 'III', 'IV', 'I, II', 'II, III', 'III, IV', 'I, II, III', 'II, III, IV', 'I, II, III, IV', '• Khans', '• Dragons', '• Mirran', '• Phyrexian', 'Prototype', 'Companion', 'To solve', 'Solved'];
+ var rulesText = (cardToImport.oracle_text || '').replace(/(?:\((?:.*?)\)|[^"\n]+(?= — ))/g, function(a){
+ if (italicExemptions.includes(a) || (cardToImport.keywords.indexOf('Spree') != -1 && a.startsWith('+'))) {return a;}
+ return '{i}' + a + '{/i}';
+ });
+ rulesText = curlyQuotes(rulesText).replace(/{Q}/g, '{untap}').replace(/{\u221E}/g, "{inf}").replace(/• /g, '• {indent}');
+ rulesText = rulesText.replace('(If this card is your chosen companion, you may put it into your hand from outside the game for {3} any time you could cast a sorcery.)', '(If this card is your chosen companion, you may put it into your hand from outside the game for {3} as a sorcery.)')
+
+ if (card.text.rules) {
+ if (card.version == 'pokemon') {
+ if (cardToImport.type_line.toLowerCase().includes('creature')) {
+ card.text.rules.text = langFontCode + rulesText;
+ card.text.rulesnoncreature.text = '';
+
+ card.text.middleStatTitle.text = 'power';
+ card.text.rightStatTitle.text = 'toughness';
+
+ } else if (cardToImport.type_line.toLowerCase().includes('planeswalker')) {
+ card.text.rules.text = langFontCode + rulesText;
+ card.text.rulesnoncreature.text = '';
+
+ card.text.pt.text = '{' + (cardToImport.loyalty || '' + '}');
+
+ card.text.middleStatTitle.text = '';
+ card.text.rightStatTitle.text = 'loyalty';
+ } else if (cardToImport.type_line.toLowerCase().includes('battle')) {
+ card.text.rules.text = langFontCode + rulesText;
+ card.text.rulesnoncreature.text = '';
+
+ card.text.pt.text = '{' + (cardToImport.defense || '' + '}');
+
+ card.text.middleStatTitle.text = '';
+ card.text.rightStatTitle.text = 'defense';
+ } else {
+ card.text.rulesnoncreature.text = langFontCode + rulesText;
+ card.text.rules.text = '';
+
+ card.text.middleStatTitle.text = '';
+ card.text.rightStatTitle.text = '';
+ }
+
+ } else {
+ card.text.rules.text = langFontCode + rulesText;
+ }
+
+ if (cardToImport.flavor_text) {
+ var flavorText = cardToImport.flavor_text;
+ var flavorTextCounter = 1;
+ while (flavorText.includes('*') || flavorText.includes('"')) {
+ if (flavorTextCounter % 2) {
+ flavorText = flavorText.replace('*', '{/i}');
+ flavorText = flavorText.replace('"', '\u201c');
+ } else {
+ flavorText = flavorText.replace('*', '{i}');
+ flavorText = flavorText.replace('"', '\u201d');
+ }
+ flavorTextCounter ++;
+ }
+
+ if (card.version == 'pokemon') {
+ if (cardToImport.type_line.toLowerCase().includes('creature')) {
+ if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
+ card.text.rules.text += '{i}';
+ } else {
+ card.text.rules.text += '{flavor}';
+ }
+ card.text.rules.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
+ } else {
+ if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
+ card.text.rulesnoncreature.text += '{i}';
+ } else {
+ card.text.rulesnoncreature.text += '{flavor}';
+ }
+ card.text.rulesnoncreature.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
+ }
+
+ } else {
+ if (!cardToImport.oracle_text || cardToImport.oracle_text == '') {
+ card.text.rules.text += '{i}';
+ } else {
+ card.text.rules.text += '{flavor}';
+ }
+ card.text.rules.text += curlyQuotes(flavorText.replace('\n', '{lns}'));
+ }
+
+
+ }
+ } else if (card.text.case) {
+ rulesText = rulesText.replace(/(\r\n|\r|\n)/g, '//{bar}//');
+ card.text.case.text = langFontCode + rulesText;
+ }
+
+ if (card.text.pt) {
+ if (card.version == 'invocation') {
+ card.text.pt.text = cardToImport.power + '\n' + cardToImport.toughness || '';
+ } else if (card.version == 'pokemon') {
+ card.text.middleStat.text = '{' + (cardToImport.power || '') + '}';
+ card.text.pt.text = '{' + (cardToImport.toughness || '') + '}';
+
+ if (card.text.middleStat && card.text.middleStat.text == '{}') {card.text.middleStat.text = '';}
+ } else {
+ card.text.pt.text = cardToImport.power + '/' + cardToImport.toughness || '';
+ }
+ }
+ if (card.text.pt && card.text.pt.text == undefined + '/' + undefined) {card.text.pt.text = '';}
+ if (card.text.pt && card.text.pt.text == undefined + '\n' + undefined) {card.text.pt.text = '';}
+ if (card.text.pt && card.text.pt.text == '{}') {card.text.pt.text = '';}
+ if (card.version.includes('planeswalker')) {
+ card.text.loyalty.text = cardToImport.loyalty || '';
+ var planeswalkerAbilities = cardToImport.oracle_text.split('\n');
+ while (planeswalkerAbilities.length > 4) {
+ var newAbility = planeswalkerAbilities[planeswalkerAbilities.length - 2] + '\n' + planeswalkerAbilities.pop();
+ planeswalkerAbilities[planeswalkerAbilities.length - 1] = newAbility;
+ }
+ for (var i = 0; i < 4; i ++) {
+ if (planeswalkerAbilities[i]) {
+ var planeswalkerAbility = planeswalkerAbilities[i].replace(': ', 'splitstring').split('splitstring');
+ if (!planeswalkerAbility[1]) {
+ planeswalkerAbility = ['', planeswalkerAbility[0]];
+ }
+ card.text['ability' + i].text = planeswalkerAbility[1].replace('(', '{i}(').replace(')', '){/i}');
+ if (card.version == 'planeswalkerTall' || card.version == 'planeswalkerCompleated') {
+ document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.3572) / planeswalkerAbilities.length);
+ } else {
+ document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.2915) / planeswalkerAbilities.length);
+ }
+ document.querySelector('#planeswalker-cost-' + i).value = planeswalkerAbility[0].replace('\u2212', '-');
+ } else {
+ card.text['ability' + i].text = '';
+ document.querySelector('#planeswalker-height-' + i).value = 0;
+ }
+ }
+ planeswalkerEdited();
+ } else if (card.version.includes('saga')) {
+ card.text.ability0.text = cardToImport.oracle_text.replace('(', '{i}(').replace(')', '){/i}') || '';
+ } else if (card.version.includes('battle')) {
+ card.text.defense.text = cardToImport.defense || '';
+ }
+ document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
+ document.querySelector('#text-editor-font-size').value = 0;
+ //font size
+ Object.keys(card.text).forEach(key => {
+ card.text[key].fontSize = 0;
+ });
+ textEdited();
+ //collector's info
+ if (localStorage.getItem('enableImportCollectorInfo') == 'true') {
+ document.querySelector('#info-number').value = cardToImport.collector_number || "";
+ document.querySelector('#info-rarity').value = (cardToImport.rarity || "")[0].toUpperCase();
+ document.querySelector('#info-set').value = (cardToImport.set || "").toUpperCase();
+ document.querySelector('#info-language').value = (cardToImport.lang || "").toUpperCase();
+ var setXhttp = new XMLHttpRequest();
+ setXhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ var setObject = JSON.parse(this.responseText)
+ if (document.querySelector('#enableNewCollectorStyle').checked) {
+ var number = document.querySelector('#info-number').value;
+
+ while (number.length < 4) {
+ number = '0' + number;
+ }
+
+ document.querySelector('#info-number').value = number;
+
+ bottomInfoEdited();
+ } else if (setObject.printed_size) {
+ var number = document.querySelector('#info-number').value;
+
+ while (number.length < 3) {
+ number = '0' + number;
+ }
+
+ var printedSize = setObject.printed_size;
+ while (printedSize.length < 3) {
+ printedSize = '0' + printedSize;
+ }
+
+ if (parseInt(number) <= parseInt(printedSize)) {
+ document.querySelector('#info-number').value = number + "/" + printedSize;
+ } else {
+ document.querySelector('#info-number').value = number;
+ }
+
+
+ bottomInfoEdited();
+ }
+ }
+ }
+ setXhttp.open('GET', "https://api.scryfall.com/sets/" + cardToImport.set, true);
+ try {
+ setXhttp.send();
+ } catch {
+ console.log('Scryfall API search failed.')
+ }
+ }
+ //art
+ document.querySelector('#art-name').value = cardToImport.name;
+ fetchScryfallData(cardToImport.name, artFromScryfall, 'art');
+ if (document.querySelector('#importAllPrints').checked) {
+ // document.querySelector('#art-index').value = document.querySelector('#import-index').value;
+ // changeArtIndex();
+ }
+ //set symbol
+ if (!document.querySelector('#lockSetSymbolCode').checked) {
+ document.querySelector('#set-symbol-code').value = cardToImport.set;
+ }
+ document.querySelector('#set-symbol-rarity').value = cardToImport.rarity.slice(0, 1);
+ if (!document.querySelector('#lockSetSymbolURL').checked) {
+ fetchSetSymbol();
+ }
+}
+function loadAvailableCards(cardKeys = JSON.parse(localStorage.getItem('cardKeys'))) {
+ if (!cardKeys) {
+ cardKeys = [];
+ cardKeys.sort();
+ localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
+ }
+ document.querySelector('#load-card-options').innerHTML = 'None selected ';
+ cardKeys.forEach(item => {
+ var cardKeyOption = document.createElement('option');
+ cardKeyOption.innerHTML = item;
+ document.querySelector('#load-card-options').appendChild(cardKeyOption);
+ });
+}
+function importChanged() {
+ var unique = document.querySelector('#importAllPrints').checked ? 'prints' : '';
+ fetchScryfallData(document.querySelector("#import-name").value, importCard, unique);
+}
+function saveCard(saveFromFile) {
+ var cardKeys = JSON.parse(localStorage.getItem('cardKeys')) || [];
+ var cardKey, cardToSave;
+ if (saveFromFile) {
+ cardKey = saveFromFile.key;
+ } else {
+ cardKey = getCardName();
+ }
+ if (!saveFromFile) {
+ cardKey = prompt('Enter the name you would like to save your card under:', cardKey);
+ if (!cardKey) {return null;}
+ }
+ cardKey = cardKey.trim();
+ if (cardKeys.includes(cardKey)) {
+ if (!confirm('Would you like to overwrite your card previously saved as "' + cardKey + '"?\n(Clicking "cancel" will affix a version number)')) {
+ var originalCardKey = cardKey;
+ var cardKeyNumber = 1;
+ while (cardKeys.includes(cardKey)) {
+ cardKey = originalCardKey + ' (' + cardKeyNumber + ')';
+ cardKeyNumber ++;
+ }
+ }
+ }
+ if (saveFromFile) {
+ cardToSave = saveFromFile.data;
+ } else {
+ cardToSave = JSON.parse(JSON.stringify(card));
+ cardToSave.frames.forEach(frame => {
+ delete frame.image;
+ frame.masks.forEach(mask => delete mask.image);
+ });
+ }
+ try {
+ localStorage.setItem(cardKey, JSON.stringify(cardToSave));
+ if (!cardKeys.includes(cardKey)) {
+ cardKeys.push(cardKey);
+ cardKeys.sort();
+ localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
+ loadAvailableCards(cardKeys);
+ }
+ } catch (error) {
+ notify('You have exceeded your 5MB of local storage, and your card has failed to save. If you would like to continue saving cards, please download all saved cards, then delete all saved cards to free up space. Local storage is most often exceeded by uploading large images directly from your computer. If possible/convenient, using a URL avoids the need to save these large images. Apologies for the inconvenience.');
+ }
+}
+async function loadCard(selectedCardKey) {
+ //clear the draggable frames
+ document.querySelector('#frame-list').innerHTML = null;
+ //clear the existing card, then replace it with the new JSON
+ card = {};
+ card = JSON.parse(localStorage.getItem(selectedCardKey));
+ //if the card was loaded properly...
+ if (card) {
+ //load values from card into html inputs
+ document.querySelector('#info-number').value = card.infoNumber;
+ document.querySelector('#info-rarity').value = card.infoRarity;
+ document.querySelector('#info-set').value = card.infoSet;
+ document.querySelector('#info-language').value = card.infoLanguage;
+ document.querySelector('#info-note').value = card.infoNote;
+ document.querySelector('#info-year').value = card.infoYear || date.getFullYear();
+ artistEdited(card.infoArtist);
+ document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
+ document.querySelector('#text-editor-font-size').value = card.text[Object.keys(card.text)[selectedTextIndex]].fontSize || 0;
+ loadTextOptions(card.text);
+ document.querySelector('#art-x').value = scaleX(card.artX) - scaleWidth(card.marginX);
+ document.querySelector('#art-y').value = scaleY(card.artY) - scaleHeight(card.marginY);
+ document.querySelector('#art-zoom').value = card.artZoom * 100;
+ document.querySelector('#art-rotate').value = card.artRotate || 0;
+ uploadArt(card.artSource);
+ document.querySelector('#setSymbol-x').value = scaleX(card.setSymbolX) - scaleWidth(card.marginX);
+ document.querySelector('#setSymbol-y').value = scaleY(card.setSymbolY) - scaleHeight(card.marginY);
+ document.querySelector('#setSymbol-zoom').value = card.setSymbolZoom * 100;
+ uploadSetSymbol(card.setSymbolSource);
+ document.querySelector('#watermark-x').value = scaleX(card.watermarkX) - scaleWidth(card.marginX);
+ document.querySelector('#watermark-y').value = scaleY(card.watermarkY) - scaleHeight(card.marginY);
+ document.querySelector('#watermark-zoom').value = card.watermarkZoom * 100;
+ // document.querySelector('#watermark-left').value = card.watermarkLeft;
+ // document.querySelector('#watermark-right').value = card.watermarkRight;
+ document.querySelector('#watermark-opacity').value = card.watermarkOpacity * 100;
+ document.getElementById("rounded-corners").checked = !card.noCorners;
+ uploadWatermark(card.watermarkSource);
+ card.frames.reverse();
+ await card.frames.forEach(item => addFrame([], item));
+ card.frames.reverse();
+ if (card.onload) {
+ await loadScript(card.onload);
+ }
+ card.manaSymbols.forEach(item => loadScript(item));
+ //canvases
+ var canvasesResized = false;
+ canvasList.forEach(name => {
+ if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
+ sizeCanvas(name);
+ canvasesResized = true;
+ }
+ });
+ if (canvasesResized) {
+ drawTextBuffer();
+ drawFrames();
+ bottomInfoEdited();
+ watermarkEdited();
+ }
+ } else {
+ notify(selectedCardKey + ' failed to load.', 5)
+ }
+}
+function deleteCard() {
+ var keyToDelete = document.querySelector('#load-card-options').value;
+ if (keyToDelete) {
+ var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
+ cardKeys.splice(cardKeys.indexOf(keyToDelete), 1);
+ cardKeys.sort();
+ localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
+ localStorage.removeItem(keyToDelete);
+ loadAvailableCards(cardKeys);
+ }
+}
+function deleteSavedCards() {
+ if (confirm('WARNING:\n\nALL of your saved cards will be deleted! If you would like to save these cards, please make sure you have downloaded them first. There is no way to undo this.\n\n(Press "OK" to delete your cards)')) {
+ var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
+ cardKeys.forEach(key => localStorage.removeItem(key));
+ localStorage.setItem('cardKeys', JSON.stringify([]));
+ loadAvailableCards([]);
+ }
+}
+async function downloadSavedCards() {
+ var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
+ if (cardKeys) {
+ var allSavedCards = [];
+ cardKeys.forEach(item => {
+ allSavedCards.push({key:item, data:JSON.parse(localStorage.getItem(item))});
+ });
+ var download = document.createElement('a');
+ download.href = URL.createObjectURL(new Blob([JSON.stringify(allSavedCards)], {type:'text'}));
+ download.download = 'saved-cards.cardconjurer';
+ document.body.appendChild(download);
+ await download.click();
+ download.remove();
+ }
+}
+function uploadSavedCards(event) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ JSON.parse(reader.result).forEach(item => saveCard(item));
+ }
+ reader.readAsText(event.target.files[0]);
+}
+//TUTORIAL TAB
+function loadTutorialVideo() {
+ var video = document.querySelector('.video > iframe');
+ if (video.src == '') {
+ video.src = 'https://www.youtube-nocookie.com/embed/e4tnOiub41g?rel=0';
+ }
+}
+// GUIDELINES
+function drawNewGuidelines() {
+ // clear
+ guidelinesContext.clearRect(0, 0, guidelinesCanvas.width, guidelinesCanvas.height);
+ // set opacity
+ guidelinesContext.globalAlpha = 0.25;
+ // textboxes
+ guidelinesContext.fillStyle = 'blue';
+ Object.entries(card.text).forEach(item => {
+ guidelinesContext.fillRect(scaleX(item[1].x || 0), scaleY(item[1].y || 0), scaleWidth(item[1].width || 1), scaleHeight(item[1].height || 1));
+ });
+ // art
+ guidelinesContext.fillStyle = 'green';
+ guidelinesContext.fillRect(scaleX(card.artBounds.x), scaleY(card.artBounds.y), scaleWidth(card.artBounds.width), scaleHeight(card.artBounds.height));
+ // watermark
+ guidelinesContext.fillStyle = 'yellow';
+ var watermarkWidth = scaleWidth(card.watermarkBounds.width);
+ var watermarkHeight = scaleHeight(card.watermarkBounds.height);
+ guidelinesContext.fillRect(scaleX(card.watermarkBounds.x) - watermarkWidth / 2, scaleY(card.watermarkBounds.y) - watermarkHeight / 2, watermarkWidth, watermarkHeight);
+ // set symbol
+ var setSymbolX = scaleX(card.setSymbolBounds.x);
+ var setSymbolY = scaleY(card.setSymbolBounds.y);
+ var setSymbolWidth = scaleWidth(card.setSymbolBounds.width);
+ var setSymbolHeight = scaleHeight(card.setSymbolBounds.height);
+ if (card.setSymbolBounds.vertical == 'center') {
+ setSymbolY -= setSymbolHeight / 2;
+ } else if (card.setSymbolBounds.vertical == 'bottom') {
+ setSymbolY -= setSymbolHeight;
+ }
+ if (card.setSymbolBounds.horizontal == 'center') {
+ setSymbolX -= setSymbolWidth / 2;
+ } else if (card.setSymbolBounds.horizontal == 'right') {
+ setSymbolX -= setSymbolWidth;
+ }
+ guidelinesContext.fillStyle = 'red';
+ guidelinesContext.fillRect(setSymbolX, setSymbolY, setSymbolWidth, setSymbolHeight);
+ // grid
+ guidelinesContext.globalAlpha = 1;
+ guidelinesContext.beginPath();
+ guidelinesContext.strokeStyle = 'gray';
+ guidelinesContext.lineWidth = 1;
+ const boxPadding = 25;
+ for (var x = 0; x <= card.width; x += boxPadding) {
+ guidelinesContext.moveTo(x, 0);
+ guidelinesContext.lineTo(x, card.height);
+ }
+ for (var y = 0; y <= card.height; y += boxPadding) {
+ guidelinesContext.moveTo(0, y);
+ guidelinesContext.lineTo(card.width, y);
+ }
+ guidelinesContext.stroke();
+ //center lines
+ guidelinesContext.beginPath();
+ guidelinesContext.strokeStyle = 'black';
+ guidelinesContext.lineWidth = 3;
+ guidelinesContext.moveTo(card.width / 2, 0);
+ guidelinesContext.lineTo(card.width / 2, card.height);
+ guidelinesContext.moveTo(0, card.height / 2);
+ guidelinesContext.lineTo(card.width, card.height / 2);
+ guidelinesContext.stroke();
+ //draw to card
+ drawCard();
+}
+//HIGHLIGHT TRANSPARENCIES
+function toggleCardBackgroundColor(highlight) {
+ if (highlight) {
+ previewCanvas.style["background-color"] = "#ff007fff";
+ } else {
+ previewCanvas.style["background-color"] = "#0000";
+ }
+}
+//Rounded Corners
+function setRoundedCorners(value) {
+ card.noCorners = !value;
+ drawCard();
+}
+//Various loaders
+function imageURL(url, destination, otherParams) {
+ var imageurl = url;
+ // If an image URL does not have HTTP in it, assume it's a local file in the repo local_art directory.
+ if (!url.includes('http')) {
+ imageurl = '/local_art/' + url;
+ } else if (params.get('noproxy') != '') {
+ //CORS PROXY LINKS
+ //Previously: https://cors.bridged.cc/
+ imageurl = 'https://corsproxy.io/?' + encodeURIComponent(url);
+ }
+ destination(imageurl, otherParams);
+}
+async function imageLocal(event, destination, otherParams) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ destination(reader.result, otherParams);
+ }
+ reader.onerror = function () {
+ destination('/img/blank.png', otherParams);
+ }
+ await reader.readAsDataURL(event.target.files[0]);
+}
+function loadScript(scriptPath) {
+ var script = document.createElement('script');
+ script.setAttribute('type', 'text/javascript');
+ script.onerror = function(){notify('A script failed to load, likely due to an update. Please reload your page. Sorry for the inconvenience.');}
+ script.setAttribute('src', scriptPath);
+ if (typeof script != 'undefined') {
+ document.querySelectorAll('head')[0].appendChild(script);
+ }
+}
+// Stretchable SVGs
+function stretchSVG(frameObject) {
+ xhr = new XMLHttpRequest();
+ xhr.open('GET', fixUri(frameObject.src), true);
+ xhr.overrideMimeType('image/svg+xml');
+ xhr.onload = function(e) {
+ if (this.readyState == 4 && this.status == 200) {
+ frameObject.image.src = 'data:image/svg+xml;charset=utf-8,' + stretchSVGReal((new XMLSerializer).serializeToString(this.responseXML.documentElement), frameObject);
+ }
+ }
+ xhr.send();
+}
+function stretchSVGReal(data, frameObject) {
+ var returnData = data;
+ frameObject.stretch.forEach(stretch => {
+ const change = stretch.change;
+ const targets = stretch.targets;
+ const name = stretch.name;
+ const oldData = returnData.split(name + '" d="')[1].split('" style=')[0];
+ var newData = '';
+ const listData = oldData.split(/(?=[clmz])/gi);
+ for (i = 0; i < listData.length; i ++) {
+ const item = listData[i];
+ if (targets.includes(i) || targets.includes(-i)) {
+ let sign = 1;
+ if (i != 0 && targets.includes(-i)) {sign = -1};
+ if (item[0] == 'C' || item[0] == 'c') {
+ newCoords = [];
+ item.slice(1).split(' ').forEach(pair => {
+ coords = pair.split(',');
+ newCoords.push((scaleWidth(change[0]) * sign + parseFloat(coords[0])) + ',' + (scaleHeight(change[1]) * sign + parseFloat(coords[1])));
+ });
+ newData += item[0] + newCoords.join(' ');
+ } else {
+ const coords = item.slice(1).split(/[, ]/);
+ newData += item[0] + (scaleWidth(change[0]) * sign + parseFloat(coords[0])) + ',' + (scaleHeight(change[1]) * sign + parseFloat(coords[1]))
+ }
+ } else {
+ newData += item;
+ }
+ }
+ returnData = returnData.replace(oldData, newData);
+ });
+ return returnData;
+}
+function processScryfallCard(card, responseCards) {
+ if ('card_faces' in card) {
+ card.card_faces.forEach(face => {
+ face.set = card.set;
+ face.rarity = card.rarity;
+ face.collector_number = card.collector_number;
+ face.lang = card.lang;
+ if (card.lang != 'en') {
+ face.oracle_text = face.printed_text;
+ face.name = face.printed_name;
+ face.type_line = face.printed_type_line;
+ }
+ responseCards.push(face);
+ if (!face.image_uris) {
+ face.image_uris = card.image_uris;
+ }
+ });
+ } else {
+ if (card.lang != 'en') {
+ card.oracle_text = card.printed_text;
+ card.name = card.printed_name;
+ card.type_line = card.printed_type_line;
+ }
+ responseCards.push(card);
+ }
+}
+
+function fetchScryfallCardByID(scryfallID, callback = console.log) {
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ responseCards = [];
+ importedCards = [JSON.parse(this.responseText)];
+ importedCards.forEach(card => {
+ processScryfallCard(card, responseCards);
+ });
+ callback(responseCards);
+ } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
+ notify(`No card found for "${cardName}" in ${cardLanguageSelect.options[cardLanguageSelect.selectedIndex].text}.`, 5);
+ }
+ }
+ xhttp.open('GET', 'https://api.scryfall.com/cards/' + scryfallID, true);
+ try {
+ xhttp.send();
+ } catch {
+ console.log('Scryfall API search failed.')
+ }
+}
+
+function fetchScryfallCardByCodeNumber(code, number, callback = console.log) {
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ responseCards = [];
+ importedCards = [JSON.parse(this.responseText)];
+ importedCards.forEach(card => {
+ processScryfallCard(card, responseCards);
+ });
+ callback(responseCards);
+ } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
+ notify('No card found for ' + code + ' #' + number, 5);
+ }
+ }
+ xhttp.open('GET', 'https://api.scryfall.com/cards/' + code + '/' + number, true);
+ try {
+ xhttp.send();
+ } catch {
+ console.log('Scryfall API search failed.')
+ }
+}
+
+//SCRYFALL STUFF MAY BE CHANGED IN THE FUTURE
+function fetchScryfallData(cardName, callback = console.log, unique = '') {
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ responseCards = [];
+ importedCards = JSON.parse(this.responseText).data;
+ importedCards.forEach(card => {
+ processScryfallCard(card, responseCards);
+ });
+ callback(responseCards);
+ } else if (this.readyState == 4 && this.status == 404 && !unique && cardName != '') {
+ notify(`No cards found for "${cardName}" in ${cardLanguageSelect.options[cardLanguageSelect.selectedIndex].text}.`, 5);
+ }
+ }
+ cardLanguageSelect = document.querySelector('#import-language');
+ var cardLanguage = `lang%3D${cardLanguageSelect.value}`;
+ var uniqueArt = '';
+ if (unique) {
+ uniqueArt = '&unique=' + unique;
+ }
+ var url = `https://api.scryfall.com/cards/search?order=released&include_extras=true${uniqueArt}&q=name%3D${cardName.replace(/ /g, '_')}%20${cardLanguage}`;
+ xhttp.open('GET', url, true);
+ try {
+ xhttp.send();
+ } catch {
+ console.log('Scryfall API search failed.')
+ }
+}
+
+function toggleTextTag(tag) {
+ var element = document.getElementById('text-editor');
+
+ var text = element.value;
+
+ var start = element.selectionStart;
+ var end = element.selectionEnd;
+ var selection = text.substring(start, end);
+
+ var openTag = '{' + tag + '}';
+ var closeTag = '{/' + tag + '}';
+
+ var prefix = text.substring(0, start);
+ var suffix = text.substring(end);
+
+ if (prefix.endsWith(openTag) && suffix.startsWith(closeTag)) {
+ prefix = prefix.substring(0, prefix.length-openTag.length);
+ suffix = suffix.substring(closeTag.length);
+ } else if (selection.startsWith(openTag) && selection.endsWith(closeTag)) {
+ selection = selection.substring(openTag.length, selection.length-closeTag.length);
+ } else {
+ selection = openTag + selection + closeTag;
+ }
+
+ element.value = prefix + selection + suffix;
+
+ textEdited();
+}
+
+function toggleHighRes() {
+ localStorage.setItem('high-res', document.querySelector('#high-res').checked);
+ drawCard();
+}
+
+// INITIALIZATION
+
+// auto load frame version (user defaults)
+if (!localStorage.getItem('autoLoadFrameVersion')) {
+ localStorage.setItem('autoLoadFrameVersion', document.querySelector('#autoLoadFrameVersion').checked);
+}
+document.querySelector('#autoLoadFrameVersion').checked = 'true' == localStorage.getItem('autoLoadFrameVersion');
+// document.querySelector('#high-res').checked = 'true' == localStorage.getItem('high-res');
+
+// collector info (user defaults)
+var defaultCollector = JSON.parse(localStorage.getItem('defaultCollector') || '{}');
+if ('number' in defaultCollector) {
+ document.querySelector('#info-number').value = defaultCollector.number;
+ document.querySelector('#info-note').value = defaultCollector.note;
+ document.querySelector('#info-rarity').value = defaultCollector.rarity;
+ document.querySelector('#info-set').value = defaultCollector.setCode;
+ document.querySelector('#info-language').value = defaultCollector.lang;
+ if (defaultCollector.starDot) {setTimeout(function(){defaultCollector.starDot = false; toggleStarDot();}, 500);}
+} else {
+ document.querySelector('#info-number').value = date.getFullYear();
+}
+if (!localStorage.getItem('enableImportCollectorInfo')) {
+ localStorage.setItem('enableImportCollectorInfo', 'false');
+} else {
+ document.querySelector('#enableImportCollectorInfo').checked = (localStorage.getItem('enableImportCollectorInfo') == 'true');
+}
+if (!localStorage.getItem('enableNewCollectorStyle')) {
+ localStorage.setItem('enableNewCollectorStyle', 'false');
+} else {
+ document.querySelector('#enableNewCollectorStyle').checked = (localStorage.getItem('enableNewCollectorStyle') == 'true');
+}
+if (!localStorage.getItem('enableCollectorInfo')) {
+ localStorage.setItem('enableCollectorInfo', 'true');
+} else {
+ document.querySelector('#enableCollectorInfo').checked = (localStorage.getItem('enableCollectorInfo') == 'true');
+}
+if (!localStorage.getItem('autoFrame')) {
+ localStorage.setItem('autoFrame', 'false');
+} else {
+ document.querySelector('#autoFrame').value = localStorage.getItem('autoFrame');
+}
+if (!localStorage.getItem('autoFit')) {
+ localStorage.setItem('autoFit', 'true');
+} else {
+ document.querySelector('#art-update-autofit').checked = localStorage.getItem('autoFit');
+}
+
+// lock set symbol code (user defaults)
+if (!localStorage.getItem('lockSetSymbolCode')) {
+ localStorage.setItem('lockSetSymbolCode', '');
+}
+if (localStorage.getItem('set-symbol-source')) {
+ document.querySelector('#set-symbol-source').value = localStorage.getItem('set-symbol-source');
+}
+document.querySelector('#lockSetSymbolCode').checked = '' != localStorage.getItem('lockSetSymbolCode');
+if (document.querySelector('#lockSetSymbolCode').checked) {
+ document.querySelector('#set-symbol-code').value = localStorage.getItem('lockSetSymbolCode');
+ fetchSetSymbol();
+}
+
+// lock set symbol url (user defaults)
+if (!localStorage.getItem('lockSetSymbolURL')) {
+ localStorage.setItem('lockSetSymbolURL', '');
+}
+document.querySelector('#lockSetSymbolURL').checked = '' != localStorage.getItem('lockSetSymbolURL');
+if (document.querySelector('#lockSetSymbolURL').checked) {
+ setSymbol.src = localStorage.getItem('lockSetSymbolURL');
+}
+
+//bind inputs together
+bindInputs('#frame-editor-hsl-hue', '#frame-editor-hsl-hue-slider');
+bindInputs('#frame-editor-hsl-saturation', '#frame-editor-hsl-saturation-slider');
+bindInputs('#frame-editor-hsl-lightness', '#frame-editor-hsl-lightness-slider');
+bindInputs('#show-guidelines', '#show-guidelines-2', true);
+
+// Load / init whatever
+loadScript('/js/frames/groupStandard-3.js');
+loadAvailableCards();
+initDraggableArt();
diff --git a/js/frameSearch.js b/js/frameSearch.js
index 6a47fa73..f141190f 100644
--- a/js/frameSearch.js
+++ b/js/frameSearch.js
@@ -1,314 +1,315 @@
-const frameNames = new Map ([
- //standard
- ['Regular Frames', 'M15Regular-1'],
- ['Legend Crowns', 'M15LegendCrowns'],
- ['Legend Crowns (Etched)', 'LegendCrownsEtched'],
- ['Floating Legend Crowns', 'M15LegendCrownsFloating'],
- ['Floating Legend Crowns (Universes Beyond)', 'UBLegendCrownsFloating'],
- ['Legend Crowns (Universes Beyond)', 'UBLegendCrowns'],
- ['Inner Crowns', 'M15InnerCrowns'],
- ['Inner Crowns (Etched)', 'InnerCrownsEtched'],
- ['Miracle', 'M15Miracle'],
- ['Holo Stamps', 'M15HoloStamps'],
- ['Nicknames', 'M15Nickname-2'],
- ['Dark Power/Toughness', 'M15DarkPT'],
- ['Colored Borders', 'M15Borders'],
- ['Color Identity Pips', 'M15CIPips'],
- ['"The List" Stamp', 'TheList'],
- ['Lands', 'M15Lands'],
- ['Spree (Outlaws of Thunder Junction)', 'Spree'],
- ['Spree (Universes Beyond)', 'SpreeUB'],
- ['Cases (Murders at Karlov Manor)', 'Case'],
- ['Battles (March of the Machine)', 'Battle'],
- ['Prototype (Brothers\' War)', 'Prototype'],
- ['Prototype (Extended Art) (Brothers\' War)', 'PrototypeExtended'],
- ['Attractions (Unfinity)', 'Attraction'],
- ['Class (D&D)', 'Class'],
- ['Snow (Kaldheim)', 'M15Snow'],
- ['Mutate (Ikoria)', 'M15Mutate'],
- ['Nyx (Theros)', 'M15Nyx'],
- ['Adventures (Eldraine)', 'Adventure'],
- ['Devoid (Zendikar)', 'M15Devoid'],
- ['Aftermath (Amonkhet)', 'Aftermath'],
- ['Flip (Kamigawa)', 'Flip'],
- ['Levelers (Zendikar)', 'Levelers'],
- ['Split Cards', 'Split'],
- ['Fuse Cards', 'Fuse'],
- ['Conspiracies (Draft Matters)', 'Conspiracy'],
- ['Colorshifted (Planar Chaos)', 'Colorshifted'],
- ['Brawl Legend Crowns', 'Brawl'],
- //showcase
- ['Dossier (MKM)', 'Dossier'],
- ['Scrolls of Middle-earth (LTR)', 'Scroll'],
- ['Pip-Boy (PIP)', 'Pipboy'],
- ['Enchanting Tales (WOT)', 'EnchantingTales'],
- ['TARDIS (WHO)', 'TARDIS'],
- ['Ring (LTR)', 'Ring'],
- ['Ixalan Coin (MOM)', 'IxalanCoin'],
- ['Ikoria Crystal (MOM)', 'Crystal'],
- ['Ravnica City (MOM)', 'Ravnica'],
- ['Tarkir Sketch (MOM)', 'Tarkir'],
- ['Oil Slick (ONE)', 'OilSlick'],
- ['Stained Glass (DMU)', 'DMUStainedGlass'],
- ['Golden Age (SNC)', 'SNCGilded'],
- ['Art Deco (SNC)', 'SNCArtDeco'],
- ['Skyscraper (SNC)', 'SNCSkyscraper'],
- ['Ninja (NEO)', 'NeoNinja'],
- ['Samurai (NEO)', 'NeoSamurai'],
- ['Neon (NEO)', 'NeoNeon'],
- ['Double Feature (DBL)', 'DoubleFeature'],
- ['Double Feature: Transform (DBL)', 'DoubleFeatureTransform'],
- ['Fang (VOW)', 'Fang'],
- ['Equinox: Single-faced (MID)', 'Equinox'],
- ['Equinox: Transform Front (MID)', 'EquinoxFront'],
- ['Equinox: Transform Back (MID)', 'EquinoxBack'],
- ['Eternal Night (MID)', 'EternalNight'],
- ['DND Sourcebook (AFR)', 'DNDSourcebook'],
- ['DND Module (AFR)', 'DNDModule'],
- ['Sketch Cards (MH2)', 'MH2'],
- ['Mystical Archive (STA)', 'MysticalArchive'],
- ['Japanese Mystical Archive (STA)', 'MysticalArchiveJP'],
- ['Phyrexian', 'Praetors'],
- ['Kaldheim (KHM)', 'Kaldheim-2'],
- ['Nonlegendary Kaldheim (KHM)', 'KaldheimNonleg'],
- ['Commander Legends (CMR)', 'CommanderLegends'],
- ['Zendikar Rising (ZNR)', 'ZendikarRising'],
- ['M21 Signature Spellbooks (M21)', 'M21'],
- ['Theros Beyond Death (THB)', 'M15NyxShowcase'],
- ['Eldraine Storybooks: Adventures (ELD)', 'Storybook'],
- ['Eldraine Storybooks: Adventures (WOE)', 'StorybookWOE'],
- ['Eldraine Storybooks (MOM)', 'StorybookMUL'],
- ['Borderless', 'GenericShowcase'],
- ['Borderless (Alt)', 'Borderless'],
- ['Fullart', 'M15ClearTextboxes'],
- ['Nickname ("Godzilla")', 'M15Nickname'],
- ['Extended Art (Regular)', 'M15BoxTopper'],
- ['Extended Art (Shorter Textbox)', 'M15ExtendedArtShort'],
- ['FNM Promo (Inverted Promos)', 'FNM'],
- ['Universes Beyond', 'UB'],
- ['Universes Beyond (Full art)', 'UBFull'],
- ['Universes Beyond (Extended art)', 'UBExtendedArt'],
- ['Full Text', 'FullText'],
- ['Etched', 'Etched'],
- ['Etched (Nyx)', 'EtchedNyx'],
- ['Etched (Snow)', 'EtchedSnow'],
- ['ZNR Expeditions (2020)', 'ExpeditionZNR-1'],
- ['Signature Spellbook (Jace/Gideon)', 'SignatureSpellbook'],
- ['Ixalan Maps', 'Ixalan'],
- ['Amonkhet Invocations (u/Smyris)', 'Invocation'],
- ['Amonkhet Invocations (Multiverse Legends)', 'InvocationMUL'],
- ['Kaladesh Inventions', 'Invention'],
- ['BFZ Expeditions (2015)', 'ExpeditionBFZ-1'],
- ['SDCC15 (Blackout)', 'SDCC15'],
- ['Innistrad: Double Feature Planeswalkers', 'PlaneswalkerDBL'],
- ['Future Shifted', 'FutureRegular'],
- //planeswalker
- ['Planeswalker', 'PlaneswalkerRegular'],
- ['Planeswalker Borderless', 'PlaneswalkerBorderless'],
- ['Planeswalker Extended Art', 'PlaneswalkerBoxTopper'],
- ['Planeswalker Tall', 'PlaneswalkerTall'],
- ['Planeswalker Tall Borderless', 'PlaneswalkerTallBorderless'],
- ['Planeswalker Compleated', 'PlaneswalkerCompleated'],
- ['Planeswalker Holo Stamps', 'PlaneswalkerHoloStamps'],
- ['Planeswalker Nickname', 'PlaneswalkerNickname'],
- ['Planeswalker Blackout (SDCC15)', 'PlaneswalkerSDCC15'],
- ['Planeswalker MDFC', 'PlaneswalkerMDFC'],
- ['Planeswalker Transform (Front)', 'PlaneswalkerTransformFront'],
- ['Planeswalker Transform (Back)', 'PlaneswalkerTransformBack'],
- ['Double Feature Planeswalker Transform (Front)', 'PlaneswalkerTransformFrontDBL'],
- ['Double Feature Planeswalker Transform (Back)', 'PlaneswalkerTransformBackDBL'],
- ['Planeswalker Transform Icons', 'PlaneswalkerTransformIcons'],
- //saga
- ['Sagas', 'SagaRegular'],
- ['Sagas (Universes Beyond)', 'SagaUB'],
- ['Sagas (Scrolls of Middle-earth) (LTR)', 'SagaLTR'],
- //dfc
- ['Transform (Front)', 'M15TransformFront'],
- ['Transform (Back)', 'M15TransformBack'],
- ['Transform (Back) (New)', 'M15TransformBackNew'],
- ['Color Identity Pips', 'M15CIPips'],
- ['Transform Icons', 'M15TransformTypes'],
- ['Sagas (Front)', 'SagaDFC'],
- ['Borderless (Front)', 'TransformBorderlessFront'],
- ['Borderless (Back)', 'TransformBorderlessBack'],
- ['Extended Art (Front)', 'TransformExtendedFront'],
- ['Extended Art (Back)', 'TransformExtendedBack'],
- ['SDCC15 (Blackout)', 'TransformSDCC15'],
- ['DFC Legend Crowns', 'TransformLegendCrowns'],
- ['DFC Floating Legend Crowns', 'TransformLegendCrownsFloating'],
- ['DFC Nickname Legend Crowns', 'TransformLegendCrownsNickname'],
- //modal
- ['Modal DFC', 'ModalRegular'],
- ['Modal DFC Borderless', 'ModalBorderless'],
- ['Modal DFC Extended Art', 'ModalExtended'],
- ['Modal DFC Nickname', 'ModalNickname'],
- ['Modal DFC Short', 'ModalShort'],
- ['Modal DFC Short-Nickname', 'ModalShortNickname'],
- ['Modal DFC Legend Crowns', 'ModalLegendCrowns'],
- ['Modal DFC Floating Legend Crowns', 'ModalLegendCrownsFloating'],
- ['Modal DFC Nickname Legend Crowns', 'ModalLegendCrownsNickname'],
- ['Modal DFC Brawl Legend Crowns', 'ModalLegendCrownsBrawl'],
- ['DFC Helper Cards', 'ModalHelper'],
- //token
- ['Regular Tokens', 'TokenRegular-1'],
- ['Textless Tokens', 'TokenTextless-1'],
- ['Borderless Textless Tokens', 'TokenTextlessBorderless'],
- ['Tall Tokens', 'TokenTall-1'],
- ['Short Tokens', 'TokenShort-1'],
- ['Monarch Token', 'TokenMonarch'],
- ['Initiative Token', 'TokenInitiative'],
- ['Day/Night Marker', 'TokenDayNight'],
- ['Planeswalker Emblems', 'Emblem'],
- ['Jumpstart Front Cards', 'JMPFront'],
- ['Jumpstart 2022 Front Cards', 'J22Front'],
- ['Regular Tokens (Bordered M15)', 'TokenRegularM15'],
- ['Textless Tokens (Bordered M15)', 'TokenTextlessM15'],
- ['Original Tokens (Old Bordered)', 'TokenOld'],
- ['Unglued Tokens', 'TokenUnglued'],
- //misc
- ['Future Shifted', 'FutureRegular'],
- ['Colorshifted', '8thColorshifted'],
- ['8th Edition', '8th'],
- ['Seventh Edition', 'Seventh'],
- ['Fifth Edition', 'SeventhButFifth'],
- ['Fourth Edition', 'Fourth'],
- ['Legends Multicolored', 'Legends'],
- ['Alpha/Beta/Unlimited', 'ABU'],
- ['Playtest Cards', 'Playtest'],
- ['Dungeon (AFR)', 'Dungeon'],
- ['Planechase', 'Planechase'],
- ['Vanguard', 'Vanguard'],
- ['Cardback', 'Cardback'],
- //promo
- ['Promos', 'PromoOpenHouse'],
- ['Promo Borderless Frames', 'PromoRegular-1'],
- ['Promo Borderless Frames (Extra Short)', 'IkoShort'],
- ['Promo Extended Art Frames', 'PromoExtended'],
- ['Promo Nickname Frames', 'PromoNickname'],
- ['Promo Generic Showcase', 'PromoGenericShowcase'],
- //textless
- ['Kamigawa Basics (NEO)', 'NeoBasics'],
- ['Fullart Basics (2022)', 'TextlessBasics2022'],
- ['Fullart Basics (Universes Beyond)', 'TextlessBasics2022UB'],
- ['Fullart Basics (SNC)', 'TextlessBasicsSNC'],
- ['Fullart Basics (THB)', 'TextlessBasics'],
- ['Fullart Basics (ZEN)', 'ZendikarBasic-1'],
- ['Fullart Snow Basics', 'FullartBasicRoundBottom'],
- ['Unstable Basics (UST)', 'Unstable'],
- ['Unhinged Basics (UNH)', 'Unhinged'],
- ['Generic Showcase', 'TextlessGenericShowcase'],
- ['Magic Fest Promos', 'MagicFest'],
- ['Extended Art Invocations', 'AKHInvocationExtended'],
- ['Textless Inventions', 'TextlessInvention'],
- ['Textless Seventh', 'SeventhTextless'],
- //custom
- ['Misc Custom Frames', 'MiscCustom'],
- ['Deck Covers', 'CustomDeckCover'],
- ['Simple Inventions', 'SimpleInventions'],
- ['Tapped (Horizontal M15)', 'Tapped'],
- ['Textless Duals', 'CustomDualLands'],
- ['Seventh Edition Planeswalkers', 'PlaneswalkerSeventh'],
- ['Seventh Edition Sagas', 'OldSaga'],
- ['Seventh Edition Snow Lands', 'SeventhSnowLands'],
- ['Floating Old Border', 'OldFloating'],
- ['Floating Old Border (Short)', 'OldFloatingShort'],
- ['Classicshifted', 'Classicshifted'],
- ['Classicshifted Lands', 'ClassicshiftedLands'],
- ['Classicshifted Planeswalkers', 'ClassicshiftedPlaneswalker'],
- ['Classicshifted Planeswalker Transform Addons', 'ClassicshiftedPlaneswalkerTransform'],
- ['Classicshifted Sagas', 'ClassicshiftedSaga'],
- ['Classicshifted MDFC Addons', 'ClassicshiftedDFC'],
- ['Classicshifted Transform Addons', 'ClassicshiftedTransform'],
- ['Classicshifted Color Identity Pips', 'ClassicshiftedCIPips'],
- ['Short Neon (NEO)', 'NEONeonShort'],
- ['Colored Golden Age (SNC)', 'SNCGildedColored'],
- ['Textless Golden Age (SNC)', 'SNCGildedTextless'],
- ['Textless Equinox (MID)', 'EquinoxTextless'],
- ['Horizontal Japanese Mystical Archive (STA)', 'MysticalArchiveJPHorizontal'],
- ['Brawl Legend Crowns', 'Brawl'],
- ['Cartoony - Sheepwave', 'Cartoony'],
- ['Neon - Elry', 'CustomNeon'],
- ['Ixalan - @feuer_ameise', 'FeuerAmeiseIxalan'],
- ['Kaldheim, Fullart - @feuer_ameise', 'FeuerAmeiseKaldheim'],
- ['Celid\'s Asap', 'CustomCelidAsap'],
- ['Magrao\'s Kaldheim', 'CustomMagraoKaldheim'],
- ['Pokemon', 'Pokemon'],
- ['Circuit', 'Circuit'],
-]);
-
-frameSearch = (str) => {
- if (frameNames.has(str)) loadScript("/js/frames/pack" + frameNames.get(str) + ".js");
-}
-
-//Thank you to w3schools for providing the following quick-and-easy autocomplete code :)
-//(some modifications made)
-
-autocomplete(document.getElementById("frameSearch"), Array.from(frameNames.keys()));
-
-function autocomplete(inp, arr) {
- var currentFocus;
- inp.addEventListener("input", function(e) {
- var a, b, i, val = this.value;
- closeAllLists();
- if (!val) { return false;}
- currentFocus = -1;
- a = document.createElement("DIV");
- a.setAttribute("id", this.id + "autocomplete-list");
- a.setAttribute("class", "autocomplete-items");
- this.parentNode.appendChild(a);
- for (i = 0; i < arr.length; i++) {
- if (arr[i].toUpperCase().includes(val.toUpperCase())) {
- b = document.createElement("DIV");
- b.setAttribute("class", "input")
- b.innerHTML = arr[i];
- b.addEventListener("click", function(e) {
- inp.value = this.innerHTML;
- frameSearch(inp.value);
- closeAllLists();
- });
- a.appendChild(b);
- }
- }
- });
- inp.addEventListener("keydown", function(e) {
- var x = document.getElementById(this.id + "autocomplete-list");
- if (x) x = x.getElementsByTagName("div");
- if (e.keyCode == 40) {
- currentFocus++;
- addActive(x);
- } else if (e.keyCode == 38) {
- currentFocus--;
- addActive(x);
- } else if (e.keyCode == 13) {
- e.preventDefault();
- if (currentFocus > -1) {
- if (x) x[currentFocus].click();
- }
- } else if (e.keyCode == 27) {
- closeAllLists();
- }
- });
- function addActive(x) {
- if (!x) return false;
- removeActive(x);
- if (currentFocus >= x.length) currentFocus = 0;
- if (currentFocus < 0) currentFocus = (x.length - 1);
- x[currentFocus].classList.add("autocomplete-active");
- }
- function removeActive(x) {
- for (var i = 0; i < x.length; i++) {
- x[i].classList.remove("autocomplete-active");
- }
- }
- function closeAllLists(elmnt) {
- var x = document.getElementsByClassName("autocomplete-items");
- for (var i = 0; i < x.length; i++) {
- if (elmnt != x[i] && elmnt != inp) {
- x[i].parentNode.removeChild(x[i]);
- }
- }
- }
- document.addEventListener("click", function (e) {
- closeAllLists(e.target);
- });
+const frameNames = new Map ([
+ //standard
+ ['Regular Frames', 'M15Regular-1'],
+ ['Legend Crowns', 'M15LegendCrowns'],
+ ['Legend Crowns (Etched)', 'LegendCrownsEtched'],
+ ['Floating Legend Crowns', 'M15LegendCrownsFloating'],
+ ['Floating Legend Crowns (Universes Beyond)', 'UBLegendCrownsFloating'],
+ ['Legend Crowns (Universes Beyond)', 'UBLegendCrowns'],
+ ['Inner Crowns', 'M15InnerCrowns'],
+ ['Inner Crowns (Etched)', 'InnerCrownsEtched'],
+ ['Miracle', 'M15Miracle'],
+ ['Holo Stamps', 'M15HoloStamps'],
+ ['Nicknames', 'M15Nickname-2'],
+ ['Dark Power/Toughness', 'M15DarkPT'],
+ ['Colored Borders', 'M15Borders'],
+ ['Color Identity Pips', 'M15CIPips'],
+ ['"The List" Stamp', 'TheList'],
+ ['Lands', 'M15Lands'],
+ ['Spree (Outlaws of Thunder Junction)', 'Spree'],
+ ['Spree (Universes Beyond)', 'SpreeUB'],
+ ['Cases (Murders at Karlov Manor)', 'Case'],
+ ['Battles (March of the Machine)', 'Battle'],
+ ['Prototype (Brothers\' War)', 'Prototype'],
+ ['Prototype (Extended Art) (Brothers\' War)', 'PrototypeExtended'],
+ ['Attractions (Unfinity)', 'Attraction'],
+ ['Class (D&D)', 'Class'],
+ ['Snow (Kaldheim)', 'M15Snow'],
+ ['Mutate (Ikoria)', 'M15Mutate'],
+ ['Nyx (Theros)', 'M15Nyx'],
+ ['Adventures (Eldraine)', 'Adventure'],
+ ['Devoid (Zendikar)', 'M15Devoid'],
+ ['Aftermath (Amonkhet)', 'Aftermath'],
+ ['Flip (Kamigawa)', 'Flip'],
+ ['Levelers (Zendikar)', 'Levelers'],
+ ['Split Cards', 'Split'],
+ ['Fuse Cards', 'Fuse'],
+ ['Conspiracies (Draft Matters)', 'Conspiracy'],
+ ['Colorshifted (Planar Chaos)', 'Colorshifted'],
+ ['Brawl Legend Crowns', 'Brawl'],
+ //showcase
+ ['Wanted (OTJ)', 'Wanted'],
+ ['Dossier (MKM)', 'Dossier'],
+ ['Scrolls of Middle-earth (LTR)', 'Scroll'],
+ ['Pip-Boy (PIP)', 'Pipboy'],
+ ['Enchanting Tales (WOT)', 'EnchantingTales'],
+ ['TARDIS (WHO)', 'TARDIS'],
+ ['Ring (LTR)', 'Ring'],
+ ['Ixalan Coin (MOM)', 'IxalanCoin'],
+ ['Ikoria Crystal (MOM)', 'Crystal'],
+ ['Ravnica City (MOM)', 'Ravnica'],
+ ['Tarkir Sketch (MOM)', 'Tarkir'],
+ ['Oil Slick (ONE)', 'OilSlick'],
+ ['Stained Glass (DMU)', 'DMUStainedGlass'],
+ ['Golden Age (SNC)', 'SNCGilded'],
+ ['Art Deco (SNC)', 'SNCArtDeco'],
+ ['Skyscraper (SNC)', 'SNCSkyscraper'],
+ ['Ninja (NEO)', 'NeoNinja'],
+ ['Samurai (NEO)', 'NeoSamurai'],
+ ['Neon (NEO)', 'NeoNeon'],
+ ['Double Feature (DBL)', 'DoubleFeature'],
+ ['Double Feature: Transform (DBL)', 'DoubleFeatureTransform'],
+ ['Fang (VOW)', 'Fang'],
+ ['Equinox: Single-faced (MID)', 'Equinox'],
+ ['Equinox: Transform Front (MID)', 'EquinoxFront'],
+ ['Equinox: Transform Back (MID)', 'EquinoxBack'],
+ ['Eternal Night (MID)', 'EternalNight'],
+ ['DND Sourcebook (AFR)', 'DNDSourcebook'],
+ ['DND Module (AFR)', 'DNDModule'],
+ ['Sketch Cards (MH2)', 'MH2'],
+ ['Mystical Archive (STA)', 'MysticalArchive'],
+ ['Japanese Mystical Archive (STA)', 'MysticalArchiveJP'],
+ ['Phyrexian', 'Praetors'],
+ ['Kaldheim (KHM)', 'Kaldheim-2'],
+ ['Nonlegendary Kaldheim (KHM)', 'KaldheimNonleg'],
+ ['Commander Legends (CMR)', 'CommanderLegends'],
+ ['Zendikar Rising (ZNR)', 'ZendikarRising'],
+ ['M21 Signature Spellbooks (M21)', 'M21'],
+ ['Theros Beyond Death (THB)', 'M15NyxShowcase'],
+ ['Eldraine Storybooks: Adventures (ELD)', 'Storybook'],
+ ['Eldraine Storybooks: Adventures (WOE)', 'StorybookWOE'],
+ ['Eldraine Storybooks (MOM)', 'StorybookMUL'],
+ ['Borderless', 'GenericShowcase'],
+ ['Borderless (Alt)', 'Borderless'],
+ ['Fullart', 'M15ClearTextboxes'],
+ ['Nickname ("Godzilla")', 'M15Nickname'],
+ ['Extended Art (Regular)', 'M15BoxTopper'],
+ ['Extended Art (Shorter Textbox)', 'M15ExtendedArtShort'],
+ ['FNM Promo (Inverted Promos)', 'FNM'],
+ ['Universes Beyond', 'UB'],
+ ['Universes Beyond (Full art)', 'UBFull'],
+ ['Universes Beyond (Extended art)', 'UBExtendedArt'],
+ ['Full Text', 'FullText'],
+ ['Etched', 'Etched'],
+ ['Etched (Nyx)', 'EtchedNyx'],
+ ['Etched (Snow)', 'EtchedSnow'],
+ ['ZNR Expeditions (2020)', 'ExpeditionZNR-1'],
+ ['Signature Spellbook (Jace/Gideon)', 'SignatureSpellbook'],
+ ['Ixalan Maps', 'Ixalan'],
+ ['Amonkhet Invocations (u/Smyris)', 'Invocation'],
+ ['Amonkhet Invocations (Multiverse Legends)', 'InvocationMUL'],
+ ['Kaladesh Inventions', 'Invention'],
+ ['BFZ Expeditions (2015)', 'ExpeditionBFZ-1'],
+ ['SDCC15 (Blackout)', 'SDCC15'],
+ ['Innistrad: Double Feature Planeswalkers', 'PlaneswalkerDBL'],
+ ['Future Shifted', 'FutureRegular'],
+ //planeswalker
+ ['Planeswalker', 'PlaneswalkerRegular'],
+ ['Planeswalker Borderless', 'PlaneswalkerBorderless'],
+ ['Planeswalker Extended Art', 'PlaneswalkerBoxTopper'],
+ ['Planeswalker Tall', 'PlaneswalkerTall'],
+ ['Planeswalker Tall Borderless', 'PlaneswalkerTallBorderless'],
+ ['Planeswalker Compleated', 'PlaneswalkerCompleated'],
+ ['Planeswalker Holo Stamps', 'PlaneswalkerHoloStamps'],
+ ['Planeswalker Nickname', 'PlaneswalkerNickname'],
+ ['Planeswalker Blackout (SDCC15)', 'PlaneswalkerSDCC15'],
+ ['Planeswalker MDFC', 'PlaneswalkerMDFC'],
+ ['Planeswalker Transform (Front)', 'PlaneswalkerTransformFront'],
+ ['Planeswalker Transform (Back)', 'PlaneswalkerTransformBack'],
+ ['Double Feature Planeswalker Transform (Front)', 'PlaneswalkerTransformFrontDBL'],
+ ['Double Feature Planeswalker Transform (Back)', 'PlaneswalkerTransformBackDBL'],
+ ['Planeswalker Transform Icons', 'PlaneswalkerTransformIcons'],
+ //saga
+ ['Sagas', 'SagaRegular'],
+ ['Sagas (Universes Beyond)', 'SagaUB'],
+ ['Sagas (Scrolls of Middle-earth) (LTR)', 'SagaLTR'],
+ //dfc
+ ['Transform (Front)', 'M15TransformFront'],
+ ['Transform (Back)', 'M15TransformBack'],
+ ['Transform (Back) (New)', 'M15TransformBackNew'],
+ ['Color Identity Pips', 'M15CIPips'],
+ ['Transform Icons', 'M15TransformTypes'],
+ ['Sagas (Front)', 'SagaDFC'],
+ ['Borderless (Front)', 'TransformBorderlessFront'],
+ ['Borderless (Back)', 'TransformBorderlessBack'],
+ ['Extended Art (Front)', 'TransformExtendedFront'],
+ ['Extended Art (Back)', 'TransformExtendedBack'],
+ ['SDCC15 (Blackout)', 'TransformSDCC15'],
+ ['DFC Legend Crowns', 'TransformLegendCrowns'],
+ ['DFC Floating Legend Crowns', 'TransformLegendCrownsFloating'],
+ ['DFC Nickname Legend Crowns', 'TransformLegendCrownsNickname'],
+ //modal
+ ['Modal DFC', 'ModalRegular'],
+ ['Modal DFC Borderless', 'ModalBorderless'],
+ ['Modal DFC Extended Art', 'ModalExtended'],
+ ['Modal DFC Nickname', 'ModalNickname'],
+ ['Modal DFC Short', 'ModalShort'],
+ ['Modal DFC Short-Nickname', 'ModalShortNickname'],
+ ['Modal DFC Legend Crowns', 'ModalLegendCrowns'],
+ ['Modal DFC Floating Legend Crowns', 'ModalLegendCrownsFloating'],
+ ['Modal DFC Nickname Legend Crowns', 'ModalLegendCrownsNickname'],
+ ['Modal DFC Brawl Legend Crowns', 'ModalLegendCrownsBrawl'],
+ ['DFC Helper Cards', 'ModalHelper'],
+ //token
+ ['Regular Tokens', 'TokenRegular-1'],
+ ['Textless Tokens', 'TokenTextless-1'],
+ ['Borderless Textless Tokens', 'TokenTextlessBorderless'],
+ ['Tall Tokens', 'TokenTall-1'],
+ ['Short Tokens', 'TokenShort-1'],
+ ['Monarch Token', 'TokenMonarch'],
+ ['Initiative Token', 'TokenInitiative'],
+ ['Day/Night Marker', 'TokenDayNight'],
+ ['Planeswalker Emblems', 'Emblem'],
+ ['Jumpstart Front Cards', 'JMPFront'],
+ ['Jumpstart 2022 Front Cards', 'J22Front'],
+ ['Regular Tokens (Bordered M15)', 'TokenRegularM15'],
+ ['Textless Tokens (Bordered M15)', 'TokenTextlessM15'],
+ ['Original Tokens (Old Bordered)', 'TokenOld'],
+ ['Unglued Tokens', 'TokenUnglued'],
+ //misc
+ ['Future Shifted', 'FutureRegular'],
+ ['Colorshifted', '8thColorshifted'],
+ ['8th Edition', '8th'],
+ ['Seventh Edition', 'Seventh'],
+ ['Fifth Edition', 'SeventhButFifth'],
+ ['Fourth Edition', 'Fourth'],
+ ['Legends Multicolored', 'Legends'],
+ ['Alpha/Beta/Unlimited', 'ABU'],
+ ['Playtest Cards', 'Playtest'],
+ ['Dungeon (AFR)', 'Dungeon'],
+ ['Planechase', 'Planechase'],
+ ['Vanguard', 'Vanguard'],
+ ['Cardback', 'Cardback'],
+ //promo
+ ['Promos', 'PromoOpenHouse'],
+ ['Promo Borderless Frames', 'PromoRegular-1'],
+ ['Promo Borderless Frames (Extra Short)', 'IkoShort'],
+ ['Promo Extended Art Frames', 'PromoExtended'],
+ ['Promo Nickname Frames', 'PromoNickname'],
+ ['Promo Generic Showcase', 'PromoGenericShowcase'],
+ //textless
+ ['Kamigawa Basics (NEO)', 'NeoBasics'],
+ ['Fullart Basics (2022)', 'TextlessBasics2022'],
+ ['Fullart Basics (Universes Beyond)', 'TextlessBasics2022UB'],
+ ['Fullart Basics (SNC)', 'TextlessBasicsSNC'],
+ ['Fullart Basics (THB)', 'TextlessBasics'],
+ ['Fullart Basics (ZEN)', 'ZendikarBasic-1'],
+ ['Fullart Snow Basics', 'FullartBasicRoundBottom'],
+ ['Unstable Basics (UST)', 'Unstable'],
+ ['Unhinged Basics (UNH)', 'Unhinged'],
+ ['Generic Showcase', 'TextlessGenericShowcase'],
+ ['Magic Fest Promos', 'MagicFest'],
+ ['Extended Art Invocations', 'AKHInvocationExtended'],
+ ['Textless Inventions', 'TextlessInvention'],
+ ['Textless Seventh', 'SeventhTextless'],
+ //custom
+ ['Misc Custom Frames', 'MiscCustom'],
+ ['Deck Covers', 'CustomDeckCover'],
+ ['Simple Inventions', 'SimpleInventions'],
+ ['Tapped (Horizontal M15)', 'Tapped'],
+ ['Textless Duals', 'CustomDualLands'],
+ ['Seventh Edition Planeswalkers', 'PlaneswalkerSeventh'],
+ ['Seventh Edition Sagas', 'OldSaga'],
+ ['Seventh Edition Snow Lands', 'SeventhSnowLands'],
+ ['Floating Old Border', 'OldFloating'],
+ ['Floating Old Border (Short)', 'OldFloatingShort'],
+ ['Classicshifted', 'Classicshifted'],
+ ['Classicshifted Lands', 'ClassicshiftedLands'],
+ ['Classicshifted Planeswalkers', 'ClassicshiftedPlaneswalker'],
+ ['Classicshifted Planeswalker Transform Addons', 'ClassicshiftedPlaneswalkerTransform'],
+ ['Classicshifted Sagas', 'ClassicshiftedSaga'],
+ ['Classicshifted MDFC Addons', 'ClassicshiftedDFC'],
+ ['Classicshifted Transform Addons', 'ClassicshiftedTransform'],
+ ['Classicshifted Color Identity Pips', 'ClassicshiftedCIPips'],
+ ['Short Neon (NEO)', 'NEONeonShort'],
+ ['Colored Golden Age (SNC)', 'SNCGildedColored'],
+ ['Textless Golden Age (SNC)', 'SNCGildedTextless'],
+ ['Textless Equinox (MID)', 'EquinoxTextless'],
+ ['Horizontal Japanese Mystical Archive (STA)', 'MysticalArchiveJPHorizontal'],
+ ['Brawl Legend Crowns', 'Brawl'],
+ ['Cartoony - Sheepwave', 'Cartoony'],
+ ['Neon - Elry', 'CustomNeon'],
+ ['Ixalan - @feuer_ameise', 'FeuerAmeiseIxalan'],
+ ['Kaldheim, Fullart - @feuer_ameise', 'FeuerAmeiseKaldheim'],
+ ['Celid\'s Asap', 'CustomCelidAsap'],
+ ['Magrao\'s Kaldheim', 'CustomMagraoKaldheim'],
+ ['Pokemon', 'Pokemon'],
+ ['Circuit', 'Circuit'],
+]);
+
+frameSearch = (str) => {
+ if (frameNames.has(str)) loadScript("/js/frames/pack" + frameNames.get(str) + ".js");
+}
+
+//Thank you to w3schools for providing the following quick-and-easy autocomplete code :)
+//(some modifications made)
+
+autocomplete(document.getElementById("frameSearch"), Array.from(frameNames.keys()));
+
+function autocomplete(inp, arr) {
+ var currentFocus;
+ inp.addEventListener("input", function(e) {
+ var a, b, i, val = this.value;
+ closeAllLists();
+ if (!val) { return false;}
+ currentFocus = -1;
+ a = document.createElement("DIV");
+ a.setAttribute("id", this.id + "autocomplete-list");
+ a.setAttribute("class", "autocomplete-items");
+ this.parentNode.appendChild(a);
+ for (i = 0; i < arr.length; i++) {
+ if (arr[i].toUpperCase().includes(val.toUpperCase())) {
+ b = document.createElement("DIV");
+ b.setAttribute("class", "input")
+ b.innerHTML = arr[i];
+ b.addEventListener("click", function(e) {
+ inp.value = this.innerHTML;
+ frameSearch(inp.value);
+ closeAllLists();
+ });
+ a.appendChild(b);
+ }
+ }
+ });
+ inp.addEventListener("keydown", function(e) {
+ var x = document.getElementById(this.id + "autocomplete-list");
+ if (x) x = x.getElementsByTagName("div");
+ if (e.keyCode == 40) {
+ currentFocus++;
+ addActive(x);
+ } else if (e.keyCode == 38) {
+ currentFocus--;
+ addActive(x);
+ } else if (e.keyCode == 13) {
+ e.preventDefault();
+ if (currentFocus > -1) {
+ if (x) x[currentFocus].click();
+ }
+ } else if (e.keyCode == 27) {
+ closeAllLists();
+ }
+ });
+ function addActive(x) {
+ if (!x) return false;
+ removeActive(x);
+ if (currentFocus >= x.length) currentFocus = 0;
+ if (currentFocus < 0) currentFocus = (x.length - 1);
+ x[currentFocus].classList.add("autocomplete-active");
+ }
+ function removeActive(x) {
+ for (var i = 0; i < x.length; i++) {
+ x[i].classList.remove("autocomplete-active");
+ }
+ }
+ function closeAllLists(elmnt) {
+ var x = document.getElementsByClassName("autocomplete-items");
+ for (var i = 0; i < x.length; i++) {
+ if (elmnt != x[i] && elmnt != inp) {
+ x[i].parentNode.removeChild(x[i]);
+ }
+ }
+ }
+ document.addEventListener("click", function (e) {
+ closeAllLists(e.target);
+ });
}
\ No newline at end of file
diff --git a/js/frames/groupMargin.js b/js/frames/groupMargin.js
index ac25c38c..3445e49f 100644
--- a/js/frames/groupMargin.js
+++ b/js/frames/groupMargin.js
@@ -1,5 +1,6 @@
loadFramePacks([
{name:'Generic Margins', value:'Margin-1'},
+ {name:'Wanted Margin', value:'MarginWanted'},
{name:'Enchanting Tales Margins', value:'MarginEnchantingTales'},
{name:'LTR Ring Margins', value:'MarginRing'},
{name:'D&D Module Margins', value:'MarginDNDModule'},
diff --git a/js/frames/groupShowcase-5.js b/js/frames/groupShowcase-5.js
index 80aef84c..c0aeb760 100644
--- a/js/frames/groupShowcase-5.js
+++ b/js/frames/groupShowcase-5.js
@@ -1,94 +1,95 @@
-loadFramePacks([
- {name:'Set Showcase Frames (Chronological)', value:'disabled'},
- {name:'Pip-Boy (PIP)', value:'Pipboy'},
- {name:'Dossier (MKM)', value:'Dossier'},
- {name:'Scrolls of Middle-earth (LTR)', value:'Scroll'},
- {name:'Enchanting Tales (WOT)', value:'EnchantingTales'},
- {name:'Eldraine Storybooks: Adventures (WOE)', value:'StorybookWOE'},
- {name:'TARDIS (WHO)', value:'TARDIS'},
- {name:'Ring (LTR)', value:'Ring'},
- {name:'Eldraine Storybooks (MOM)', value:'StorybookMUL'},
- {name:'Ixalan Coin (MOM)', value:'IxalanCoin'},
- {name:'Tarkir Sketch (MOM)', value:'Tarkir'},
- {name:'Ikoria Crystal (MOM)', value:'Crystal'},
- {name:'Ravnica City (MOM)', value:'Ravnica'},
- {name:'Oil Slick (ONE)', value:'OilSlick'},
- {name:'Stained Glass (DMU)', value:'DMUStainedGlass'},
- {name:'Golden Age (SNC)', value:'SNCGilded'},
- {name:'Art Deco (SNC)', value:'SNCArtDeco'},
- {name:'Skyscraper (SNC)', value:'SNCSkyscraper'},
- {name:'Ninja (NEO)', value:'NeoNinja'},
- {name:'Samurai (NEO)', value:'NeoSamurai'},
- {name:'Neon (NEO)', value:'NeoNeon'},
- {name:'Double Feature (DBL)', value:'DoubleFeature'},
- {name:'Double Feature: Transform (DBL)', value:'DoubleFeatureTransform'},
- {name:'Fang (VOW)', value:'Fang'},
- {name:'Equinox: Single-faced (MID)', value:'Equinox'},
- {name:'Equinox: Transform Front (MID)', value:'EquinoxFront'},
- {name:'Equinox: Transform Back (MID)', value:'EquinoxBack'},
- {name:'Eternal Night (MID)', value:'EternalNight'},
- {name:'D&D Sourcebook (AFR)', value:'DNDSourcebook'},
- {name:'D&D Module (AFR)', value:'DNDModule'},
- {name:'Sketch Cards (MH2)', value:'MH2'},
- {name:'Mystical Archive (STA)', value:'MysticalArchive'},
- {name:'Japanese Mystical Archive (STA)', value:'MysticalArchiveJP'},
- {name:'Horizontal Japanese Mystical Archive (STA)', value:'MysticalArchiveJPHorizontal'},
- {name:'Kaldheim (KHM)', value:'Kaldheim-2'},
- {name:'Nonlegendary Kaldheim (KHM)', value:'KaldheimNonleg'},
- {name:'Commander Legends (CMR)', value:'CommanderLegends'},
- {name:'Zendikar Rising (ZNR)', value:'ZendikarRising'},
- {name:'M21 Signature Spellbooks (M21)', value:'M21'},
- {name:'Theros Beyond Death (THB)', value:'M15NyxShowcase'},
- {name:'Eldraine Storybooks: Adventures (ELD)', value:'Storybook'},
-
- {name:'Generic Showcase Frames', value:'disabled'},
- {name:'Borderless', value:'GenericShowcase'},
- {name:'Borderless (Alt)', value:'Borderless'},
- {name:'Fullart', value:'M15ClearTextboxes'},
- {name:'Nickname ("Godzilla")', value:'M15Nickname'},
- {name:'Extended Art (Regular)', value:'M15BoxTopper'},
- {name:'Extended Art (Shorter Textbox)', value:'M15ExtendedArtShort'},
- {name:'FNM Promo (Inverted Promos)', value:'FNM'},
- {name:'Full Text', value:'FullText'},
- {name:'Foil-Etched', value:'disabled'},
- {name:'Etched', value:'Etched'},
- {name:'Etched (Nyx)', value:'EtchedNyx'},
- {name:'Etched (Snow)', value:'EtchedSnow'},
- {name:'Legend Crowns (Etched)', value:'LegendCrownsEtched'},
- {name:'Inner Crowns (Etched)', value:'InnerCrownsEtched'},
-
- {name:'Universes Beyond', value:'disabled'},
- {name:'Universes Beyond', value:'UB'},
- {name:'Universes Beyond (Full art)', value:'UBFull'},
- {name:'Universes Beyond (Extended art)', value:'UBExtendedArt'},
- {name:'Legend Crowns (Universes Beyond)', value:'UBLegendCrowns'},
- {name:'Floating Legend Crowns (Universes Beyond)', value:'UBLegendCrownsFloating'},
-
- {name:'Masterpieces/Other', value:'disabled'},
- {name:'Phyrexian', value:'Praetors'},
- {name:'ZNR Expeditions (2020)', value:'ExpeditionZNR-1'},
- {name:'Signature Spellbook (Jace/Gideon)', value:'SignatureSpellbook'},
- {name:'Ixalan Maps', value:'Ixalan'},
- {name:'Amonkhet Invocations (u/Smyris)', value:'Invocation'},
- {name:'Amonkhet Invocations (Multiverse Legends)', value:'InvocationMUL'},
- {name:'Kaladesh Inventions', value:'Invention'},
- {name:'BFZ Expeditions (2015)', value:'ExpeditionBFZ-1'},
- {name:'SDCC15 (Blackout)', value:'SDCC15'},
- {name:'Future Shifted', value:'FutureRegular'},
-
- {name:'Addons', value:'disabled'},
- {name:'Legend Crowns', value:'M15LegendCrowns'},
- {name:'Legend Crowns (Universes Beyond)', value:'UBLegendCrowns'},
- {name:'Floating Legend Crowns', value:'M15LegendCrownsFloating'},
- {name:'Floating Legend Crowns (Universes Beyond)', value:'UBLegendCrownsFloating'},
- {name:'Inner Crowns', value:'M15InnerCrowns'},
- {name:'Nicknames', value:'M15Nickname-2'},
- {name:'Holo Stamps', value:'M15HoloStamps'},
- {name:'Dark Power/Toughness', value:'M15DarkPT'},
- {name:'Colored Borders', value:'M15Borders'},
- {name:'Color Identity Pips', value:'M15CIPips'},
- {name:'"The List" Stamp', value:'TheList'},
-
- {name:'Custom Addons', value:'disabled'},
- {name:'Brawl Legend Crowns', value:'Brawl'}
+loadFramePacks([
+ {name:'Set Showcase Frames (Chronological)', value:'disabled'},
+ {name:'Wanted (OTJ)', value:'Wanted'},
+ {name:'Pip-Boy (PIP)', value:'Pipboy'},
+ {name:'Dossier (MKM)', value:'Dossier'},
+ {name:'Scrolls of Middle-earth (LTR)', value:'Scroll'},
+ {name:'Enchanting Tales (WOT)', value:'EnchantingTales'},
+ {name:'Eldraine Storybooks: Adventures (WOE)', value:'StorybookWOE'},
+ {name:'TARDIS (WHO)', value:'TARDIS'},
+ {name:'Ring (LTR)', value:'Ring'},
+ {name:'Eldraine Storybooks (MOM)', value:'StorybookMUL'},
+ {name:'Ixalan Coin (MOM)', value:'IxalanCoin'},
+ {name:'Tarkir Sketch (MOM)', value:'Tarkir'},
+ {name:'Ikoria Crystal (MOM)', value:'Crystal'},
+ {name:'Ravnica City (MOM)', value:'Ravnica'},
+ {name:'Oil Slick (ONE)', value:'OilSlick'},
+ {name:'Stained Glass (DMU)', value:'DMUStainedGlass'},
+ {name:'Golden Age (SNC)', value:'SNCGilded'},
+ {name:'Art Deco (SNC)', value:'SNCArtDeco'},
+ {name:'Skyscraper (SNC)', value:'SNCSkyscraper'},
+ {name:'Ninja (NEO)', value:'NeoNinja'},
+ {name:'Samurai (NEO)', value:'NeoSamurai'},
+ {name:'Neon (NEO)', value:'NeoNeon'},
+ {name:'Double Feature (DBL)', value:'DoubleFeature'},
+ {name:'Double Feature: Transform (DBL)', value:'DoubleFeatureTransform'},
+ {name:'Fang (VOW)', value:'Fang'},
+ {name:'Equinox: Single-faced (MID)', value:'Equinox'},
+ {name:'Equinox: Transform Front (MID)', value:'EquinoxFront'},
+ {name:'Equinox: Transform Back (MID)', value:'EquinoxBack'},
+ {name:'Eternal Night (MID)', value:'EternalNight'},
+ {name:'D&D Sourcebook (AFR)', value:'DNDSourcebook'},
+ {name:'D&D Module (AFR)', value:'DNDModule'},
+ {name:'Sketch Cards (MH2)', value:'MH2'},
+ {name:'Mystical Archive (STA)', value:'MysticalArchive'},
+ {name:'Japanese Mystical Archive (STA)', value:'MysticalArchiveJP'},
+ {name:'Horizontal Japanese Mystical Archive (STA)', value:'MysticalArchiveJPHorizontal'},
+ {name:'Kaldheim (KHM)', value:'Kaldheim-2'},
+ {name:'Nonlegendary Kaldheim (KHM)', value:'KaldheimNonleg'},
+ {name:'Commander Legends (CMR)', value:'CommanderLegends'},
+ {name:'Zendikar Rising (ZNR)', value:'ZendikarRising'},
+ {name:'M21 Signature Spellbooks (M21)', value:'M21'},
+ {name:'Theros Beyond Death (THB)', value:'M15NyxShowcase'},
+ {name:'Eldraine Storybooks: Adventures (ELD)', value:'Storybook'},
+
+ {name:'Generic Showcase Frames', value:'disabled'},
+ {name:'Borderless', value:'GenericShowcase'},
+ {name:'Borderless (Alt)', value:'Borderless'},
+ {name:'Fullart', value:'M15ClearTextboxes'},
+ {name:'Nickname ("Godzilla")', value:'M15Nickname'},
+ {name:'Extended Art (Regular)', value:'M15BoxTopper'},
+ {name:'Extended Art (Shorter Textbox)', value:'M15ExtendedArtShort'},
+ {name:'FNM Promo (Inverted Promos)', value:'FNM'},
+ {name:'Full Text', value:'FullText'},
+ {name:'Foil-Etched', value:'disabled'},
+ {name:'Etched', value:'Etched'},
+ {name:'Etched (Nyx)', value:'EtchedNyx'},
+ {name:'Etched (Snow)', value:'EtchedSnow'},
+ {name:'Legend Crowns (Etched)', value:'LegendCrownsEtched'},
+ {name:'Inner Crowns (Etched)', value:'InnerCrownsEtched'},
+
+ {name:'Universes Beyond', value:'disabled'},
+ {name:'Universes Beyond', value:'UB'},
+ {name:'Universes Beyond (Full art)', value:'UBFull'},
+ {name:'Universes Beyond (Extended art)', value:'UBExtendedArt'},
+ {name:'Legend Crowns (Universes Beyond)', value:'UBLegendCrowns'},
+ {name:'Floating Legend Crowns (Universes Beyond)', value:'UBLegendCrownsFloating'},
+
+ {name:'Masterpieces/Other', value:'disabled'},
+ {name:'Phyrexian', value:'Praetors'},
+ {name:'ZNR Expeditions (2020)', value:'ExpeditionZNR-1'},
+ {name:'Signature Spellbook (Jace/Gideon)', value:'SignatureSpellbook'},
+ {name:'Ixalan Maps', value:'Ixalan'},
+ {name:'Amonkhet Invocations (u/Smyris)', value:'Invocation'},
+ {name:'Amonkhet Invocations (Multiverse Legends)', value:'InvocationMUL'},
+ {name:'Kaladesh Inventions', value:'Invention'},
+ {name:'BFZ Expeditions (2015)', value:'ExpeditionBFZ-1'},
+ {name:'SDCC15 (Blackout)', value:'SDCC15'},
+ {name:'Future Shifted', value:'FutureRegular'},
+
+ {name:'Addons', value:'disabled'},
+ {name:'Legend Crowns', value:'M15LegendCrowns'},
+ {name:'Legend Crowns (Universes Beyond)', value:'UBLegendCrowns'},
+ {name:'Floating Legend Crowns', value:'M15LegendCrownsFloating'},
+ {name:'Floating Legend Crowns (Universes Beyond)', value:'UBLegendCrownsFloating'},
+ {name:'Inner Crowns', value:'M15InnerCrowns'},
+ {name:'Nicknames', value:'M15Nickname-2'},
+ {name:'Holo Stamps', value:'M15HoloStamps'},
+ {name:'Dark Power/Toughness', value:'M15DarkPT'},
+ {name:'Colored Borders', value:'M15Borders'},
+ {name:'Color Identity Pips', value:'M15CIPips'},
+ {name:'"The List" Stamp', value:'TheList'},
+
+ {name:'Custom Addons', value:'disabled'},
+ {name:'Brawl Legend Crowns', value:'Brawl'}
])
\ No newline at end of file
diff --git a/js/frames/manaSymbolsWanted.js b/js/frames/manaSymbolsWanted.js
new file mode 100644
index 00000000..631a77bf
--- /dev/null
+++ b/js/frames/manaSymbolsWanted.js
@@ -0,0 +1,25 @@
+//checks to see if it needs to run
+if (!card.manaSymbols.includes('/js/frames/manaSymbolsWanted.js')) {
+ card.manaSymbols.push('/js/frames/manaSymbolsWanted.js');
+}
+if (!mana.get('majpw')) {
+ loadManaSymbols([
+ 'wanted/wanted0',
+ 'wanted/wanted1',
+ 'wanted/wanted2',
+ 'wanted/wanted3',
+ 'wanted/wanted4',
+ 'wanted/wanted5',
+ 'wanted/wanted6',
+ 'wanted/wanted7',
+ 'wanted/wanted8',
+ 'wanted/wanted9',
+ 'wanted/wantedx',
+ 'wanted/wantedw',
+ 'wanted/wantedu',
+ 'wanted/wantedb',
+ 'wanted/wantedr',
+ 'wanted/wantedg',
+ 'wanted/wantedc'
+ ]);
+}
\ No newline at end of file
diff --git a/js/frames/packMarginWanted.js b/js/frames/packMarginWanted.js
new file mode 100644
index 00000000..2f96440a
--- /dev/null
+++ b/js/frames/packMarginWanted.js
@@ -0,0 +1,13 @@
+//Create objects for common properties across available frames
+var bounds = {x:-88.5/2010, y:-79/2817, width:2187/2010, height:2975/2817};
+var ogBounds = {x:0, y:0, width:1, height:1};
+//defines available frames
+availableFrames = [
+ {name:'Wanted Extension', src:'/img/frames/wanted/margin.png', bounds:bounds, ogBounds:ogBounds}
+];
+//disables/enables the "Load Frame Version" button
+document.querySelector('#loadFrameVersion').disabled = false;
+//defines process for loading this version, if applicable
+document.querySelector('#loadFrameVersion').onclick = loadMarginVersion;
+//loads available frames
+loadFramePack();
\ No newline at end of file
diff --git a/js/frames/packWanted.js b/js/frames/packWanted.js
new file mode 100644
index 00000000..c2a447f1
--- /dev/null
+++ b/js/frames/packWanted.js
@@ -0,0 +1,66 @@
+//Create objects for common properties across available frames
+var masks = [{src:'/img/frames/m15/regular/m15MaskPinline.png', name:'Pinline'}, {src:'/img/frames/m15/regular/m15MaskTitle.png', name:'Title'}, {src:'/img/frames/m15/regular/m15MaskType.png', name:'Type'}, {src:'/img/frames/m15/regular/m15MaskRules.png', name:'Rules'}, {src:'/img/frames/m15/regular/m15MaskFrame.png', name:'Frame'}, {src:'/img/frames/m15/regular/m15MaskBorder.png', name:'Border'}];
+var ptBounds = {x:1351/2010, y:2395/2817, width:642/2010, height:271/2817};
+var stampBounds = {x:714/2010, y:2490/2817, width:630/2010, height:182/2817};
+//defines available frames
+availableFrames = [
+ {name:'White Frame', src:'/img/frames/wanted/w.png'},
+ {name:'Blue Frame', src:'/img/frames/wanted/u.png'},
+ {name:'Black Frame', src:'/img/frames/wanted/b.png'},
+ {name:'Red Frame', src:'/img/frames/wanted/r.png'},
+ {name:'Green Frame', src:'/img/frames/wanted/g.png'},
+ {name:'Multicolored Frame', src:'/img/frames/wanted/m.png'},
+ {name:'Artifact Frame', src:'/img/frames/wanted/a.png'},
+
+ {name:'White Power/Toughness', src:'/img/frames/wanted/pt/w.png', bounds: ptBounds},
+ {name:'Blue Power/Toughness', src:'/img/frames/wanted/pt/u.png', bounds: ptBounds},
+ {name:'Black Power/Toughness', src:'/img/frames/wanted/pt/b.png', bounds: ptBounds},
+ {name:'Red Power/Toughness', src:'/img/frames/wanted/pt/r.png', bounds: ptBounds},
+ {name:'Green Power/Toughness', src:'/img/frames/wanted/pt/g.png', bounds: ptBounds},
+ {name:'Multicolored Power/Toughness', src:'/img/frames/wanted/pt/m.png', bounds: ptBounds},
+ {name:'Artifact Power/Toughness', src:'/img/frames/wanted/pt/a.png', bounds: ptBounds},
+
+ {name:'White Holo Stamp', src:'/img/frames/wanted/stamp/w.png', bounds: stampBounds},
+ {name:'Blue Holo Stamp', src:'/img/frames/wanted/stamp/u.png', bounds: stampBounds},
+ {name:'Black Holo Stamp', src:'/img/frames/wanted/stamp/b.png', bounds: stampBounds},
+ {name:'Red Holo Stamp', src:'/img/frames/wanted/stamp/r.png', bounds: stampBounds},
+ {name:'Green Holo Stamp', src:'/img/frames/wanted/stamp/g.png', bounds: stampBounds},
+ {name:'Multicolored Holo Stamp', src:'/img/frames/wanted/stamp/m.png', bounds: stampBounds},
+ {name:'Artifact Holo Stamp', src:'/img/frames/wanted/stamp/a.png', bounds: stampBounds}
+];
+//disables/enables the "Load Frame Version" button
+document.querySelector('#loadFrameVersion').disabled = false;
+//defines process for loading this version, if applicable
+document.querySelector('#loadFrameVersion').onclick = async function() {
+ //resets things so that every frame doesn't have to
+ await resetCardIrregularities();
+ //sets card version
+ card.version = 'wanted';
+
+ card.bottomInfoColor = 'black';
+ card.hideBottomInfoBorder = true;
+ setBottomInfoStyle();
+
+ loadScript('/js/frames/manaSymbolsWanted.js');
+ //art bounds
+ card.artBounds = {x:215/2010, y:652/2817, width:1581/2010, height:1067/2817};
+ autoFitArt();
+ //set symbol bounds
+ //1641,1725
+ card.setSymbolBounds = {x:1860/2010, y:1782/2814, width:0.12, height:0.0410, vertical:'center', horizontal: 'right'};
+ resetSetSymbol();
+ //watermark bounds
+ card.watermarkBounds = {x:0.5, y:0.7762, width:0.75, height:0.2305};
+ resetWatermark();
+ //text
+ loadTextOptions({
+ mana: {name:'Mana Cost', text:'', size:95/2010, manaCost:true, manaPrefix:'wanted', vertical:true, noVerticalCenter:true, manaPlacement: {x:[1813/2010, 1813/2010, 1813/2010, 1813/2010, 1813/2010, 1813/2010], y:[626/2817, 733/2817, 840/2817, 947/2817, 1054/2817, 1161/2817]}},
+ title: {name:'Title', text:'', x:61/2010, y:254/2817, width:1889/2010, height:175/2817, oneLine:true, font:'davisonamericana', size:175/2187, color:'#523c29', allCaps: true, align:'center'},
+ subtitle: {name:'Subtitle', text:'', x:61/2010, y:445/2817, width:1889/2010, height:92/2817, oneLine:true, font:'davisonamericana', size:92/2187, color:'#523c29', allCaps: true, align:'center'},
+ type: {name:'Type', text:'', x:151/2010, y:1760/2817, width:1490/2010, height:70/2817, oneLine:true, font:'officina', size:76/2817, color:'#523c29', allCaps: true},
+ rules: {name:'Rules Text', text:'', x:155/2010, y:1857/2817, width:1703/2010, height:678/2817, size:0.0362, font:'decour', size:81/2187},
+ pt: {name:'Power/Toughness', text:'', x:0.7928, y:2530/2817, width:0.1367, height:0.0372, size:0.0372, font:'arialblack', oneLine:true, align:'center', color:'#523c29'}
+ });
+}
+//loads available frames
+loadFramePack();
\ No newline at end of file