mirror of
https://git.sfja.dk/sfja/h6-logicirc.git
synced 2025-06-06 19:38:45 +01:00
start rework coordinates
This commit is contained in:
parent
36b29bdcef
commit
91e8d7dc6c
@ -46,6 +46,7 @@ export class V2 {
|
||||
export interface Geometry {
|
||||
pointInside(thisPos: V2, pointPos: V2): boolean;
|
||||
collidesWith(thisPos: V2, other: Geometry, otherPos: V2): boolean;
|
||||
boundingRectSize(): V2;
|
||||
render(r: Renderer, pos: V2, color: string): void;
|
||||
}
|
||||
|
||||
@ -77,6 +78,10 @@ export class Rect implements Geometry {
|
||||
return other.collidesWith(otherPos, this, thisPos);
|
||||
}
|
||||
|
||||
boundingRectSize(): V2 {
|
||||
return new V2(this.width, this.height);
|
||||
}
|
||||
|
||||
render(r: Renderer, pos: V2, color: string): void {
|
||||
r.fillRect(pos.x, pos.y, this.width, this.height, color);
|
||||
}
|
||||
@ -114,6 +119,10 @@ export class Circle implements Geometry {
|
||||
return other.collidesWith(otherPos, other, thisPos);
|
||||
}
|
||||
|
||||
boundingRectSize(): V2 {
|
||||
return new V2(this.radius, this.radius);
|
||||
}
|
||||
|
||||
render(r: Renderer, pos: V2, color: string): void {
|
||||
r.fillCirc(pos.x, pos.y, this.radius, color);
|
||||
}
|
||||
@ -138,6 +147,16 @@ export class Shape implements Geometry {
|
||||
);
|
||||
}
|
||||
|
||||
boundingRectSize(): V2 {
|
||||
return this.innerShapes
|
||||
.reduce((size, [pos, shape]) => {
|
||||
const shapeSize = shape.boundingRectSize();
|
||||
size.x = Math.max(size.x, pos.x + shapeSize.x);
|
||||
size.y = Math.max(size.y, pos.y + shapeSize.y);
|
||||
return size;
|
||||
}, new V2(0, 0));
|
||||
}
|
||||
|
||||
render(r: Renderer, pos: V2, color: string): void {
|
||||
for (const [shapePos, shape] of this.innerShapes) {
|
||||
shape.render(r, shapePos.add(pos), color);
|
||||
|
178
src/simulator.ts
178
src/simulator.ts
@ -39,10 +39,15 @@ export class Simulator {
|
||||
}
|
||||
}
|
||||
|
||||
type Tool = {
|
||||
component: Component;
|
||||
offsetX: number;
|
||||
};
|
||||
|
||||
class Toolbar {
|
||||
private tools: Component[] = [
|
||||
new SwitchComponent(),
|
||||
new LedComponent(),
|
||||
private tools: Tool[] = [
|
||||
{ component: new SwitchComponent(), offsetX: 32 },
|
||||
{ component: new LedComponent(), offsetX: 256 },
|
||||
];
|
||||
|
||||
private lastWidth = 0;
|
||||
@ -50,6 +55,8 @@ class Toolbar {
|
||||
|
||||
private hoveringComponentIdx?: number;
|
||||
|
||||
private scale = 64;
|
||||
|
||||
constructor(
|
||||
private mouse: Mouse,
|
||||
private tooltip: Tooltip,
|
||||
@ -64,14 +71,16 @@ class Toolbar {
|
||||
return "bubble";
|
||||
}
|
||||
|
||||
for (const [i, component] of this.tools.entries()) {
|
||||
for (const [i, tool] of this.tools.entries()) {
|
||||
const compWidth = tool.component.width * this.scale;
|
||||
const compHeight = tool.component.height * this.scale;
|
||||
if (
|
||||
x >= i * 128 + 96 - 48 &&
|
||||
x >= tool.offsetX &&
|
||||
y >= this.lastHeight - 100 - 48 &&
|
||||
x < i * 128 + 96 + component.width * 32 + 32 &&
|
||||
y < this.lastHeight - 100 + component.height * 32 + 32
|
||||
x < tool.offsetX + compWidth &&
|
||||
y < this.lastHeight - 100 + compHeight
|
||||
) {
|
||||
this.tooltip.select(this.tools[i]);
|
||||
this.tooltip.select(this.tools[i].component);
|
||||
return "stop";
|
||||
}
|
||||
}
|
||||
@ -82,12 +91,14 @@ class Toolbar {
|
||||
|
||||
hover(): "continue" | "break" {
|
||||
const { x, y } = this.mouse;
|
||||
for (const [i, component] of this.tools.entries()) {
|
||||
for (const [i, tool] of this.tools.entries()) {
|
||||
const compWidth = tool.component.width * this.scale;
|
||||
const compHeight = tool.component.height * this.scale;
|
||||
if (
|
||||
x >= i * 128 + 96 - 48 &&
|
||||
y >= this.lastHeight - 100 - 48 &&
|
||||
x < i * 128 + 96 + component.width * 32 + 32 &&
|
||||
y < this.lastHeight - 100 + component.height * 32 + 32
|
||||
x >= tool.offsetX &&
|
||||
y >= this.lastHeight - 100 &&
|
||||
x < tool.offsetX + compWidth &&
|
||||
y < this.lastHeight - 100 + compHeight
|
||||
) {
|
||||
this.hoveringComponentIdx = i;
|
||||
document.body.style.cursor = "pointer";
|
||||
@ -103,25 +114,28 @@ class Toolbar {
|
||||
this.lastHeight = r.height;
|
||||
|
||||
r.fillRect(0, r.height - 200, r.width, 200, "#aaa");
|
||||
for (const [i, component] of this.tools.entries()) {
|
||||
|
||||
for (const [i, tool] of this.tools.entries()) {
|
||||
const compWidth = tool.component.width * this.scale;
|
||||
const compHeight = tool.component.height * this.scale;
|
||||
r.strokeRect(
|
||||
i * 128 + 96 - 48,
|
||||
r.height - 100 - 48,
|
||||
96,
|
||||
96,
|
||||
tool.offsetX,
|
||||
r.height - 100,
|
||||
compWidth,
|
||||
compHeight,
|
||||
"#777",
|
||||
1,
|
||||
);
|
||||
if (i === this.hoveringComponentIdx) {
|
||||
r.fillRect(
|
||||
i * 128 + 96 - 48,
|
||||
r.height - 100 - 48,
|
||||
component.height * 32 + 64,
|
||||
component.width * 32 + 64,
|
||||
tool.offsetX,
|
||||
r.height - 100,
|
||||
compWidth,
|
||||
compHeight,
|
||||
"#00000088",
|
||||
);
|
||||
}
|
||||
component.render(r, i * 128 + 96, r.height - 100);
|
||||
tool.component.render(r, tool.offsetX, r.height - 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,12 +214,16 @@ class Tooltip {
|
||||
}
|
||||
|
||||
render(r: Renderer): void {
|
||||
const x = Math.floor(this.mouse.x / 32);
|
||||
const y = Math.floor(this.mouse.y / 32);
|
||||
if (this.selectedComponent) {
|
||||
const x = Math.floor(this.mouse.x / 32) * 32;
|
||||
const y = Math.floor(this.mouse.y / 32) * 32;
|
||||
if (this.shouldHover) {
|
||||
this.selectedComponent
|
||||
.renderTransparent(r, x * 32 + 16, y * 32 + 16);
|
||||
.renderTransparent(
|
||||
r,
|
||||
x - this.selectedComponent.offsetX * 32,
|
||||
y - this.selectedComponent.height * 32,
|
||||
);
|
||||
}
|
||||
} else if (!this.isWiring) {
|
||||
const output = this.selectedOutputTerm;
|
||||
@ -355,7 +373,11 @@ class Circuit {
|
||||
r.strokeLine(source.x, source.y, dest.x, dest.y, "black", 3);
|
||||
}
|
||||
for (const { component, x, y } of this.components) {
|
||||
component.render(r, x * 32 + 16, y * 32 + 16);
|
||||
component.render(
|
||||
r,
|
||||
x * 32 - component.offsetX * 32,
|
||||
y * 32 - component.offsetY * 32,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -384,6 +406,8 @@ class ComponentWireTerm implements WireSource, WireDest {
|
||||
}
|
||||
|
||||
interface Component {
|
||||
get offsetX(): number;
|
||||
get offsetY(): number;
|
||||
get width(): number;
|
||||
get height(): number;
|
||||
|
||||
@ -404,19 +428,45 @@ class SwitchComponent implements Component {
|
||||
|
||||
private switchOn = false;
|
||||
|
||||
public width = 1;
|
||||
public height = 1;
|
||||
|
||||
private geometry = new Rect(2, 1);
|
||||
private geometry = new Rect(1.5, 1);
|
||||
|
||||
constructor() {
|
||||
this.graphicOff.fillRect(64, 30, 16, 4, "black");
|
||||
this.graphicOff.fillCirc(48 + 32, 32, 8, "black");
|
||||
this.graphicOff.fillCirc(48, 32, 16, "black");
|
||||
this.graphicOff.strokeRect(
|
||||
0,
|
||||
0,
|
||||
this.graphicOff.width,
|
||||
this.graphicOff.height,
|
||||
"#88000088",
|
||||
2,
|
||||
);
|
||||
this.graphicOff.fillRect(48, 30, 16, 4, "black");
|
||||
this.graphicOff.fillCirc(64, 32, 8, "black");
|
||||
this.graphicOff.fillCirc(32, 32, 16, "black");
|
||||
|
||||
this.graphicOn.fillRect(64, 30, 16, 4, "black");
|
||||
this.graphicOn.fillCirc(48 + 32, 32, 8, "black");
|
||||
this.graphicOn.fillCirc(48, 32, 16, "red");
|
||||
this.graphicOn.strokeRect(
|
||||
0,
|
||||
0,
|
||||
this.graphicOn.width,
|
||||
this.graphicOn.height,
|
||||
"#88000088",
|
||||
2,
|
||||
);
|
||||
this.graphicOn.fillRect(48, 30, 16, 4, "black");
|
||||
this.graphicOn.fillCirc(64, 32, 8, "black");
|
||||
this.graphicOn.fillCirc(32, 32, 16, "red");
|
||||
}
|
||||
|
||||
get offsetX(): number {
|
||||
return 0.5;
|
||||
}
|
||||
get offsetY(): number {
|
||||
return 0.5;
|
||||
}
|
||||
get width(): number {
|
||||
return this.geometry.width;
|
||||
}
|
||||
get height(): number {
|
||||
return this.geometry.height;
|
||||
}
|
||||
|
||||
clone(): Component {
|
||||
@ -433,12 +483,12 @@ class SwitchComponent implements Component {
|
||||
|
||||
render(r: Renderer, x: number, y: number): void {
|
||||
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||
graphic.render(r, x - 48, y - 32);
|
||||
graphic.render(r, x, y);
|
||||
}
|
||||
|
||||
renderTransparent(r: Renderer, x: number, y: number): void {
|
||||
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||
graphic.render(r, x - 48, y - 32, 0.5);
|
||||
graphic.render(r, x, y, 0.5);
|
||||
}
|
||||
|
||||
click(x: number, y: number): void {
|
||||
@ -478,19 +528,45 @@ class LedComponent implements Component {
|
||||
|
||||
private switchOn = false;
|
||||
|
||||
public width = 1;
|
||||
public height = 1;
|
||||
|
||||
private geometry = new Rect(2, 1);
|
||||
private geometry = new Rect(1.5, 1);
|
||||
|
||||
constructor() {
|
||||
this.graphicOff.fillRect(16, 30, 16, 4, "black");
|
||||
this.graphicOff.fillCirc(16, 32, 8, "black");
|
||||
this.graphicOff.fillCirc(48, 32, 16, "black");
|
||||
this.graphicOff.strokeRect(
|
||||
0,
|
||||
0,
|
||||
this.graphicOff.width,
|
||||
this.graphicOff.height,
|
||||
"#88000088",
|
||||
2,
|
||||
);
|
||||
this.graphicOff.fillRect(32, 30, 16, 4, "black");
|
||||
this.graphicOff.fillCirc(32, 32, 8, "black");
|
||||
this.graphicOff.fillCirc(64, 32, 16, "black");
|
||||
|
||||
this.graphicOn.fillRect(16, 30, 16, 4, "black");
|
||||
this.graphicOn.fillCirc(16, 32, 8, "black");
|
||||
this.graphicOn.fillCirc(48, 32, 16, "red");
|
||||
this.graphicOn.strokeRect(
|
||||
0,
|
||||
0,
|
||||
this.graphicOn.width,
|
||||
this.graphicOn.height,
|
||||
"#88000088",
|
||||
2,
|
||||
);
|
||||
this.graphicOn.fillRect(32, 30, 16, 4, "black");
|
||||
this.graphicOn.fillCirc(32, 32, 8, "black");
|
||||
this.graphicOn.fillCirc(64, 32, 16, "red");
|
||||
}
|
||||
|
||||
get offsetX(): number {
|
||||
return 1.5;
|
||||
}
|
||||
get offsetY(): number {
|
||||
return 0.5;
|
||||
}
|
||||
get width(): number {
|
||||
return this.geometry.width;
|
||||
}
|
||||
get height(): number {
|
||||
return this.geometry.height;
|
||||
}
|
||||
|
||||
clone(): Component {
|
||||
@ -511,12 +587,12 @@ class LedComponent implements Component {
|
||||
|
||||
render(r: Renderer, x: number, y: number): void {
|
||||
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||
graphic.render(r, x - 48, y - 32);
|
||||
graphic.render(r, x, y);
|
||||
}
|
||||
|
||||
renderTransparent(r: Renderer, x: number, y: number): void {
|
||||
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||
graphic.render(r, x - 48, y - 32, 0.5);
|
||||
graphic.render(r, x, y, 0.5);
|
||||
}
|
||||
|
||||
hoveredInputTerminal(
|
||||
|
Loading…
Reference in New Issue
Block a user