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