From 230225e7646d4f6f681068916d7e5f13aa8f4576 Mon Sep 17 00:00:00 2001 From: Ewan Howell <48070995+ewanhowell5195@users.noreply.github.com> Date: Fri, 10 May 2024 00:06:55 +0100 Subject: [PATCH] minecraft title generator render controls fixes --- plugins.json | 11 +- .../minecraft_title_generator/changelog.json | 23 + .../minecraft_title_generator.js | 1496 +++++++++-------- 3 files changed, 800 insertions(+), 730 deletions(-) create mode 100644 plugins/minecraft_title_generator/changelog.json diff --git a/plugins.json b/plugins.json index c406b541..753a147b 100644 --- a/plugins.json +++ b/plugins.json @@ -306,11 +306,16 @@ "author": "Ewan Howell", "description": "Create Minecraft-styled title models!", "tags": ["Minecraft", "Title", "Logo"], - "version": "1.4.1", + "version": "1.5.0", "min_version": "4.8.0", "variant": "both", "creation_date": "2023-06-10", - "await_loading": true + "await_loading": true, + "contributes": { + "formats": ["minectaft_title"] + }, + "has_changelog": true, + "website": "https://ewanhowell.com/plugins/minecraft-title-generator/" }, "workspaces": { "title": "Workspaces", @@ -582,7 +587,7 @@ "version": "2.0.0", "min_version": "4.9.4", "variant": "both", - "tags": ["Format: Generic Model", "Mesh", "Tool"] + "tags": ["Format: Generic Model", "Mesh", "Tool"] }, "wasd_controls": { "title": "WASD Controls", diff --git a/plugins/minecraft_title_generator/changelog.json b/plugins/minecraft_title_generator/changelog.json new file mode 100644 index 00000000..9699206a --- /dev/null +++ b/plugins/minecraft_title_generator/changelog.json @@ -0,0 +1,23 @@ +{ + "1.5.0": { + "title": "1.5.0", + "date": "2024-05-10", + "author": "Ewan Howell", + "categories": [ + { + "title": "Changes", + "list": [ + "Made the position camera button a main button with a new icon", + "Render buttons now have tooltips" + ] + }, + { + "title": "Bug Fixes", + "list": [ + "Fixed render controls disappearing for some people", + "Fixed render controls missing in Blockbench v4.10.0" + ] + } + ] + } +} \ No newline at end of file diff --git a/plugins/minecraft_title_generator/minecraft_title_generator.js b/plugins/minecraft_title_generator/minecraft_title_generator.js index 73c69e50..45c8e62b 100644 --- a/plugins/minecraft_title_generator/minecraft_title_generator.js +++ b/plugins/minecraft_title_generator/minecraft_title_generator.js @@ -48,7 +48,7 @@ rootIndex: 0 } let root = connection.roots[0] - let format, action, dialog, mode, panel, styles, preview, debug + let format, action, dialog, mode, styles, preview, debug, controls const id = "minecraft_title_generator" const name = "Minecraft Title Generator" const icon = "text_fields" @@ -96,93 +96,18 @@ author: "Ewan Howell", description, tags: ["Minecraft", "Title", "Logo"], - version: "1.4.1", + version: "1.5.0", min_version: "4.8.0", variant: "both", creation_date: "2023-06-10", await_loading: true, + contributes: { + formats: ["minectaft_title"] + }, + has_changelog: true, + website: "https://ewanhowell.com/plugins/minecraft-title-generator/", async onload() { styles = Blockbench.addCSS(` - body:not(.is_mobile) #work_screen:has(#panel_minecraft_title_render_panel:not(.hidden)) { - grid-template-columns: 0px auto 0 !important; - } - #panel_minecraft_title_render_panel > .panel_handle, #work_screen:has(#panel_minecraft_title_render_panel:not(.hidden)) > .resizer.vertical { - display: none !important; - } - #work_screen:has(#panel_minecraft_title_render_panel:not(.hidden)) > #center { - margin-bottom: calc(4px - var(--toolbar-height)); - } - #panel_minecraft_title_render_panel { - width: 0px !important; - height: 0px !important; - } - #minecraft-title-render-controls-container { - position: absolute; - left: 0; - right: 0; - bottom: 50px; - display: flex; - justify-content: center; - } - #minecraft-title-render-controls { - background-color: var(--color-ui); - z-index: 2; - padding: 10px; - box-shadow: 0 5px 10px #0006; - display: flex; - gap: 10px; - align-items: center; - flex-direction: column; - } - .minecraft-title-render-controls-row { - display: flex; - gap: 20px; - align-items: center; - } - #minecraft-title-render-button { - background-color: var(--color-close); - color: var(--color-light); - padding: 10px 30px 1px; - border-radius: 8px; - cursor: pointer; - transition: filter .15s; - } - #minecraft-title-render-button:hover { - filter: brightness(1.25) hue-rotate(5deg); - } - #minecraft-title-render-button.disabled { - background-color: var(--color-button); - cursor: not-allowed; - } - minecraft-title-render-button.disabled:hover { - filter: initial; - } - .minecraft-title-button { - cursor: pointer; - border-radius: 4px; - } - .minecraft-title-button.selected { - background-color: var(--color-accent); - color: var(--color-accent_text); - } - .minecraft-title-button.selected > svg { - fill: var(--color-accent_text); - } - #resolutions { - display: flex; - background-color: var(--color-button); - padding: 4px; - } - .resolution { - width: 32px; - height: 32px; - } - .resolution > i { - font-size: 32px; - } - .resolution > svg { - fill: var(--color-text); - } .minecraft-title-list { display: flex; max-height: 384px; @@ -403,576 +328,631 @@ Toolbars.outliner.add(action, 0) MenuBar.menus.edit.addAction(action, 4) Interface.Panels.outliner.menu.addAction(action, 0) - panel = new Panel("minecraft_title_render_panel", { - name: "Render Controls", - icon: "photo_camera", - condition: { - modes: ["minecraft_title_render"] - }, - component: { - methods: { - render() { - if (Preview.selected.camera instanceof THREE.OrthographicCamera) return Blockbench.showMessageBox({ - title: "Orthographic not supported", - message: "Orthographic perspectives are not supported for render mode.\n\nIf you wish to render with an orthographic perspective, use the built-in Blockbench screenshot options.", - buttons: ["Disable orthographic perspective", "dialog.close"], - width: 500 - }, async button => { - if (button === 0) Preview.selected.setProjectionMode(false) - }) - if (this.rendering) return - this.rendering = true - const args = this - const dialog = new Dialog({ - id: "minecraft_title_render_result", - title: "Rendering…", - buttons: [], - lines: [``], - component: { - data: { - rendering: true, - image: null, - dimensions: null, - size: null, - canvas: null, - tab: "normal", - resolutionWidth: 1920, - resolutionHeight: 1080, - aspectWidth: 16, - aspectHeight: 9, - lastChanged: "width", - linked: true, - minecraftMode: "1.20", - minecraftModes: { - "1.20": "1.20+ Title Texture", - "1.19": "1.19- Title Texture", - mojang: "Mojang Studios Texture" - }, - backgroundColour: "#78b8ff", - backgroundColour2: "#c7ecff", - backgroundColourEnabled: false, - backgroundColour2Enabled: false, - updating: false, - tabToUpdate: false, - padding: 0 + controls = document.createElement("div") + controls.id = "minecraft-title-render-controls-container" + document.getElementById("center").append(controls) + const controlsStyles = document.createElement("style") + controlsStyles.innerHTML = ` + #minecraft-title-render-controls { + position: absolute; + bottom: 50px; + left: 50%; + transform: translateX(-50%); + background-color: var(--color-ui); + flex-direction: column; + box-shadow: 0 5px 10px #0006; + align-items: center; + gap: 10px; + padding: 10px; + display: none; + z-index: 1; + } + + body[mode="minecraft_title_render"] { + #minecraft-title-render-controls { + display: flex; + } + + #center { + margin-bottom: calc(4px - var(--toolbar-height)); + } + } + + .minecraft-title-render-controls-row { + display: flex; + gap: 20px; + align-items: center; + } + + #minecraft-title-render-buttons { + display: flex; + gap: 10px; + justify-content: center; + + > div { + padding: 5px 30px; + cursor: pointer; + width: initial; + height: initial; + position: relative; + + &::before { + content: ""; + position: absolute; + inset: 0; + background-color: var(--color-error); + border-radius: 8px; + z-index: -1; + transition: filter .15s; + } + + &:first-child::before { + background-color: var(--color-accent); + } + + &:hover::before { + filter: brightness(1.25) hue-rotate(5deg); + } + + &.disabled { + cursor: not-allowed; + + &::before { + background-color: var(--color-button); + filter: initial !important; + } + } + + > i { + color: var(--color-light); + padding: 0; + } + + .tooltip { + transform: translate(calc(11px - 50%), 10px) + } + } + } + + #resolutions { + display: flex; + background-color: var(--color-button); + padding: 4px; + } + + .resolution { + width: 32px; + height: 32px; + cursor: pointer; + border-radius: 4px; + + > i { + font-size: 32px; + max-width: 32px; + } + + > svg { + fill: var(--color-text); + } + + &.selected { + background-color: var(--color-accent); + color: var(--color-accent_text); + + > svg { + fill: var(--color-accent_text); + } + } + } + ` + controls.append(controlsStyles) + const vue = document.createElement("div") + controls.append(vue) + new Vue({ + methods: { + render() { + if (Preview.selected.camera instanceof THREE.OrthographicCamera) return Blockbench.showMessageBox({ + title: "Orthographic not supported", + message: "Orthographic perspectives are not supported for render mode.\n\nIf you wish to render with an orthographic perspective, use the built-in Blockbench screenshot options.", + buttons: ["Disable orthographic perspective", "dialog.close"], + width: 500 + }, async button => { + if (button === 0) Preview.selected.setProjectionMode(false) + }) + if (this.rendering) return + this.rendering = true + const args = this + const dialog = new Dialog({ + id: "minecraft_title_render_result", + title: "Rendering…", + buttons: [], + lines: [``], + component: { + data: { + rendering: true, + image: null, + dimensions: null, + size: null, + canvas: null, + tab: "normal", + resolutionWidth: 1920, + resolutionHeight: 1080, + aspectWidth: 16, + aspectHeight: 9, + lastChanged: "width", + linked: true, + minecraftMode: "1.20", + minecraftModes: { + "1.20": "1.20+ Title Texture", + "1.19": "1.19- Title Texture", + mojang: "Mojang Studios Texture" }, - mounted() { - $(this.$refs.backgroundColour).spectrum(this.colourInput("backgroundColour")), - $(this.$refs.backgroundColour2).spectrum(this.colourInput("backgroundColour2")) + backgroundColour: "#78b8ff", + backgroundColour2: "#c7ecff", + backgroundColourEnabled: false, + backgroundColour2Enabled: false, + updating: false, + tabToUpdate: false, + padding: 0 + }, + mounted() { + $(this.$refs.backgroundColour).spectrum(this.colourInput("backgroundColour")), + $(this.$refs.backgroundColour2).spectrum(this.colourInput("backgroundColour2")) + }, + methods: { + async copy() { + const r = await fetch(this.canvas.toDataURL()) + navigator.clipboard.write([new ClipboardItem({ "image/png": await r.blob() })]) + Blockbench.showQuickMessage("Copied to clipboard") }, - methods: { - async copy() { - const r = await fetch(this.canvas.toDataURL()) - navigator.clipboard.write([new ClipboardItem({ "image/png": await r.blob() })]) - Blockbench.showQuickMessage("Copied to clipboard") - }, - save() { - Blockbench.export({ - extensions: ["png"], - type: tl("data.image"), - savetype: "image", - name: Project.name || "minecraft_title", - content: this.canvas.toDataURL() - }, () => Blockbench.showQuickMessage("Saved title")) - }, - async tabChange(tab) { - this.tab = tab - let canvas, ctx - if (tab === "normal") { - ({ canvas, ctx } = new CanvasFrame(this.image.width, this.image.height)) - ctx.drawImage(this.image, 0, 0) - } else if (tab === "square") { - const max = Math.max(this.image.width, this.image.height); - ({ canvas, ctx } = new CanvasFrame(max, max)) - ctx.drawImage(this.image, Math.floor(max / 2 - this.image.width / 2), Math.floor(max / 2 - this.image.height / 2)) - } else if (tab === "custom") { - ({ canvas, ctx } = new CanvasFrame(this.resolutionWidth, this.resolutionHeight)) - const aspect = this.image.width / this.image.height - const ratio = Math.min(canvas.width / this.image.width, canvas.height / this.image.height) - const w = Math.floor(this.image.width * ratio) - const h = Math.floor(this.image.height * ratio) - ctx.drawImage(this.image, Math.floor(canvas.width / 2 - w / 2), Math.floor(canvas.height / 2 - h / 2), w, h) - } else if (tab === "minecraft") { - const aspect = this.image.width / this.image.height - let w, h - if (this.image.width > 1024 || this.image.height > 1024) { - if (aspect > 1) { - w = 1024 - h = Math.floor(1024 / aspect) - } else { - h = 1024 - w = Math.floor(1024 * aspect) - } + save() { + Blockbench.export({ + extensions: ["png"], + type: tl("data.image"), + savetype: "image", + name: Project.name || "minecraft_title", + content: this.canvas.toDataURL() + }, () => Blockbench.showQuickMessage("Saved title")) + }, + async tabChange(tab) { + this.tab = tab + let canvas, ctx + if (tab === "normal") { + ({ canvas, ctx } = new CanvasFrame(this.image.width, this.image.height)) + ctx.drawImage(this.image, 0, 0) + } else if (tab === "square") { + const max = Math.max(this.image.width, this.image.height); + ({ canvas, ctx } = new CanvasFrame(max, max)) + ctx.drawImage(this.image, Math.floor(max / 2 - this.image.width / 2), Math.floor(max / 2 - this.image.height / 2)) + } else if (tab === "custom") { + ({ canvas, ctx } = new CanvasFrame(this.resolutionWidth, this.resolutionHeight)) + const aspect = this.image.width / this.image.height + const ratio = Math.min(canvas.width / this.image.width, canvas.height / this.image.height) + const w = Math.floor(this.image.width * ratio) + const h = Math.floor(this.image.height * ratio) + ctx.drawImage(this.image, Math.floor(canvas.width / 2 - w / 2), Math.floor(canvas.height / 2 - h / 2), w, h) + } else if (tab === "minecraft") { + const aspect = this.image.width / this.image.height + let w, h + if (this.image.width > 1024 || this.image.height > 1024) { + if (aspect > 1) { + w = 1024 + h = Math.floor(1024 / aspect) } else { - w = this.image.width - h = this.image.height - } - const capped = new CanvasFrame(w, h) - if (this.image.width < 64 || this.image.height < 64) capped.ctx.imageSmoothingEnabled = false - capped.ctx.drawImage(this.image, 0, 0, w, h) - capped.autoCrop() - if (this.minecraftMode === "1.20") { - ({ canvas, ctx } = new CanvasFrame(1024, 256)) - const scaleFactor = Math.min(1024 / capped.width, 176 / capped.height) - const newWidth = capped.width * scaleFactor - const newHeight = capped.height * scaleFactor - const x = (1024 - newWidth) / 2 - const y = (176 - newHeight) / 2 - if (newWidth > capped.width) ctx.imageSmoothingEnabled = false - ctx.drawImage(capped.canvas, x, y, newWidth, newHeight) - } else if (this.minecraftMode === "1.19") { - const base = await loadImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEABAMAAACuXLVVAAAAJ1BMVEUAAAD///8AAAACAQEeHB8jHh5FQkNTUFODfHylnJmon5yvpKDIw79IVPQIAAAAAnRSTlMAAHaTzTgAAAgfSURBVHhe7M6xAAAAAAKwFPKXDaNnI1h6dg8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjBUzaG7buOK4Kn6RDNC0VOQDiweQmolOBWl3JjqVppSZ6iRGtGeiU2ibqq0T2ZhwyZOmaYiKJ1/SSjqpjS1pcZJkiTT3Q/X/3i5BR5kRZjT8H4CHh8Xub997Cyy5AOUIKqQGpSrkaA4q/CYLYLHRaGwTA6zDcos4hEGr1WoWco9wCostq+e0MTW3/NYTa9Lvp85nHnxG9cAYL1qtzzIBAqXUO2KSnlJn7l9w2VxR6vC/hdy354dH1fz54aE6PFJH7+mlOleidqDeiHGkaPlIGfc7r8ennrkvOj1QYSZACQAnnAPiJ9xvcazmYb6l3CvY4ZKyek+4NtoPVGysX98fgODEg2FompkAS0pP2kQLVExnQcs8C1q0ttU76qUAvhpYs55XiZ6gD8AjehBi8zO6OWP7lWpnAeT+FEXR8yqR/3C3p/7nHXEevlLn7HsUDSfulzyrCPpe4CLWd746VaetngE4dfLK+1wpafpj9Bz90dfRa1ycP4o6f8gCkLjtE+HcQy4wWpc4D+rSA8tAptUmlgBUSQQAk65mCcB5uJWiLySbVjwVBSMrAosHCmqSd8AA7WKaTMBMpCjOj3D7NkAysgXbwRNuMa56EgylrlIAiU82gI9RVBISj9bj+UgGbaUBgJ5GBynAUCcW4GkXAGtKCbK+dlY1B0MqxUrC2Ml+D5QUy3E+j/71791uuGRjD7V/l0Zjy4Fc7+AsigyANzmLDpxVqccJUHg4Gz6HBQetShQXsgAwopSWWdfuA16A6BM6+zvsa4nGf+J/xvE/kKXkI4mAmExiXP/RRegSAGwaFtbpRIqGe74qZAHk1lSikySZaI2Oxu4mLtpFbYQ7H7z+ROPuSOsr7xi+0ADABU0QEA8GOe6qnlx4OmHnONEXACjpib7JBtjTn+iG+LJZYrPWZ8+llwjLyJopgGXsdhjrz8dXy0w41II11B8AEMAcf5YFsIhnZsJ8YVTzqakxK9GYAd7cBpB2Q2Acj15pfU1gZvX1DUOymVkDPhMfYBI9Jrk0Dy3Ppn5CfHwTD97E++amSOYa93C4NqCz+J2pH1+qn1wiuVHPApBoO309djZhvRUe5DOd+r54TGXbKbEEYCtvR7UauZuM7PzWk1UgOO0sgPzgGLlLLH2naPuRkVlSkB9dYt0GqK9wa9oRgJT8knwyknlkvAdyqyjZEx+pTLsEy1O8+5vkbhwMDNLYANAnAP1BHNdLgrsj005zd01TBU/j+IcsgL2RnnDVX5DpIS2/Jud5ZFbE6FMAkddHm2YxHmDlrknCetPqvUk3VhsJ+DIAFoc3cUTFKNoqmhim5VcnnEa6XopRIA1WXQDE/MbrDyVhs2eOzwfdsDQN1wIAfL6t3bsBSKMjlyq1xysmnGn5heTBocMltBD1uSqsrokB2maEBzZqlkinANJP9W6Aku7hg0dBrfalqegJ+g1MNxhvjKQYgNNDnQKMDYB1uMvpWtgnQec9bm66Vjt3AyzpifoZtOXampZX2VhehBNEljAdhfkZgETAjEYA2MOM35rxlthFs9jVEQABEKiTuwFkpRAhBHumgxtZCgnXHRLaBwAO0DHmAoCIx7kBwCs7nq08lKKpBJ4zFSyATOruHdFKFEV1gmpfw9qi6Nku1+RG9D2gomjjNZWiRgQ94Q9x1N0OdiO0+Rs9xLnu7T6Pumj3epfb8dLlXqr210ZofHcDUA0iKHgM4zFVcKxapzkFtW9qRiEc2xVuhiYV41jnFnCnDogWWES+ubobIBfwiCGBV1D89SkGfHLyLYAFs6a9J9BBCu2LWbAAgVxlbckIXYQMMO1nGxhiph6rcjg118Vr24XCQsLi+2U4UgAflJlbMoSgsQ0AoNg+QWFU8MUycI/ZKJcrtTJUEYAy+WXQYwU1qjDLTNiQDNgUMH/2lowkjCQo6NQHgDfd1oWwRGSdblAjPgKgIUhSPxWYIt9kQJQzkSlkAuRMHAUF4+Ox6qrZaQDgK6Xwy/DwJyqH+Rhq+xXvr3Ez4GzU/SgCYnc3rIS++SlKMqQFsAHIAIA4egKQE4PKtCkAFw6JZb4vzhdstF3eZnR8wkNE8r5OdB1Xdj8gPVkAk8ZsAGlpsMlqLx12Zr08ZmP8AwO0yUhr/Azj72axq0Wu7WkGsJANcFuy2Xjfau3xhx2bO/lVyNYoivr6gwAUhNsD0RWHRV7aiewVbut+ABpS2gz28fzIJfolwD4DkACMZNsYaP3kRaPhUGEuAKRFgw4SbAPLKKJPAeSu+ZbYDMwHIFfUorM25pgCHBvnNQOcWIChRu439SWRI/vCF/X5AKwgAUpxaEkKTwD0FIAAQCKgvNd6ldcrrZlYzAdgWWvHcbTucG67Leg7Bmg7zpoBuJZdGVsXjvOAfZUatKOv5gPwQI9kjTWppKdZ9piHNnm2/dki5fRL69Q3F4A17hyFUKeVOwBGKQBytGPysz0XANrDMDw20dItgB0GGKYAiDkREuaaEsDVfABm8isVuxXxGo2Q6GGjTrTeEG0jSnwZNBqu/bPy2XxeRDm6t+4BMF+ChbkAQHQvFRbmBADdb/w5AkgaCnRLv3LkssIvAP9vz44FAAAAAIT5W2cQwSLYn2NyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEmBOKRi4Y7csAAAAASUVORK5CYII=") - let preCanvas - if (capped.width / capped.height < 137 / 22) { - preCanvas = new CanvasFrame(Math.floor((capped.height / 22) * 137), capped.height) - preCanvas.ctx.drawImage(capped.canvas, Math.floor((preCanvas.width - capped.width) / 2), 0) - } else if (capped.width / capped.height > 137 / 22) { - preCanvas = new CanvasFrame(capped.width, Math.floor((capped.width / 137) * 22)) - preCanvas.ctx.drawImage(capped.canvas, 0, Math.floor((preCanvas.height - capped.height) / 2)) - } else preCanvas = capped; - ({ canvas, ctx } = new CanvasFrame(Math.floor((preCanvas.width / 137) * 128), Math.floor((preCanvas.width / 137) * 128), true, 1024)) - ctx.imageSmoothingEnabled = false - ctx.drawImage(base, 0, 0, canvas.width, canvas.height) - const width = Math.floor((preCanvas.width / 274) * 155) - ctx.drawImage(preCanvas.canvas, 0, 0, width, preCanvas.height, 0, 0, width, preCanvas.height) - ctx.drawImage(preCanvas.canvas, width, 0, preCanvas.width - width, preCanvas.height, 0, Math.floor(preCanvas.height / 44 * 45), preCanvas.width - width, preCanvas.height) - } else if (this.minecraftMode === "mojang") { - let preCanvas - if (capped.width < capped.height * 4) { - preCanvas = new CanvasFrame(capped.height * 4 + 8, capped.height + 2) - preCanvas.ctx.drawImage(capped.canvas, Math.floor((capped.height * 4 - capped.width) / 2) + 4, 1) - } else if (capped.width > capped.height * 4) { - preCanvas = new CanvasFrame(capped.width + 8, Math.floor(capped.width / 4) + 2) - preCanvas.ctx.drawImage(capped.canvas, 4, Math.floor((preCanvas.height - capped.height) / 2)) - } else { - preCanvas = new CanvasFrame(capped.width + 8, capped.height + 4) - preCanvas.ctx.drawImage(capped.canvas, 4, 1) - } - ({ canvas, ctx } = new CanvasFrame(Math.floor(preCanvas.width / 2), Math.floor(preCanvas.width / 2))) - ctx.drawImage(preCanvas.canvas, 0, 0) - ctx.drawImage(preCanvas.canvas, Math.floor(-preCanvas.width / 2), Math.floor(preCanvas.width / 4)) + h = 1024 + w = Math.floor(1024 * aspect) } + } else { + w = this.image.width + h = this.image.height } - const padding = tab === "minecraft" ? 0 : this.padding - this.canvas.width = canvas.width + padding * 2 - this.canvas.height = canvas.height + padding * 2 - if (this.tab !== "minecraft" && this.backgroundColourEnabled) { - if (this.backgroundColour2Enabled) { - const gradient = this.ctx.createLinearGradient(0, 0, 0, this.canvas.height) - gradient.addColorStop(0, this.backgroundColour) - gradient.addColorStop(1, this.backgroundColour2) - this.ctx.fillStyle = gradient + const capped = new CanvasFrame(w, h) + if (this.image.width < 64 || this.image.height < 64) capped.ctx.imageSmoothingEnabled = false + capped.ctx.drawImage(this.image, 0, 0, w, h) + capped.autoCrop() + if (this.minecraftMode === "1.20") { + ({ canvas, ctx } = new CanvasFrame(1024, 256)) + const scaleFactor = Math.min(1024 / capped.width, 176 / capped.height) + const newWidth = capped.width * scaleFactor + const newHeight = capped.height * scaleFactor + const x = (1024 - newWidth) / 2 + const y = (176 - newHeight) / 2 + if (newWidth > capped.width) ctx.imageSmoothingEnabled = false + ctx.drawImage(capped.canvas, x, y, newWidth, newHeight) + } else if (this.minecraftMode === "1.19") { + const base = await loadImage("data:image/png;base64,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") + let preCanvas + if (capped.width / capped.height < 137 / 22) { + preCanvas = new CanvasFrame(Math.floor((capped.height / 22) * 137), capped.height) + preCanvas.ctx.drawImage(capped.canvas, Math.floor((preCanvas.width - capped.width) / 2), 0) + } else if (capped.width / capped.height > 137 / 22) { + preCanvas = new CanvasFrame(capped.width, Math.floor((capped.width / 137) * 22)) + preCanvas.ctx.drawImage(capped.canvas, 0, Math.floor((preCanvas.height - capped.height) / 2)) + } else preCanvas = capped; + ({ canvas, ctx } = new CanvasFrame(Math.floor((preCanvas.width / 137) * 128), Math.floor((preCanvas.width / 137) * 128), true, 1024)) + ctx.imageSmoothingEnabled = false + ctx.drawImage(base, 0, 0, canvas.width, canvas.height) + const width = Math.floor((preCanvas.width / 274) * 155) + ctx.drawImage(preCanvas.canvas, 0, 0, width, preCanvas.height, 0, 0, width, preCanvas.height) + ctx.drawImage(preCanvas.canvas, width, 0, preCanvas.width - width, preCanvas.height, 0, Math.floor(preCanvas.height / 44 * 45), preCanvas.width - width, preCanvas.height) + } else if (this.minecraftMode === "mojang") { + let preCanvas + if (capped.width < capped.height * 4) { + preCanvas = new CanvasFrame(capped.height * 4 + 8, capped.height + 2) + preCanvas.ctx.drawImage(capped.canvas, Math.floor((capped.height * 4 - capped.width) / 2) + 4, 1) + } else if (capped.width > capped.height * 4) { + preCanvas = new CanvasFrame(capped.width + 8, Math.floor(capped.width / 4) + 2) + preCanvas.ctx.drawImage(capped.canvas, 4, Math.floor((preCanvas.height - capped.height) / 2)) } else { - this.ctx.fillStyle = this.backgroundColour + preCanvas = new CanvasFrame(capped.width + 8, capped.height + 4) + preCanvas.ctx.drawImage(capped.canvas, 4, 1) } - this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height) + ({ canvas, ctx } = new CanvasFrame(Math.floor(preCanvas.width / 2), Math.floor(preCanvas.width / 2))) + ctx.drawImage(preCanvas.canvas, 0, 0) + ctx.drawImage(preCanvas.canvas, Math.floor(-preCanvas.width / 2), Math.floor(preCanvas.width / 4)) } - this.ctx.drawImage(canvas, padding, padding) - const size = this.canvas.toDataURL().slice(22).length * 0.75 - this.dimensions = `${this.canvas.width} x ${this.canvas.height}` - this.size = `${size > 1048576 ? `${Math.roundTo(size / 1048576, 2)} MB` : `${Math.round(size / 1024)} KB`}` - }, - changeResolution(changed) { - this.lastChanged = changed - if (this.linked) { - if (changed === "width") { - this.resolutionHeight = Math.max(1, Math.floor((this.resolutionWidth * this.aspectHeight) / this.aspectWidth)) - } else { - this.resolutionWidth = Math.max(1, Math.floor((this.resolutionHeight * this.aspectWidth) / this.aspectHeight)) - } - if (this.resolutionWidth > 4096 || this.resolutionHeight > 4096) { - const aspect = this.resolutionWidth / this.resolutionHeight - if (aspect > 1) { - this.resolutionWidth = 4096 - this.resolutionHeight = Math.floor(4096 / aspect) - } else { - this.resolutionHeight = 4096 - this.resolutionWidth = Math.floor(4096 * aspect) - } - } + } + const padding = tab === "minecraft" ? 0 : this.padding + this.canvas.width = canvas.width + padding * 2 + this.canvas.height = canvas.height + padding * 2 + if (this.tab !== "minecraft" && this.backgroundColourEnabled) { + if (this.backgroundColour2Enabled) { + const gradient = this.ctx.createLinearGradient(0, 0, 0, this.canvas.height) + gradient.addColorStop(0, this.backgroundColour) + gradient.addColorStop(1, this.backgroundColour2) + this.ctx.fillStyle = gradient } else { - this.resolutionWidth = Math.max(1, parseInt(this.resolutionWidth)) - this.resolutionHeight = Math.max(1, parseInt(this.resolutionHeight)) - const [aW, aH] = getAspectRatio(this.resolutionWidth, this.resolutionHeight) - this.aspectWidth = aW - this.aspectHeight = aH + this.ctx.fillStyle = this.backgroundColour } - this.update("custom") - }, - changeAspect() { - this.aspectWidth = Math.max(1, parseInt(this.aspectWidth)) - this.aspectHeight = Math.max(1, parseInt(this.aspectHeight)) - const [w, h] = getFromAspect(this.aspectWidth, this.aspectHeight, this.resolutionWidth, this.resolutionHeight, this.lastChanged === "width") - this.resolutionWidth = w - this.resolutionHeight = h - this.update("custom") - }, - colourInput: v => ({ - preferredFormat: "hex", - color: dialog.component.data[v], - showAlpha: false, - showInput: true, - move: c => dialog.content_vue.updateColour(v, c), - change: c => dialog.content_vue.updateColour(v, c), - hide: c => dialog.content_vue.updateColour(v, c) - }), - updateColour(v, c) { - this[v] = c.toHexString() - this.update(this.tab) - }, - async update(tab) { - if (this.updating) { - this.tabToUpdate = tab - return + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height) + } + this.ctx.drawImage(canvas, padding, padding) + const size = this.canvas.toDataURL().slice(22).length * 0.75 + this.dimensions = `${this.canvas.width} x ${this.canvas.height}` + this.size = `${size > 1048576 ? `${Math.roundTo(size / 1048576, 2)} MB` : `${Math.round(size / 1024)} KB`}` + }, + changeResolution(changed) { + this.lastChanged = changed + if (this.linked) { + if (changed === "width") { + this.resolutionHeight = Math.max(1, Math.floor((this.resolutionWidth * this.aspectHeight) / this.aspectWidth)) + } else { + this.resolutionWidth = Math.max(1, Math.floor((this.resolutionHeight * this.aspectWidth) / this.aspectHeight)) } - this.updating = true - await this.tabChange(tab) - this.updating = false - if (this.tabToUpdate) { - this.update(this.tabToUpdate) - this.tabToUpdate = false + if (this.resolutionWidth > 4096 || this.resolutionHeight > 4096) { + const aspect = this.resolutionWidth / this.resolutionHeight + if (aspect > 1) { + this.resolutionWidth = 4096 + this.resolutionHeight = Math.floor(4096 / aspect) + } else { + this.resolutionHeight = 4096 + this.resolutionWidth = Math.floor(4096 * aspect) + } } + } else { + this.resolutionWidth = Math.max(1, parseInt(this.resolutionWidth)) + this.resolutionHeight = Math.max(1, parseInt(this.resolutionHeight)) + const [aW, aH] = getAspectRatio(this.resolutionWidth, this.resolutionHeight) + this.aspectWidth = aW + this.aspectHeight = aH } + this.update("custom") }, - template: ` -