Skip to content

Instantly share code, notes, and snippets.

@Meshiest
Last active October 25, 2020 06:09
Show Gist options
  • Save Meshiest/deb920d27531a2fba5bff2befed39a32 to your computer and use it in GitHub Desktop.
Save Meshiest/deb920d27531a2fba5bff2befed39a32 to your computer and use it in GitHub Desktop.
Low effort text generator website for brickadia saves - must adhere to the format
<script src="https://cdn.jsdelivr.net/gh/meshiest/brs-js/dist/dist.js"></script>
<script src="https://gist.githack.com/Meshiest/2a253b88a514610772aa03625d41e23a/raw/bricktool.js"></script>
<h1>cake's 3am low effort text generator for brickadia</h1>
<p>
Click <a href="https://github.com/Meshiest/omegga-textgen/tree/master/fonts" target="_blank">here</a> for demo fonts. This is based on the <a href="https://github.com/Meshiest/omegga-textgen" target="_blank">omegga textgen plugin</a>. Read the code for this <a href="https://gist.github.com/Meshiest/deb920d27531a2fba5bff2befed39a32" target="_blank">here</a>.
</p>
<p>
You must select a valid save or you will not be able to generate text. See demo saves for the format
</p>
<table>
<tr>
<td><b>Input font</b></td>
<td>
<input id="fileInput" type="file">
</td>
</tr>
<tr>
<td><b>Color (RGB 0-255)</b></td>
<td>
<input id="colorR" type="number" min="0" max="255" value="0" placeholder="R">
<input id="colorG" type="number" min="0" max="255" value="0" placeholder="G">
<input id="colorB" type="number" min="0" max="255" value="0" placeholder="B">
</td>
</tr>
<tr>
<td><b>Spacing (1 stud = 10)</b></td>
<td>
<input id="spacing" type="number" min="0" value="10">
</td>
</tr>
</table>
<div id="generateArea" style="display: none;">
<h3>Enter text here.</h3>
<p>Single line only, just paste a really long line and split it yourself</p>
<input id="text" type="text">
<button id="generateBtn">generate</button> <br/>
<a id="anchor" download="text.brs">Download</a>
</div>
<pre id="jsonElem"></pre>
<img src="https://i.imgur.com/jmfZMLC.png">
<img src="https://i.imgur.com/e83XIDc.png">
<img src="https://i.imgur.com/PRnfdcM.png">
<script>
function parseFont(data) {
const $_ = $tool(data);
const startMarker = $_.find({asset: 'PB_DefaultBrick', size: [5, 5, 2], material: 'BMC_Glow', color: 0})[0];
if (!startMarker)
throw 'missing start marker (1x1f white (greys 0) glow marker)';
const endMarker = $_.find({asset: 'PB_DefaultBrick', size: [5, 5, 2], material: 'BMC_Glow', color: 7})[0];
if (!endMarker)
throw 'missing end marker (1x1f black (greys 7) glow marker)';
// determine which axis the characters are on
const axis = startMarker.position.findIndex((x, i) => x !== endMarker.position[i]);
// direction the character set is going
const delta = endMarker.position[axis] - startMarker.position[axis];
// get the character plates
const characters = $_.find({asset: 'PB_DefaultBrick', material: 'BMC_Plastic', color: 0})
// sort them based on distance from start marker
.sort((a, b) =>
(a.position[axis] - b.position[axis])*delta
)
// get the bricks above the plate
.map(c => {
const size = c.rotation === 1 || c.rotation == 3 ? [c.size[1], c.size[0], c.size[2]] : c.size;
return {
bricks: $_.shifted($_.above(c), c.position.map(v => -v)),
width: size[axis] * 2,
height: size[1 - axis] * 2,
};
});
console.log('Found', characters.length, 'chars in character set');
if (characters.length !== 95) {
console.warn('Character list: ' + Array.from({length: 95}).map((_, i) => String.fromCharCode(i + 32)).join(''));
throw 'not enough characters built.';
}
// generate brick text from string
return (str='', {shift=[0, 0, 0], color=[0, 0, 0], spacing=10, centered=false}={}) => {
// break into characters, convert to ascii
const chars = str.split('').map(c => c.charCodeAt(0)).filter(c => c >= 32 && c <= 127);
let length = 0;
const output = [];
// if the text is centered, move the text to the left by half of the width
const fullWidth = chars.reduce((a, c) => a + characters[c - 32].width + spacing, -5);
if (centered)
length -= fullWidth/2;
// iterate through characters, adding kerning based on encoded character width
for (const c of chars) {
const { bricks, width } = characters[c - 32];
// determine global offset
let shifted = [...shift];
// add the kerning and existing length
shifted[axis] += (length + width/2) * Math.sign(delta);
// center this character
length += width + spacing;
// add it to the save
output.push(...$_.shifted(bricks, shifted));
}
// set the color
for (const b of output)
b.color = [...color, 255];
// save
return $_.write(output);
};
}
fileInput.addEventListener('change', e => {
const file = e.target.files[0];
if (file) {
// Read the file into a byte array
file.arrayBuffer()
.then(buff => {
const save = BRS.read(buff);
jsonElem.innerText = 'generating';
// Log the save object
console.log(save);
const generator = parseFont(save);
generateArea.style.display = 'block';
generateBtn.onclick = () => {
generator(
text.value, {
color: [colorR.value, colorG.value, colorB.value].map(n => parseInt(n)),
spacing: parseInt(spacing.value),
},
);
}
})
.catch(err => {
generateArea.style.display = 'none';
// Display the error
jsonElem.innerText = 'Error: ' + (err.message || err);
});
}
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment