Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Created November 25, 2022 16:44
Show Gist options
  • Save JettMonstersGoBoom/578bb0cccd8fd9852e4a94d465944437 to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/578bb0cccd8fd9852e4a94d465944437 to your computer and use it in GitHub Desktop.
// TILED plugin
// NES experiment, loading .CHR files and being able to edit the four palettes and update the tileset dynamically.
// 1st play with the new JS api for Tiled
var NESToolState = {
dialogOpen: false,
chosenAction: null,
chosenIndex: null,
image: null,
tileset: null,
bytes: null
}
const PALETTE =
[
'#00aa7f',
'#0055ff',
'#aaaaff',
'#ffffff',
'#ab5236',
'#5f574f',
'#c2c3c7',
'#fff1e8',
'#ff004d',
'#ffa300',
'#ffec27',
'#00e436',
'#29adff',
'#83769c',
'#ff77a8',
'#ffccaa',
];
function CHR_repaint()
{
if (NESToolState.bytes==null) return
if (NESToolState.image==null)
{
tiled.log("new image")
NESToolState.image = new Image(128, 128*4, Image.Format_Indexed8);
}
if (NESToolState.image!=null)
{
}
NESToolState.image.setColorTable(PALETTE);
for (let n = 0; n < 256; n++)
{
let offset = Math.floor(n * 16)
let x = Math.floor(n % 16) * 8
let y = Math.floor(n / 16) * 8
for(let j = 0; j < 8; j++)
{
let a = NESToolState.bytes[offset+j]
let b = NESToolState.bytes[8+offset+j]
for(let i = 0; i < 8; i++)
{
let ix=7-i
let c = (a>>ix) & 1
let d = ((b>>ix) & 1)<<1
NESToolState.image.setPixel(x + i, y + j, c + d)
NESToolState.image.setPixel(x + i, 128+y + j, 4+c + d)
NESToolState.image.setPixel(x + i, 256+y + j, 8+c + d)
NESToolState.image.setPixel(x + i, 384+y + j, 12+c + d)
}
}
}
var map = tiled.activeAsset;
if (NESToolState.tileset==null)
{
tiled.log("new tileset")
NESToolState.tileset = new Tileset('NES p0');
NESToolState.tileset.setTileSize(8, 8);
// Create a tileset from sprite image
map.addTileset(NESToolState.tileset);
}
tiled.log("update tileset")
NESToolState.tileset.transparentColor = PALETTE[0]
NESToolState.tileset.loadFromImage(NESToolState.image);
}
function CHR_read(filename)
{
var map = tiled.activeAsset;
if(!map || !map.isTileMap) {
tiled.alert("Make sure a Map document is active.")
return;
}
let f = new BinaryFile(filename);
if (f==null)
{
tiled.alert("failed.")
return;
}
let cart = f.readAll()
if (NESToolState.bytes!=null)
delete(NESToolState.bytes)
NESToolState.bytes = new Uint8Array(cart)
f.close();
return map;
}
NESToolState.NESDialog = tiled.registerAction("NESToolDialog", function(action) {
if(NESToolState.dialogOpen) return;
NESToolState.dialogOpen = true;
let dialog = new Dialog("NES Tool");
tiled.log("clear stored data")
NESToolState.image = null
NESToolState.tileset = null
NESToolState.bytes = null
tiled.log("colour buttons")
cb0 = [16]
for (let i = 0; i < 16; ++i)
{
cb0[i] = dialog.addColorButton("")
cb0[i].color = PALETTE[i]
cb0[i].colorChanged.connect(function() {
PALETTE[i] = cb0[i].color.toString()
CHR_repaint()
});
if ((i&3)==3)
dialog.addNewRow()
}
tiled.log("file button")
let fname = dialog.addFilePicker(".chr")
fname.fileUrlChanged.connect(function() {
var fileSchemeReplace = tiled.platform == "windows" ? "file:///" : "file://";
var fileUrl = fname.fileUrl.toString().replace(fileSchemeReplace, "");
CHR_read(fileUrl)
CHR_repaint()
CHR_repaint()
});
dialog.addNewRow();
let closeButton = dialog.addButton("Cancel");
closeButton.clicked.connect(function() { dialog.done(Dialog.Rejected);} );
dialog.finished.connect(function() { NESToolState.dialogOpen = false; });
dialog.show();
});
NESToolState.NESDialog.text = "NESToolDialog...";
tiled.extendMenu("Edit", [
{ action: "NESToolDialog", before: "Preferences" },
{separator: true}
]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment