Skip to content

Commit

Permalink
exports
Browse files Browse the repository at this point in the history
  • Loading branch information
skuqre committed Nov 26, 2023
1 parent 59a5b6e commit caa222e
Show file tree
Hide file tree
Showing 8 changed files with 1,262 additions and 29 deletions.
1,071 changes: 1,053 additions & 18 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
},
"dependencies": {
"astro": "^3.3.0",
"buffer": "^6.0.3",
"gif-encoder": "^0.7.2",
"gifencoder": "^2.0.1",
"hex-to-css-filter": "^5.4.0"
}
}
23 changes: 22 additions & 1 deletion src/components/DialogueInput.astro
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,25 @@
</td>
</tr>

<th>
Export <span style="font-size: 13px"><a href="/nikke-font-generator/what-is/export-types">See explanation</a></span>
</th>
<tr>
<td colspan="3" class="wholerow">
<button class="whole-row" id="export-png" title="THE DOWNLOAD BUTTON">Export as PNG...</button>
</td>
</tr>
<tr>
<td colspan="3" class="wholerow">
<button class="whole-row" id="export-gif" title="Download as GIF file that animates like the game.">Export as animated GIF...</button>
</td>
</tr>
<tr>
<td colspan="3" class="wholerow">
<button class="whole-row" id="export-frames" title="Frames will have each letter appear one by one, making a 'typewriting' effect once put together in some software. Use the GIF option instead if you'd like to see what I mean.">Export as individual frames (as ZIP)...</button>
</td>
</tr>

<th>
Other
</th>
Expand Down Expand Up @@ -152,9 +171,11 @@
</tr>
<tr>
<td colspan="3" class="wholerow" id="enable-sizing">
<button class="whole-row" style="margin-bottom: 8px;">Enable Size, Position, and Post-process tools</button>
<button class="whole-row">Enable Size, Position, and Post-process tools</button>
</td>
</tr>

<tr style="margin-bottom: 4px; display: block;"></tr>
</table>
</div>

Expand Down
5 changes: 5 additions & 0 deletions src/layouts/md.astro
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ const {frontmatter} = Astro.props;
}
}

td, th {
text-align: left;
padding: 16px;
}

code {
font-size: 14px;
background-color: rgba(0, 0, 0, 0.4);
Expand Down
14 changes: 14 additions & 0 deletions src/pages/update-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ title: Update Log
---
<br>

## Export `Nov 26, 2023`

- added the ability to download/export in 3 different types
- **Export as PNG...**: downloads the output you currently see as an image file. it's the download button!
- **Export as animated GIF...**: not necessarily animates the character if you uploaded the gif of the character, BUT, animates the dialogue text *(only, currently)*, as if it were typing itself, then it downloads as a gif.
- **Export as individual frames (as ZIP)...**: imagine typing the same stuff one by one and exporting it one by one to create the typing effect. this one does it automatically and wraps it up in a present for you!

the site now uses tools like `Buffer`, `gif-encoder`, and `client-zip` for things like this. hope y'all enjoy.

<br>

---
<br>

## Fixes `Nov 25, 2023`

- fixed newlines not working properly
Expand Down
23 changes: 23 additions & 0 deletions src/pages/what-is/export-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
layout: ../../layouts/md.astro
title: Export Types - Dialogue Generator
---

# Export Types - Dialogue Generator

Ever since the update on `Nov 23, 2023`, 3 export types have been added so that you can make use of the generator more.

Here's what each one does, explained more elaborately by an idiot.

| Export type | What it does |
|-|-|
| **Export as PNG...** | downloads the output you currently see as an image file. it's the download button! |
| **Export as animated GIF...** | not necessarily animates the character if you uploaded the gif of the character, BUT, animates the dialogue text *(only, currently)*, as if it were typing itself, then it downloads as a gif. |
| **Export as individual frames (as ZIP)...** | imagine typing the same stuff one by one and exporting it one by one to create the typing effect. this one does it automatically and wraps it up in a present for you! |

<br>

## Behavior warning
When clicking on one of them, your browser may lag for a bit; this is your device processing the images, so don't panic.

The whole thing you're working with here is made to use YOUR device as no servers are involved in this site.
140 changes: 130 additions & 10 deletions src/scripts/dialogue.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { draw9slice } from "./util.js";
import { draw9slice, dataURLtoFile } from "./util.js";
import { GIFEncoder, quantize, applyPalette } from "https://unpkg.com/gifenc";
import { downloadZip } from "https://cdn.jsdelivr.net/npm/client-zip/index.js"
import { Buffer } from "buffer";

const canvas = document.getElementById("dialogue-canvas");
const ctx = canvas.getContext("2d");
const ctx = canvas.getContext("2d", { willReadFrequently: true });

const myFont = new FontFace('PEB', "url('/nikke-font-generator/fonts/Pretendard-ExtraBold.ttf')");
await myFont.load();
Expand Down Expand Up @@ -360,14 +363,7 @@ document.querySelectorAll('#enable-sizing')[0].addEventListener('click', () => {
document.getElementById('sizing-tool').style['display'] = sizetools ? "block" : "none";
});

document.querySelectorAll('canvas#dialogue-canvas')[0].addEventListener('click', () => {
if (dragbg || dragch || dragcn || dragdt || dragdc || dragcb || dragar) return;
var link = document.createElement('a');
var canvas = document.getElementById('dialogue-canvas')
link.download = 'nikke-dialogue.png';
link.href = canvas.toDataURL()
link.click();
});
document.querySelectorAll('canvas#dialogue-canvas')[0].addEventListener('click', downloadImage);

let dragbg = false;
let dragch = false;
Expand Down Expand Up @@ -569,6 +565,10 @@ document.querySelectorAll('button#bgautofit')[0].addEventListener('click', () =>
document.querySelectorAll('button#bgautofit')[0].innerHTML = "Auto Fit: " + (bgautofit ? "ON" : "OFF");
});

document.querySelectorAll('button#export-png')[0].addEventListener('click', downloadImage);
document.querySelectorAll('button#export-gif')[0].addEventListener('click', animateTypewrite);
document.querySelectorAll('button#export-frames')[0].addEventListener('click', downloadIndividualFrames);

function updateDragButtons() {
document.querySelectorAll('button#dch')[0].innerHTML = dragch ? "ON" : "OFF";
document.querySelectorAll('button#dbg')[0].innerHTML = dragbg ? "ON" : "OFF";
Expand Down Expand Up @@ -865,6 +865,126 @@ function getLines(ctx, text, maxWidth) {
return lines;
}

let exporting = false;
function animateTypewrite() {
if (exporting) return;
exporting = true;

let textc = text2;
let subtextc = subtext2;

let individual = subtextc.split('');

const encoder = new GIFEncoder(canvassize[0], canvassize[1]);

let wasArrowOn = arrowOn;

arrowOn = false;
let curText = "";
individual.splice(0, 0, '');
for (let i = 0; i < individual.length; i++) {
curText += individual[i];

if (individual[i+1] == ' ') {
curText += individual[i+1];
i++;
}
if (individual[i+1] == '\\n') {
curText += individual[i+1];
i++;
}

generateText(textc, curText)

const { data, width, height } = ctx.getImageData(0, 0, canvassize[0], canvassize[1]);
const palette = quantize(data, 256);
const index = applyPalette(data, palette);

encoder.writeFrame(index, width, height, { palette: palette, delay: 75, repeat: -1 });
}

arrowOn = wasArrowOn;
generateText(textc, curText)

const { data, width, height } = ctx.getImageData(0, 0, canvassize[0], canvassize[1]);
const palette = quantize(data, 256);
const index = applyPalette(data, palette);

encoder.writeFrame(index, width, height, { palette: palette, delay: 75, repeat: -1 });

encoder.finish();

let output = encoder.bytes();
let b64 = Buffer.from(output).toString('base64');

var link = document.createElement('a');
link.download = 'nikke-dialogue.gif';
link.href = "data:image/gif;base64," + b64;
link.click();

exporting = false;
}

function downloadIndividualFrames() {
let imgs = []

let textc = text2;
let subtextc = subtext2;

let individual = subtextc.split('');

let wasArrowOn = arrowOn;

arrowOn = false;
let curText = "";
individual.splice(0, 0, '');

for (let i = 0; i < individual.length; i++) {
curText += individual[i];

if (individual[i+1] == ' ') {
curText += individual[i+1];
i++;
}
if (individual[i+1] == '\\n') {
curText += individual[i+1];
i++;
}

generateText(textc, curText)

imgs.push({
name: "nikke-frame" + i + ".png",
input: dataURLtoFile(canvas.toDataURL(), "nikke-frame" + i + ".png")
})
}

arrowOn = wasArrowOn;
generateText(textc, curText)
imgs.push({
name: "nikke-frame" + individual.length + ".png",
input: dataURLtoFile(canvas.toDataURL(), "nikke-frame" + individual.length + ".png")
})

downloadZip(imgs).blob().then((blob) => {
const link = document.createElement("a")
link.href = window.URL.createObjectURL(blob)
link.download = "nikke-dialogue.zip"
link.click()
link.remove()
})
}

function downloadImage() {
if (dragbg || dragch || dragcn || dragdt || dragdc || dragcb || dragar) return;
var link = document.createElement('a');
var canvas = document.getElementById('dialogue-canvas')
link.download = 'nikke-dialogue.png';
link.href = canvas.toDataURL();
link.click();
link.remove();
}

function getLinesForParagraphs(ctx, text, maxWidth) {
let ass = text.split("\n").map(para => getLines(ctx, para, maxWidth))
let res = []
Expand Down
12 changes: 12 additions & 0 deletions src/scripts/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ export function draw9slice(ctx, img, squareslice, x, y, w, h) {
ctx.drawImage(img, sx, sy + sh, sw, img.height - (sy + sh), x + sx, y + sy + ch, cw, img.height - (sy + sh)) // down

ctx.drawImage(img, sx, sy, sw, sh, x + sx, y + sy, cw, ch); // center
}

export function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[arr.length - 1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}

0 comments on commit caa222e

Please sign in to comment.