pixel editor palette selector, tilemap viewer

This commit is contained in:
Steven Hugg 2019-03-22 12:32:37 -04:00
parent 4469dd7e36
commit f55da302ed
16 changed files with 326 additions and 104 deletions

View File

@ -457,6 +457,9 @@ div.asset_file {
margin:0.5em;
padding:1em;
}
div.asset_file select {
color: #000;
}
div.asset_file_header {
font-weight: bold;
color: white;

View File

@ -100,6 +100,7 @@ TODO:
- 'src is undefined' when committing old image editor
- editor: select palette for chr, select charmap for map (dependencies?)
- global undo/redo at checkpoints (when rom changes)
- asset editor still refreshes twice
WEB WORKER FORMAT

View File

@ -6,11 +6,13 @@
// link the pattern table into CHR ROM
//#link "chr_generic.s"
const char PALETTE[16] = { /*{pal:"nes",layout:"nes"}*/
0x03,
0x11,0x30,0x27, 0,
0x1c,0x20,0x2c, 0,
0x00,0x10,0x20, 0,
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[16] = {
0x03, // background color
0x25,0x30,0x27,0x00, // ladders and pickups
0x1C,0x20,0x2C,0x00, // floor blocks
0x00,0x10,0x20,0x00,
0x06,0x16,0x26
};

View File

@ -726,17 +726,18 @@ void play_scene() {
rescue_scene();
}
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // ladders and pickups
0x1c,0x20,0x2c, 0, // floor blocks
0x00,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x11,0x30,0x27, 0x0, // ladders and pickups
0x1c,0x20,0x2c, 0x0, // floor blocks
0x00,0x10,0x20, 0x0,
0x06,0x16,0x26, 0x0,
0x16,0x35,0x24, 0, // enemy sprites
0x00,0x37,0x25, 0, // rescue person
0x0d,0x2d,0x3a, 0,
0x16,0x35,0x24, 0x0, // enemy sprites
0x00,0x37,0x25, 0x0, // rescue person
0x0d,0x2d,0x3a, 0x0,
0x0d,0x27,0x2a // player sprites
};

View File

@ -1,13 +1,13 @@
.export _climbr_title_pal
.export _climbr_title_rle
_climbr_title_pal:
;;{pal:"nes",layout:"nes"};;
_climbr_title_pal:
.byte $0F,$11,$25,$35,$0F,$01,$21,$30
.byte $0F,$06,$1C,$3C,$0F,$11,$28,$38
;;
_climbr_title_rle:
;;{w:32,h:30,bpp:8,comp:"rletag",map:"nesnt"};;
_climbr_title_rle:
.byte $01,$00,$01,$10,$80,$01,$02,$00
.byte $80,$00,$80,$00,$01,$1f,$80,$80
.byte $00,$01,$07,$41,$4e,$00,$38,$42

View File

@ -58,18 +58,19 @@ const unsigned char* const playerRunSeq[16] = {
playerRRun1, playerRRun2,
};
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // ladders and pickups
0x1c,0x20,0x2c, 0, // floor blocks
0x00,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x25,0x30,0x27,0x00, // ladders and pickups
0x1C,0x20,0x2C,0x00, // floor blocks
0x00,0x10,0x20,0x00,
0x06,0x16,0x26,0x00,
0x16,0x35,0x24, 0, // enemy sprites
0x00,0x37,0x25, 0, // rescue person
0x0d,0x2d,0x3a, 0,
0x0d,0x27,0x2a // player sprites
0x16,0x35,0x24,0x00, // enemy sprites
0x00,0x37,0x25,0x00, // rescue person
0x0D,0x2D,0x1A,0x00,
0x0D,0x27,0x2A // player sprites
};
// setup PPU and tables

View File

@ -102,18 +102,19 @@ void scroll_demo() {
}
}
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // background 0
0x1c,0x20,0x2c, 0, // background 1
0x00,0x10,0x20, 0, // background 2
0x06,0x16,0x26, 0, // background 3
0x25,0x30,0x27,0x00, // ladders and pickups
0x1C,0x20,0x2C,0x00, // floor blocks
0x00,0x10,0x20,0x00,
0x06,0x16,0x26,0x00,
0x16,0x35,0x24, 0, // sprite 0
0x00,0x37,0x25, 0, // sprite 1
0x0d,0x2d,0x3a, 0, // sprite 2
0x0d,0x27,0x2a // sprite 3
0x16,0x35,0x24,0x00, // enemy sprites
0x00,0x37,0x25,0x00, // rescue person
0x0D,0x2D,0x1A,0x00,
0x0D,0x27,0x2A // player sprites
};
// main function, run after console reset

