Skip to content

Instantly share code, notes, and snippets.

@0xf0f0f0
Created February 16, 2021 13:07
Show Gist options
  • Select an option

  • Save 0xf0f0f0/b6768474e9ad2ce6ffce75e4d3483096 to your computer and use it in GitHub Desktop.

Select an option

Save 0xf0f0f0/b6768474e9ad2ce6ffce75e4d3483096 to your computer and use it in GitHub Desktop.
editor-runner
/* eslint-disable */
import dat from 'dat.gui';
class Editor {
get bg() {
return 'data:image/png;base64,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';
}
get defaultPallete() {
return {
color1: '#fff000',
color2: '#fff0ff',
color3: '#f000ff',
};
}
get defaultMapProps() {
return {
tileSize: 32,
mapWidth: 10,
mapHeight: 10,
colPadding: 0,
rowPadding: 0,
};
}
constructor(onThreeSceneUpdateCB = () => {}, pallete = defaultPallete, mapProps = {}) {
const props = {
...this.defaultMapProps,
...mapProps,
};
Object.keys(props).forEach((key) => {
this[key] = props[key];
});
this.pallete = pallete;
this.eraserEnabled = false;
this.fillColor = '#ffff00';
this.srcTile = null;
this.mapData = [];
this.canvas = null;
this.ctx = null;
this.pathPoints = [];
this.onThreeSceneUpdateCB = onThreeSceneUpdateCB;
window.addEventListener('click', (e) => this.onClick(e));
}
init() {
const div = this.wrapper = document.createElement('div');
div.style = 'pointer-events: all; top: 0; overflow: scroll; position: fixed; z-index: 90; overflow-x: scroll; width: 320px; height: 640px;';
const canvas = this.canvas = document.createElement('canvas');
canvas.id = 'roadEditor';
canvas.style = `background-position: left top; background-repeat: repeat; background-image: url(${this.bg}); position: absolute; max-width: initial;`;
canvas.width = this.mapWidth * this.tileSize;
canvas.height = this.mapHeight * this.tileSize;
div.appendChild(canvas);
document.body.appendChild(div);
this.ctx = canvas.getContext('2d');
const input = this.input = document.createElement('input');
input.id = 'uploadInput';
input.type = 'file';
input.style = 'visibility:hidden';
document.body.appendChild(input);
input.addEventListener('change', this.uploadMapAndBuild.bind(this));
this.initGUI();
}
initGUI() {
const editor = this;
const editorInterface = {
tileSize: editor.tileSize,
mapWidth: editor.mapWidth,
mapHeight: editor.mapHeight,
rowPadding: editor.rowPadding,
colPadding: editor.colPadding,
eraser: () => editor.enableEraser(true),
buildMap: () => editor.buildMap(),
clearCanvas: () => editor.clearMap(),
downloadMap: () => editor.downloadMap('editor_map.js'),
uploadMap: () => document.getElementById('uploadInput').click(),
};
const gui = this.gui = new dat.GUI({
name: 'Editor GUI',
id: 'editor',
});
this.gui.domElement.id = 'editor_gui';
const mapOptionsFolder = this.mapOptionsFolder = gui.addFolder('Map_Options');
mapOptionsFolder.add(editorInterface, 'tileSize', editorInterface.tileSize, editorInterface.tileSize);
mapOptionsFolder.add(editorInterface, 'mapWidth', 0, 100).onChange((e) => {
editor.mapWidth = Math.round(e);
editor.rebuildCanvas();
});
mapOptionsFolder.add(editorInterface, 'mapHeight', 0, 300).onChange((e) => {
editor.mapHeight = Math.round(e);
editor.rebuildCanvas();
});
mapOptionsFolder.add(editorInterface, 'rowPadding', -300, 300, 0.00001).onChange((e) => {
editor.rowPadding = e;
});
mapOptionsFolder.add(editorInterface, 'colPadding', -300, 300, 0.00001).onChange((e) => {
editor.colPadding = e;
});
const typesOptionsFolder = gui.addFolder('Types');
Object.keys(this.pallete)
.forEach((key) => {
typesOptionsFolder.add({ [key]: () => {} }, key).onChange(() => {
editor.setupFillColor(key);
});
});
const pointsFolder = gui.addFolder('Points');
pointsFolder.add({ addPoint: () => {} }, 'addPoint');
const toolsFolder = gui.addFolder('Tools');
toolsFolder.add(editorInterface, 'eraser').name('Eraser');
toolsFolder.add(editorInterface, 'buildMap').name('Build');
toolsFolder.add(editorInterface, 'clearCanvas').name('Clear Map');
toolsFolder.add(editorInterface, 'downloadMap').name('Dowload');
toolsFolder.add(editorInterface, 'uploadMap').name('Upload');
}
rebuildCanvas() {
const { mapHeight, mapWidth, tileSize, canvas } = this;
canvas.width = mapWidth * tileSize;
canvas.height = mapHeight * tileSize;
}
getTile(e) {
const row = e.layerX / this.tileSize | 0;
const col = e.layerY / this.tileSize | 0;
return { row, col };
}
setTile(row, col) {
const { tileSize, ctx } = this;
if (this.eraserEnabled) {
ctx.clearRect(row * tileSize, col * tileSize, tileSize, tileSize);
} else if (this.fillColor) {
ctx.clearRect(row * tileSize, col * tileSize, tileSize, tileSize);
ctx.beginPath();
ctx.fillStyle = this.fillColor;
ctx.rect(row * tileSize, col * tileSize, tileSize, tileSize);
ctx.fill();
ctx.closePath();
}
}
buildMap(updateThreeScene = true) {
const { mapWidth, mapHeight } = this;
this.mapData = [];
const checkColor = (color) => color[0] === 0 && color[1] === 0 && color[2] === 0
&& color[3] === 0;
const convertRBGtoHEX = (rgba) => `#${((1 << 24) + (parseInt(rgba[0]) << 16) + (parseInt(rgba[1]) << 8) + parseInt(rgba[2])).toString(16).slice(1)}`;
const getTypeByColor = (color) => {
const c = convertRBGtoHEX(color);
const t = Object.keys(this.pallete).find((key) => this.pallete[key] === c);
if (t) return t;
return null;
};
for (let i = 0; i < mapWidth; i++) {
for (let j = 0; j < mapHeight; j++) {
const color = this.getColor(i, j);
if (!checkColor(color.data)) {
this.mapData.push({
type: getTypeByColor(color.data),
i,
j,
});
}
}
}
if (updateThreeScene) {
this.updateThreeScene(this.mapData, {
mapWidth: this.mapWidth,
mapHeight: this.mapHeight,
colsGap: this.colPadding,
rowsGap: this.rowPadding,
});
}
}
uploadMapAndBuild() {
const reader = new FileReader();
reader.onload = (responce) => {
const { result } = responce.target;
const map = JSON.parse(result);
this.drawMap(map);
};
reader.readAsText(this.input.files[this.input.files.length - 1]);
}
drawMap({ mapWidth, mapHeight, rowPadding, colPadding, map }) {
const { mapOptionsFolder } = this;
const mapWC = mapOptionsFolder.__controllers[1];
const mapHC = mapOptionsFolder.__controllers[2];
const rowPC = mapOptionsFolder.__controllers[3];
const colPC = mapOptionsFolder.__controllers[4];
mapWC.setValue(mapWidth);
mapHC.setValue(mapHeight);
rowPC.setValue(rowPadding);
colPC.setValue(colPadding);
map.forEach(({ type, i, j }) => {
this.setupFillColor(type);
this.setTile(i, j);
});
this.buildMap(true);
}
clearMap() {
const r = confirm('Are u sure?');
if (r) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.mapData = [];
}
}
updateThreeScene(map = this.mapData) {
this.onThreeSceneUpdateCB(map, {
rowsGap: this.rowPadding,
colsGap: this.colPadding,
mapWidth: this.mapWidth,
});
}
getColor(i, j) {
const row = i * this.tileSize + this.tileSize / 2;
const col = j * this.tileSize + this.tileSize / 2;
return this.ctx.getImageData(row, col, 1, 1);
}
downloadMap(filename) {
this.buildMap(false);
const m = this.mapData.sort((a, b) => {
if (a.type < b.type) { return -1; }
if (a.type > b.type) { return 1; }
return 0;
});
const map = {
map: m,
mapWidth: this.mapWidth,
mapHeight: this.mapHeight,
rowPadding: this.rowPadding,
colPadding: this.colPadding,
};
const blob = new Blob([JSON.stringify(map)], { type: 'text/csv' });
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
enableEraser(value) {
this.eraserEnabled = value;
if (value) {
this.fillColor = null;
}
}
setupFillColor(color) {
if (this.pallete[color]) {
this.fillColor = this.pallete[color];
this.enableEraser(false);
}
}
onClick(e) {
if (e.target.id === this.canvas.id) {
const { row, col } = this.getTile(e);
this.setTile(row, col);
}
const qs = document.querySelectorAll('#editor_gui > ul')[0];
if (qs.className === 'closed' && !this.isClosed) {
this.wrapper.style.visibility = 'hidden';
this.isClosed = true;
} else if (this.isClosed) {
this.isClosed = false;
this.wrapper.style.visibility = 'visible';
}
}
}
export default Editor;
// init
// this.editor = new Editor((map, props) => {
// this.objectsCreator.createMap({
// map, ...props
// });
// }, {
// hammer: '#fff000',
// gems: '#fff00f',
// mult: '#00ff00',
// trap: '#444000',
// gear: '#945300',
// gear_r: '#300300',
// }, {
// mapWidth: 5,
// mapHeight: 100,
// rowPadding: 3,
// colPadding: .01
// });
// this.editor.init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment