mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-09 02:31:21 +00:00
refactored pixel compositor for metasprites
This commit is contained in:
parent
f55da302ed
commit
f49ce33f97
@ -783,8 +783,8 @@ export class Palettizer extends PixNode {
|
|||||||
|
|
||||||
ncolors : number;
|
ncolors : number;
|
||||||
context : EditorContext;
|
context : EditorContext;
|
||||||
options : SelectablePalette[];
|
paloptions : SelectablePalette[];
|
||||||
selindex : number = 0;
|
palindex : number = 0;
|
||||||
|
|
||||||
// TODO: control to select palette for bitmaps
|
// TODO: control to select palette for bitmaps
|
||||||
|
|
||||||
@ -805,7 +805,7 @@ export class Palettizer extends PixNode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateRight() {
|
updateRight() {
|
||||||
this.updatePalette();
|
this.updateRefs();
|
||||||
this.images = this.left.images;
|
this.images = this.left.images;
|
||||||
var mask = this.palette.length - 1; // must be power of 2
|
var mask = this.palette.length - 1; // must be power of 2
|
||||||
// for each image, map bytes to RGB colors
|
// for each image, map bytes to RGB colors
|
||||||
@ -817,11 +817,11 @@ export class Palettizer extends PixNode {
|
|||||||
return out;
|
return out;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updatePalette() {
|
updateRefs() {
|
||||||
if (this.context != null) {
|
if (this.context != null) {
|
||||||
this.options = this.context.getPalettes(this.ncolors);
|
this.paloptions = this.context.getPalettes(this.ncolors);
|
||||||
if (this.options && this.options.length > 0) {
|
if (this.paloptions && this.paloptions.length > 0) {
|
||||||
this.palette = this.options[this.selindex].palette;
|
this.palette = this.paloptions[this.palindex].palette;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.palette == null) {
|
if (this.palette == null) {
|
||||||
@ -876,40 +876,79 @@ export class PaletteFormatToRGB extends PixNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NESNametableConverter extends PixNode {
|
export abstract class Compositor extends PixNode {
|
||||||
|
|
||||||
palette : Uint32Array;
|
|
||||||
tilemap : Uint8Array[]; // tilemap images
|
tilemap : Uint8Array[]; // tilemap images
|
||||||
rgbimgs : Uint32Array[]; // output (1 image)
|
images : Uint8Array[]; // output (1 image)
|
||||||
width : number;
|
width : number;
|
||||||
height : number;
|
height : number;
|
||||||
cols : number;
|
|
||||||
rows : number;
|
|
||||||
baseofs : number;
|
|
||||||
|
|
||||||
context : EditorContext;
|
context : EditorContext;
|
||||||
paloptions : SelectablePalette[];
|
|
||||||
tileoptions : SelectableTilemap[];
|
tileoptions : SelectableTilemap[];
|
||||||
palindex : number = 0;
|
|
||||||
tileindex : number = 0;
|
tileindex : number = 0;
|
||||||
|
|
||||||
constructor(context:EditorContext) {
|
constructor(context:EditorContext) {
|
||||||
super();
|
super();
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
updateRefs() {
|
||||||
|
if (this.context != null) {
|
||||||
|
this.tileoptions = this.context.getTilemaps(256);
|
||||||
|
if (this.tileoptions && this.tileoptions.length > 0) {
|
||||||
|
this.tilemap = this.tileoptions[this.tileindex].images;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MetaspriteEntry = {
|
||||||
|
x:number, y:number, tile:number, attr:number
|
||||||
|
};
|
||||||
|
|
||||||
|
export class MetaspriteCompositor extends Compositor {
|
||||||
|
|
||||||
|
metadefs : MetaspriteEntry[];
|
||||||
|
|
||||||
|
constructor(context:EditorContext, metadefs) {
|
||||||
|
super(context);
|
||||||
|
this.metadefs = metadefs;
|
||||||
|
}
|
||||||
|
updateLeft() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
updateRight() {
|
||||||
|
this.updateRefs();
|
||||||
|
this.width = 16; // TODO
|
||||||
|
this.height = 16; // TODO
|
||||||
|
var idata = new Uint8Array(this.width * this.height);
|
||||||
|
this.images = [idata];
|
||||||
|
this.metadefs.forEach((meta) => {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NESNametableConverter extends Compositor {
|
||||||
|
|
||||||
|
cols : number;
|
||||||
|
rows : number;
|
||||||
|
baseofs : number;
|
||||||
|
constructor(context:EditorContext) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
updateLeft() {
|
updateLeft() {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
updateRight() {
|
updateRight() {
|
||||||
this.words = this.left.words;
|
this.words = this.left.words;
|
||||||
this.updatePalette();
|
this.updateRefs();
|
||||||
this.cols = 32;
|
this.cols = 32;
|
||||||
this.rows = 30;
|
this.rows = 30;
|
||||||
this.width = this.cols * 8;
|
this.width = this.cols * 8;
|
||||||
this.height = this.rows * 8;
|
this.height = this.rows * 8;
|
||||||
this.baseofs = 0;
|
this.baseofs = 0;
|
||||||
var idata = new Uint32Array(this.width * this.height);
|
var idata = new Uint8Array(this.width * this.height);
|
||||||
this.rgbimgs = [idata];
|
this.images = [idata];
|
||||||
var a = 0;
|
var a = 0;
|
||||||
var attraddr;
|
var attraddr;
|
||||||
for (var row=0; row<this.rows; row++) {
|
for (var row=0; row<this.rows; row++) {
|
||||||
@ -927,8 +966,7 @@ export class NESNametableConverter extends PixNode {
|
|||||||
for (var x=0; x<8; x++) {
|
for (var x=0; x<8; x++) {
|
||||||
var color = t[j++];
|
var color = t[j++];
|
||||||
if (color) color += coloradd;
|
if (color) color += coloradd;
|
||||||
var rgb = this.palette[color];
|
idata[i++] = color;
|
||||||
idata[i++] = rgb | 0xff000000;
|
|
||||||
}
|
}
|
||||||
i += this.cols*8-8;
|
i += this.cols*8-8;
|
||||||
}
|
}
|
||||||
@ -937,18 +975,6 @@ export class NESNametableConverter extends PixNode {
|
|||||||
}
|
}
|
||||||
// TODO
|
// 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
|
///// UI CONTROLS
|
||||||
@ -1073,17 +1099,17 @@ export class CharmapEditor extends PixNode {
|
|||||||
// add palette selector
|
// add palette selector
|
||||||
// TODO: only view when editing?
|
// TODO: only view when editing?
|
||||||
var palizer = this.left;
|
var palizer = this.left;
|
||||||
if (palizer instanceof Palettizer && palizer.options.length > 1) {
|
if (palizer instanceof Palettizer && palizer.paloptions.length > 1) {
|
||||||
var palselect = $(document.createElement('select'));
|
var palselect = $(document.createElement('select'));
|
||||||
palizer.options.forEach((palopt, i) => {
|
palizer.paloptions.forEach((palopt, i) => {
|
||||||
// TODO: full identifier
|
// TODO: full identifier
|
||||||
var sel = $(document.createElement('option')).text(palopt.name).val(i).appendTo(palselect);
|
var sel = $(document.createElement('option')).text(palopt.name).val(i).appendTo(palselect);
|
||||||
if (i == (palizer as Palettizer).selindex)
|
if (i == (palizer as Palettizer).palindex)
|
||||||
sel.attr('selected','selected');
|
sel.attr('selected','selected');
|
||||||
});
|
});
|
||||||
palselect.appendTo(agrid).change((e) => {
|
palselect.appendTo(agrid).change((e) => {
|
||||||
var index = $(e.target).val() as number;
|
var index = $(e.target).val() as number;
|
||||||
(palizer as Palettizer).selindex = index;
|
(palizer as Palettizer).palindex = index;
|
||||||
palizer.refreshRight();
|
palizer.refreshRight();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
27
src/views.ts
27
src/views.ts
@ -1029,8 +1029,8 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
|
|||||||
while (node != null) {
|
while (node != null) {
|
||||||
if (node instanceof pixed.Palettizer) {
|
if (node instanceof pixed.Palettizer) {
|
||||||
// TODO: move to node class?
|
// TODO: move to node class?
|
||||||
var rgbimgs = node.rgbimgs;
|
var rgbimgs = node.rgbimgs; // TODO: why is null?
|
||||||
if (rgbimgs.length >= matchlen) {
|
if (rgbimgs && rgbimgs.length >= matchlen) {
|
||||||
result.push({node:node, name:"Tilemap", images:node.images, rgbimgs:rgbimgs}); // TODO
|
result.push({node:node, name:"Tilemap", images:node.images, rgbimgs:rgbimgs}); // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1072,7 +1072,9 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
|
|||||||
var start = m.index + m[0].length;
|
var start = m.index + m[0].length;
|
||||||
var end;
|
var end;
|
||||||
// TODO: verilog end
|
// TODO: verilog end
|
||||||
if (m[0].startsWith(';;')) {
|
if (platform_id == 'verilog') {
|
||||||
|
end = data.indexOf("end", start); // asm
|
||||||
|
} else if (m[0].startsWith(';;')) {
|
||||||
end = data.indexOf(';;', start); // asm
|
end = data.indexOf(';;', start); // asm
|
||||||
} else {
|
} else {
|
||||||
end = data.indexOf(';', start); // C
|
end = data.indexOf(';', start); // C
|
||||||
@ -1089,6 +1091,24 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// look for DEF_METASPRITE_2x2(playerRStand, 0xd8, 0)
|
||||||
|
// TODO: could also look in ROM
|
||||||
|
var re2 = /DEF_METASPRITE_(\d+)x(\d+)[(](\w+),\s*(\w+),\s*(\w+)/gi;
|
||||||
|
while (m = re2.exec(data)) {
|
||||||
|
var width = parseInt(m[1]);
|
||||||
|
var height = parseInt(m[2]);
|
||||||
|
var ident = m[3];
|
||||||
|
var tile = parseInt(m[4]);
|
||||||
|
var attr = parseInt(m[5]);
|
||||||
|
var metadefs = [];
|
||||||
|
for (var x=0; x<width; x++) {
|
||||||
|
for (var y=0; y<height; y++) {
|
||||||
|
metadefs.push({x:x*8, y:y*8, tile:tile, attr:attr});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var meta = {defs:metadefs,width:width*8,height:height*8};
|
||||||
|
result.push({fileid:id,label:ident,meta:meta});
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,6 +1217,7 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext {
|
|||||||
// is this a nes nametable?
|
// is this a nes nametable?
|
||||||
if (frag.fmt.map == 'nesnt') {
|
if (frag.fmt.map == 'nesnt') {
|
||||||
node = node.addRight(new pixed.NESNametableConverter(this)); // TODO?
|
node = node.addRight(new pixed.NESNametableConverter(this)); // TODO?
|
||||||
|
node = node.addRight(new pixed.Palettizer(this, {w:8,h:8,bpp:4})); // TODO?
|
||||||
const fmt = {w:8*32,h:8*30,count:1}; // TODO
|
const fmt = {w:8*32,h:8*30,count:1}; // TODO
|
||||||
node = node.addRight(new pixed.CharmapEditor(this, newDiv(filediv), fmt));
|
node = node.addRight(new pixed.CharmapEditor(this, newDiv(filediv), fmt));
|
||||||
this.registerAsset("nametable", first, true);
|
this.registerAsset("nametable", first, true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user