mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-05-28 23:41:32 +00:00
ecs: temp vars
This commit is contained in:
parent
01056c66a8
commit
bc7cd6f1a3
|
@ -66,16 +66,26 @@ export class Bin {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
fits(b: Box) {
|
fits(b: Box) {
|
||||||
if (!boxesIntersect(this.binbounds, b)) return false;
|
if (!boxesIntersect(this.binbounds, b)) {
|
||||||
if (this.getBoxes(b, 1).length > 0) return false;
|
if (debug) console.log('out of bounds!', b.left,b.top,b.right,b.bottom);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.getBoxes(b, 1).length > 0) {
|
||||||
|
if (debug) console.log('intersect!', b.left,b.top,b.right,b.bottom);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bestFit(b: Box) : Box | null {
|
bestFit(b: BoxConstraints) : Box | null {
|
||||||
let bestscore = 0;
|
let bestscore = 0;
|
||||||
let best = null;
|
let best = null;
|
||||||
for (let f of this.free) {
|
for (let f of this.free) {
|
||||||
let dx = (f.right - f.left) - (b.right - b.left);
|
if (b.left != null && b.left < f.left) continue;
|
||||||
let dy = (f.bottom - f.top) - (b.bottom - b.top);
|
if (b.left != null && b.left + b.width > f.right) continue;
|
||||||
|
if (b.top != null && b.top < f.top) continue;
|
||||||
|
if (b.top != null && b.top + b.height > f.bottom) continue;
|
||||||
|
let dx = (f.right - f.left) - b.width;
|
||||||
|
let dy = (f.bottom - f.top) - b.height;
|
||||||
if (dx >= 0 && dy >= 0) {
|
if (dx >= 0 && dy >= 0) {
|
||||||
let score = 1 / (1 + dx + dy);
|
let score = 1 / (1 + dx + dy);
|
||||||
if (score > bestscore) {
|
if (score > bestscore) {
|
||||||
|
@ -85,8 +95,26 @@ export class Bin {
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
anyFit(b: BoxConstraints) : Box | null {
|
||||||
|
let bestscore = 0;
|
||||||
|
let best = null;
|
||||||
|
for (let f of this.free) {
|
||||||
|
let box : Box = {
|
||||||
|
left: b.left != null ? b.left : f.left,
|
||||||
|
right: f.left + b.width,
|
||||||
|
top: b.top != null ? b.top : f.top,
|
||||||
|
bottom: f.top + b.height };
|
||||||
|
if (this.fits(box)) {
|
||||||
|
let score = 1 / (1 + box.left + box.top);
|
||||||
|
if (score > bestscore) {
|
||||||
|
best = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
add(b: PlacedBox) {
|
add(b: PlacedBox) {
|
||||||
if (debug) console.log('added',b.left,b.top,b.right,b.bottom);
|
if (debug) console.log('added', b.left,b.top,b.right,b.bottom);
|
||||||
if (!this.fits(b)) {
|
if (!this.fits(b)) {
|
||||||
//console.log('collided with', this.getBoxes(b, 1));
|
//console.log('collided with', this.getBoxes(b, 1));
|
||||||
throw new Error(`bad fit ${b.left} ${b.top} ${b.right} ${b.bottom}`)
|
throw new Error(`bad fit ${b.left} ${b.top} ${b.right} ${b.bottom}`)
|
||||||
|
@ -141,19 +169,29 @@ export class Packer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bestPlacement(b: BoxConstraints) : PlacedBox | null {
|
bestPlacement(b: BoxConstraints) : PlacedBox | null {
|
||||||
let left = b.left != null ? b.left : 0;
|
|
||||||
let top = b.top != null ? b.top : 0;
|
|
||||||
let right = left + b.width;
|
|
||||||
let bottom = top + b.height;
|
|
||||||
for (let bin of this.bins) {
|
for (let bin of this.bins) {
|
||||||
let place : BoxPlacement = BoxPlacement.TopLeft; //TODO
|
let place : BoxPlacement = BoxPlacement.TopLeft; //TODO
|
||||||
let box = { left, top, right, bottom };
|
let parent = bin.bestFit(b);
|
||||||
let parent = bin.bestFit(box);
|
if (!parent) {
|
||||||
|
parent = bin.anyFit(b);
|
||||||
|
if (debug) console.log('anyfit',parent?.left,parent?.top);
|
||||||
|
}
|
||||||
if (parent) {
|
if (parent) {
|
||||||
box.left = parent.left;
|
let box = {
|
||||||
box.top = parent.top;
|
left: parent.left,
|
||||||
box.right = parent.left + b.width;
|
top: parent.top,
|
||||||
box.bottom = parent.top + b.height;
|
right: parent.left + b.width,
|
||||||
|
bottom: parent.top + b.height
|
||||||
|
};
|
||||||
|
if (b.left != null) {
|
||||||
|
box.left = b.left;
|
||||||
|
box.right = b.left + b.width;
|
||||||
|
}
|
||||||
|
if (b.top != null) {
|
||||||
|
box.top = b.top;
|
||||||
|
box.bottom = b.top + b.height;
|
||||||
|
}
|
||||||
|
if (debug) console.log('place',box.left,box.top,box.right,box.bottom,parent?.left,parent?.top);
|
||||||
/*
|
/*
|
||||||
if (place == BoxPlacement.BottomLeft || place == BoxPlacement.BottomRight) {
|
if (place == BoxPlacement.BottomLeft || place == BoxPlacement.BottomRight) {
|
||||||
box.top = parent.bottom - (box.bottom - box.top);
|
box.top = parent.bottom - (box.bottom - box.top);
|
||||||
|
@ -165,6 +203,7 @@ export class Packer {
|
||||||
return { parent, place, bin, ...box };
|
return { parent, place, bin, ...box };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (debug) console.log('cannot place!', b.left,b.top,b.width,b.height);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ how to avoid cycle crossing for critical code and data?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SourceLocated, SourceLocation } from "../workertypes";
|
import { SourceLocated, SourceLocation } from "../workertypes";
|
||||||
|
import { Bin, Packer } from "./binpack";
|
||||||
|
|
||||||
export class ECSError extends Error {
|
export class ECSError extends Error {
|
||||||
$loc: SourceLocation;
|
$loc: SourceLocation;
|
||||||
|
@ -1150,6 +1151,29 @@ export class EntityScope implements SourceLocated {
|
||||||
this.resources.add(symbol);
|
this.resources.add(symbol);
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
allocateTempVars() {
|
||||||
|
let pack = new Packer();
|
||||||
|
let maxTempBytes = 128; // TODO
|
||||||
|
pack.bins.push(new Bin({ left:0, top:0, bottom: this.eventSeq+1, right: maxTempBytes }));
|
||||||
|
for (let sys of this.systems) {
|
||||||
|
let stats = this.getSystemStats(sys);
|
||||||
|
if (sys.tempbytes && stats.tempstartseq && stats.tempendseq) {
|
||||||
|
let v = {
|
||||||
|
sys,
|
||||||
|
top: stats.tempstartseq,
|
||||||
|
bottom: stats.tempendseq+1,
|
||||||
|
width: sys.tempbytes,
|
||||||
|
height: stats.tempendseq - stats.tempstartseq + 1,
|
||||||
|
};
|
||||||
|
pack.boxes.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pack.pack()) console.log('cannot pack temporary local vars'); // TODO
|
||||||
|
console.log('tempvars', pack);
|
||||||
|
for (let b of pack.boxes) {
|
||||||
|
console.log((b as any).sys.name, b.box);
|
||||||
|
}
|
||||||
|
}
|
||||||
analyzeEntities() {
|
analyzeEntities() {
|
||||||
this.buildSegments();
|
this.buildSegments();
|
||||||
this.allocateSegment(this.bss, false);
|
this.allocateSegment(this.bss, false);
|
||||||
|
@ -1173,6 +1197,7 @@ export class EntityScope implements SourceLocated {
|
||||||
this.code.addCodeFragment(code);
|
this.code.addCodeFragment(code);
|
||||||
}
|
}
|
||||||
//this.showStats();
|
//this.showStats();
|
||||||
|
this.allocateTempVars();
|
||||||
}
|
}
|
||||||
showStats() {
|
showStats() {
|
||||||
for (let sys of this.systems) {
|
for (let sys of this.systems) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import assert from "assert";
|
||||||
import { execFileSync, spawnSync } from "child_process";
|
import { execFileSync, spawnSync } from "child_process";
|
||||||
import { readdirSync, readFileSync, writeFileSync } from "fs";
|
import { readdirSync, readFileSync, writeFileSync } from "fs";
|
||||||
import { describe } from "mocha";
|
import { describe } from "mocha";
|
||||||
import { Bin, Packer } from "../common/ecs/binpack";
|
import { Bin, BoxConstraints, Packer } from "../common/ecs/binpack";
|
||||||
import { ECSCompiler } from "../common/ecs/compiler";
|
import { ECSCompiler } from "../common/ecs/compiler";
|
||||||
import { Dialect_CA65, EntityManager, SourceFileExport } from "../common/ecs/ecs";
|
import { Dialect_CA65, EntityManager, SourceFileExport } from "../common/ecs/ecs";
|
||||||
|
|
||||||
|
@ -396,18 +396,37 @@ describe('Compiler', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function testPack(bins: Bin[], boxes: BoxConstraints[]) {
|
||||||
|
let packer = new Packer();
|
||||||
|
for (let bin of bins) packer.bins.push(bin);
|
||||||
|
for (let bc of boxes) packer.boxes.push(bc);
|
||||||
|
if (!packer.pack()) throw new Error('cannot pack')
|
||||||
|
console.log(packer.boxes);
|
||||||
|
console.log(packer.bins[0].free)
|
||||||
|
}
|
||||||
|
|
||||||
describe('Box Packer', function() {
|
describe('Box Packer', function() {
|
||||||
it('Should pack boxes', function() {
|
it('Should pack boxes', function() {
|
||||||
let packer = new Packer();
|
testPack(
|
||||||
let bin1 = new Bin({ left:0, top:0, right:10, bottom:10 });
|
[
|
||||||
packer.bins.push(bin1);
|
new Bin({ left:0, top:0, right:10, bottom:10 })
|
||||||
packer.boxes.push({ width: 5, height: 5 });
|
], [
|
||||||
packer.boxes.push({ width: 5, height: 5 });
|
{ width: 5, height: 5 },
|
||||||
packer.boxes.push({ width: 5, height: 5 });
|
{ width: 5, height: 5 },
|
||||||
packer.boxes.push({ width: 5, height: 5 });
|
{ width: 5, height: 5 },
|
||||||
if (!packer.pack()) throw new Error('cannot pack')
|
{ width: 5, height: 5 },
|
||||||
console.log(packer.boxes);
|
]
|
||||||
console.log(packer.bins[0].free)
|
);
|
||||||
|
});
|
||||||
|
it('Should pack temp vars', function() {
|
||||||
|
testPack(
|
||||||
|
[
|
||||||
|
new Bin({ left:0, top:0, right:10, bottom:10 })
|
||||||
|
], [
|
||||||
|
{ width: 3, height: 7, top: 0 },
|
||||||
|
{ width: 3, height: 7, top: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user