View File

@ -58,18 +58,19 @@ const unsigned char* const playerRunSeq[16] = {
playerRRun1, playerRRun2,
};
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // ladders and pickups
0x1c,0x20,0x2c, 0, // floor blocks
0x00,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x25,0x30,0x27,0x00, // ladders and pickups
0x1C,0x20,0x2C,0x00, // floor blocks
0x00,0x10,0x20,0x00,
0x06,0x16,0x26,0x00,
0x16,0x35,0x24, 0, // enemy sprites
0x00,0x37,0x25, 0, // rescue person
0x0d,0x2d,0x3a, 0,
0x0d,0x27,0x2a // player sprites
0x16,0x35,0x24,0x00, // enemy sprites
0x00,0x37,0x25,0x00, // rescue person
0x0D,0x2D,0x1A,0x00,
0x0D,0x27,0x2A // player sprites
};
// setup PPU and tables

View File

@ -58,7 +58,8 @@ const unsigned char* const playerRunSeq[16] = {
playerRRun1, playerRRun2,
};
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x25,0x30,0x27,0x00, // ladders and pickups

View File

@ -58,18 +58,19 @@ const unsigned char* const playerRunSeq[16] = {
playerRRun1, playerRRun2,
};
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // ladders and pickups
0x1c,0x20,0x2c, 0, // floor blocks
0x00,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x25,0x30,0x27,0x00, // ladders and pickups
0x1C,0x20,0x2C,0x00, // floor blocks
0x00,0x10,0x20,0x00,
0x06,0x16,0x26,0x00,
0x16,0x35,0x24, 0, // enemy sprites
0x00,0x37,0x25, 0, // rescue person
0x0d,0x2d,0x3a, 0,
0x0d,0x27,0x2a // player sprites
0x16,0x35,0x24,0x00, // enemy sprites
0x00,0x37,0x25,0x00, // rescue person
0x0D,0x2D,0x1A,0x00,
0x0D,0x27,0x2A // player sprites
};
// setup PPU and tables

View File

@ -25,17 +25,18 @@
//#define DEBUG_FRAMERATE
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x0f,
0x11,0x24,0x3c, 0,
0x01,0x15,0x25, 0,
0x01,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x11,0x24,0x3c, 0x0,
0x01,0x15,0x25, 0x0,
0x01,0x10,0x20, 0x0,
0x06,0x16,0x26, 0x0,
0x11,0x24,0x3c, 0,
0x01,0x15,0x25, 0,
0x31,0x35,0x3c, 0,
0x11,0x24,0x3c, 0x0,
0x01,0x15,0x25, 0x0,
0x31,0x35,0x3c, 0x0,
0x01,0x17,0x30
};
@ -47,7 +48,8 @@ const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
#define COLOR_SCORE 2
#define COLOR_EXPLOSION 3
const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
const char TILESET[128*8*2] = {
// font (0..63)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7C,0x7C,0x7C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0x6C,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xFE,0xD0,0xFE,0x16,0xFE,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xDC,0x38,0x76,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x7C,0xEC,0xEE,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xFE,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1E,0x3C,0x78,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7C,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x78,0x38,0x38,0x38,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x0E,0x7C,0xE0,0xEE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0E,0x3C,0x0E,0x0E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0xEE,0xEE,0xFE,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xE0,0xFC,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0xFC,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xEE,0x1C,0x1C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x7C,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0x7E,0x0E,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x38,0x70,0x70,0x38,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x1C,0x1C,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x1C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

View File

@ -250,8 +250,8 @@ AE(1,0,1,0),AE(0,0,0,0),AE(0,0,0,0),AE(0,0,0,0), AE(0,0,0,0),AE(0,0,0,0),AE(0,0,
AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1), AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1),AE(1,1,1,1),
};
// this is palette data
const unsigned char Palette_Table[16]={ /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const unsigned char Palette_Table[16]={
0x02,
0x31,0x31,0x31,0x00,
0x34,0x34,0x34,0x00,

View File

@ -11,18 +11,18 @@
// link the pattern table into CHR ROM
//#link "chr_generic.s"
const char PALETTE[32] = { /*{pal:"nes",layout:"nes"}*/
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // background color
0x11,0x30,0x27, 0, // ladders and pickups
0x1c,0x20,0x2c, 0, // floor blocks
0x00,0x10,0x20, 0,
0x06,0x16,0x26, 0,
0x11,0x30,0x27,0x0, // ladders and pickups
0x1c,0x20,0x2c,0x0, // floor blocks
0x00,0x10,0x20,0x0,
0x06,0x16,0x26,0x0,
0x16,0x35,0x24, 0, // enemy sprites
0x00,0x37,0x25, 0, // rescue person
0x0d,0x2d,0x3a, 0,
0x16,0x35,0x24,0x0, // enemy sprites
0x00,0x37,0x25,0x0, // rescue person
0x0d,0x2d,0x3a,0x0,
0x0d,0x27,0x2a // player sprites
};

View File

@ -5,8 +5,24 @@ import { ProjectWindows } from "../windows";
export type UintArray = number[] | Uint8Array | Uint16Array | Uint32Array; //{[i:number]:number};
// TODO: separate view/controller
export interface EditorContext {
setCurrentEditor(div : JQuery, editing : JQuery) : void;
setCurrentEditor(div:JQuery, editing:JQuery) : void;
getPalettes(matchlen : number) : SelectablePalette[];
getTilemaps(matchlen : number) : SelectableTilemap[];
}
export type SelectablePalette = {
node:PixNode
name:string
palette:Uint32Array
}
export type SelectableTilemap = {
node:PixNode
name:string
images:Uint8Array[]
rgbimgs:Uint32Array[] // TODO: different palettes?
}
export type PixelEditorImageFormat = {
@ -599,7 +615,7 @@ function pixelEditorKeypress(e) {
}
}
// TODO: reversed?
// TODO: illegal colors?
var PREDEF_PALETTES = {
'nes':[
0x525252, 0xB40000, 0xA00000, 0xB1003D, 0x740069, 0x00005B, 0x00005F, 0x001840, 0x002F10, 0x084A08, 0x006700, 0x124200, 0x6D2800, 0x000000, 0x000000, 0x000000,
@ -665,6 +681,7 @@ export abstract class PixNode {
abstract class CodeProjectDataNode extends PixNode {
project : ProjectWindows;
fileid : string;
label : string;
words : UintArray;
}
@ -674,6 +691,7 @@ export class FileDataNode extends CodeProjectDataNode {
super();
this.project = project;
this.fileid = fileid;
this.label = fileid;
this.words = data;
}
updateLeft() {
@ -690,10 +708,11 @@ export class TextDataNode extends CodeProjectDataNode {
start : number;
end : number;
constructor(project:ProjectWindows, fileid:string, text:string, start:number, end:number) {
constructor(project:ProjectWindows, fileid:string, label:string, text:string, start:number, end:number) {
super();
this.project = project;
this.fileid = fileid;
this.label = label;
this.text = text;
this.start = start;
this.end = end;
@ -762,6 +781,18 @@ export class Palettizer extends PixNode {
rgbimgs : Uint32Array[];
palette : Uint32Array;
ncolors : number;
context : EditorContext;
options : SelectablePalette[];
selindex : number = 0;
// TODO: control to select palette for bitmaps
constructor(context:EditorContext, fmt:PixelEditorImageFormat) {
super();
this.context = context;
this.ncolors = 1 << ((fmt.bpp||1) * (fmt.np||1));
}
updateLeft() {
this.rgbimgs = this.right.rgbimgs;
var pal = new RGBAPalette(this.palette);
@ -774,6 +805,7 @@ export class Palettizer extends PixNode {
});
}
updateRight() {
this.updatePalette();
this.images = this.left.images;
var mask = this.palette.length - 1; // must be power of 2
// for each image, map bytes to RGB colors
@ -785,6 +817,20 @@ export class Palettizer extends PixNode {
return out;
});
}
updatePalette() {
if (this.context != null) {
this.options = this.context.getPalettes(this.ncolors);
if (this.options && this.options.length > 0) {
this.palette = this.options[this.selindex].palette;
}
}
if (this.palette == null) {
if (this.ncolors <= 2)
this.palette = new Uint32Array([0xff000000, 0xffffffff]);
else
this.palette = new Uint32Array([0xff000000, 0xffff00ff, 0xffffff00, 0xffffffff]); // TODO: more palettes
}
}
}
function dedupPalette(cols : UintArray) : Uint32Array {
@ -830,6 +876,83 @@ export class PaletteFormatToRGB extends PixNode {
}
}
export class NESNametableConverter extends PixNode {
palette : Uint32Array;
tilemap : Uint8Array[]; // tilemap images
rgbimgs : Uint32Array[]; // output (1 image)
width : number;
height : number;
cols : number;
rows : number;
baseofs : number;
context : EditorContext;
paloptions : SelectablePalette[];
tileoptions : SelectableTilemap[];
palindex : number = 0;
tileindex : number = 0;
constructor(context:EditorContext) {
super();
this.context = context;
}
updateLeft() {
// TODO
}
updateRight() {
this.words = this.left.words;
this.updatePalette();
this.cols = 32;
this.rows = 30;
this.width = this.cols * 8;
this.height = this.rows * 8;
this.baseofs = 0;
var idata = new Uint32Array(this.width * this.height);
this.rgbimgs = [idata];
var a = 0;
var attraddr;
for (var row=0; row<this.rows; row++) {
for (var col=0; col<this.cols; col++) {
var name = this.words[this.baseofs + a];
var t = this.tilemap[name];
attraddr = (a & 0x2c00) | 0x3c0 | (a & 0x0C00) | ((a >> 4) & 0x38) | ((a >> 2) & 0x07);
var attr = this.words[attraddr];
var tag = name ^ (attr<<9) ^ 0x80000000;
var i = row*this.cols*8*8 + col*8;
var j = 0;
var attrshift = (col&2) + ((a&0x40)>>4);
var coloradd = ((attr >> attrshift) & 3) << 2;
for (var y=0; y<8; y++) {
for (var x=0; x<8; x++) {
var color = t[j++];
if (color) color += coloradd;
var rgb = this.palette[color];
idata[i++] = rgb | 0xff000000;
}
i += this.cols*8-8;
}
a++;
}
}
// TODO
}
updatePalette() {
if (this.context != null) {
this.paloptions = this.context.getPalettes(16);
if (this.paloptions && this.paloptions.length > 0) {
this.palette = this.paloptions[this.palindex].palette;
}
this.tileoptions = this.context.getTilemaps(256);
if (this.tileoptions && this.tileoptions.length > 0) {
this.tilemap = this.tileoptions[this.tileindex].images;
}
}
}
}
///// UI CONTROLS
export class Viewer { // TODO: make PixNode
width : number;
@ -933,6 +1056,7 @@ export class CharmapEditor extends PixNode {
var adual = newDiv(this.parentdiv.empty(), "asset_dual"); // contains grid and editor
var agrid = newDiv(adual);
var aeditor = newDiv(adual, "asset_editor").hide(); // contains editor, when selected
// add image chooser grid
var chooser = new ImageChooser();
chooser.rgbimgs = this.rgbimgs;
chooser.width = this.fmt.w || 1;
@ -946,6 +1070,23 @@ export class CharmapEditor extends PixNode {
aeditor.empty().append(editview.canvas);
this.context.setCurrentEditor(aeditor, $(viewer.canvas));
});
// add palette selector
// TODO: only view when editing?
var palizer = this.left;
if (palizer instanceof Palettizer && palizer.options.length > 1) {
var palselect = $(document.createElement('select'));
palizer.options.forEach((palopt, i) => {
// TODO: full identifier
var sel = $(document.createElement('option')).text(palopt.name).val(i).appendTo(palselect);
if (i == (palizer as Palettizer).selindex)
sel.attr('selected','selected');
});
palselect.appendTo(agrid).change((e) => {
var index = $(e.target).val() as number;
(palizer as Palettizer).selindex = index;
palizer.refreshRight();
});
}
}
}

View File

@ -967,6 +967,7 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
cureditordiv : JQuery;
cureditelem : JQuery;
rootnodes : pixed.PixNode[];
deferrednodes : pixed.PixNode[];
createDiv(parent : HTMLElement) {
this.maindiv = newDiv(parent, "vertical-scroll");
@ -975,10 +976,68 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
clearAssets() {
this.rootnodes = [];
this.deferrednodes = [];
}
registerAsset(type:string, node:pixed.PixNode) {
registerAsset(type:string, node:pixed.PixNode, deferred:boolean) {
this.rootnodes.push(node);
if (deferred) {
this.deferrednodes.push(node);
} else {
node.refreshRight();
}
}
getPalettes(matchlen : number) : pixed.SelectablePalette[] {
var result = [];
this.rootnodes.forEach((node) => {
while (node != null) {
if (node instanceof pixed.PaletteFormatToRGB) {
// TODO: move to node class?
var palette = node.palette;
// match full palette length?
if (matchlen == palette.length) {
result.push({node:node, name:"Palette", palette:palette});
}
// look at palette slices
if (node.layout) {
node.layout.forEach(([name, start, len]) => {
if (start < palette.length) {
if (len == matchlen) {
var rgbs = palette.slice(start, start+len);
result.push({node:node, name:name, palette:rgbs});
} else if (len+1 == matchlen) {
var rgbs = new Uint32Array(matchlen);
rgbs[0] = palette[0];
rgbs.set(palette.slice(start, start+len), 1);
result.push({node:node, name:name, palette:rgbs});
}
}
});
}
break;
}
node = node.right;
}
});
return result;
}
getTilemaps(matchlen : number) : pixed.SelectableTilemap[] {
var result = [];
this.rootnodes.forEach((node) => {
while (node != null) {
if (node instanceof pixed.Palettizer) {
// TODO: move to node class?
var rgbimgs = node.rgbimgs;
if (rgbimgs.length >= matchlen) {
result.push({node:node, name:"Tilemap", images:node.images, rgbimgs:rgbimgs}); // TODO
}
}
node = node.right;
}
});
return result;
}
setCurrentEditor(div : JQuery, editing : JQuery) {
@ -1087,11 +1146,7 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
// TODO: rotate node?
firstnode.addRight(mapper);
// pixels -> RGBA
var palizer = new pixed.Palettizer();
if (fmt.bpp*(fmt.np|1) == 1)
palizer.palette = new Uint32Array([0xff000000, 0xffffffff]);
else
palizer.palette = new Uint32Array([0x00000000, 0xffff00ff, 0xffffff00, 0xffffffff]); // TODO
var palizer = new pixed.Palettizer(this, fmt);
mapper.addRight(palizer);
// add view objects
palizer.addRight(new pixed.CharmapEditor(this, newDiv(parentdiv), fmt));
@ -1127,29 +1182,41 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
let node = new pixed.FileDataNode(projectWindows, fileid, data);
const neschrfmt = {w:8,h:8,bpp:1,count:(data.length>>4),brev:true,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}; // TODO
this.addPixelEditor(filediv, node, neschrfmt);
this.registerAsset("charmap", node);
this.registerAsset("charmap", node, true);
} else if (typeof data === 'string') {
let textfrags = this.scanFileTextForAssets(fileid, data);
for (let frag of textfrags) {
let node : pixed.PixNode = new pixed.TextDataNode(projectWindows, fileid, data, frag.start, frag.end);
let first = node;
if (frag.fmt.comp == 'rletag') {
node = node.addRight(new pixed.Compressor());
}
// is this a bitmap?
if (frag.fmt && frag.fmt.w > 0 && frag.fmt.h > 0) {
this.addPixelEditor(filediv, node, frag.fmt);
this.registerAsset("charmap", first);
nassets++;
}
// is this a palette?
else if (frag.fmt && frag.fmt.pal) {
this.addPaletteEditor(filediv, node, frag.fmt);
this.registerAsset("palette", first);
nassets++;
}
else {
// TODO: other kinds of resources?
if (frag.fmt) {
let label = fileid; // TODO: label
let node : pixed.PixNode = new pixed.TextDataNode(projectWindows, fileid, label, data, frag.start, frag.end);
let first = node;
// rle-compressed?
if (frag.fmt.comp == 'rletag') {
node = node.addRight(new pixed.Compressor());
}
// is this a nes nametable?
if (frag.fmt.map == 'nesnt') {
node = node.addRight(new pixed.NESNametableConverter(this)); // TODO?
const fmt = {w:8*32,h:8*30,count:1}; // TODO
node = node.addRight(new pixed.CharmapEditor(this, newDiv(filediv), fmt));
this.registerAsset("nametable", first, true);
nassets++;
}
// is this a bitmap?
else if (frag.fmt.w > 0 && frag.fmt.h > 0) {
this.addPixelEditor(filediv, node, frag.fmt);
this.registerAsset("charmap", first, true);
nassets++;
}
// is this a palette?
else if (frag.fmt.pal) {
this.addPaletteEditor(filediv, node, frag.fmt);
this.registerAsset("palette", first, false);
nassets++;
}
else {
// TODO: other kinds of resources?
}
}
}
}
@ -1177,8 +1244,8 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
filediv.text(e+""); // TODO: error msg?
}
});
// refresh all assets
this.rootnodes.forEach((node) => { node.refreshRight(); });
this.deferrednodes.forEach((node) => { node.refreshRight(); });
this.deferrednodes = [];
}
// TODO: scroll editors into view

2
tss

@ -1 +1 @@
Subproject commit 5b5ee67fc06956bc7dce51726e98812d2d897eaa
Subproject commit 61a1691a1de05dca3b694bf603db49ffbaf572cf