Preserve presets through optimization so object list survives after optimizing
This commit is contained in:
Vendored
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>furniture-app</title>
|
<title>furniture-app</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BP-dLhBi.js"></script>
|
<script type="module" crossorigin src="/assets/index-DE7tP3Fy.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-9k24Ci9h.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-9k24Ci9h.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ export function optimizeWithNN(state: LayoutState, options: NNOptions = {}): { b
|
|||||||
...f,
|
...f,
|
||||||
shape: { ...f.shape, points: f.shape.points?.map((p) => ({ ...p })) },
|
shape: { ...f.shape, points: f.shape.points?.map((p) => ({ ...p })) },
|
||||||
})),
|
})),
|
||||||
|
presets: state.presets?.map((p) => ({
|
||||||
|
...p,
|
||||||
|
shape: { ...p.shape },
|
||||||
|
conditions: p.conditions.map((c) => ({ ...c, params: { ...(c.params || {}) } })),
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
const entrance = candidate.entrance;
|
const entrance = candidate.entrance;
|
||||||
|
|||||||
@@ -308,23 +308,11 @@ export function ControlPanel({
|
|||||||
<div className="grid-2">
|
<div className="grid-2">
|
||||||
<label className="field">
|
<label className="field">
|
||||||
<span>Width</span>
|
<span>Width</span>
|
||||||
<NumberField
|
<NumberField value={state.room.width} min={100} width="100%" onChange={(v) => setRoom({ width: v })} />
|
||||||
value={state.room.width}
|
|
||||||
min={100}
|
|
||||||
max={5000}
|
|
||||||
width="100%"
|
|
||||||
onChange={(v) => setRoom({ width: v })}
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
<label className="field">
|
<label className="field">
|
||||||
<span>Height</span>
|
<span>Height</span>
|
||||||
<NumberField
|
<NumberField value={state.room.height} min={100} width="100%" onChange={(v) => setRoom({ height: v })} />
|
||||||
value={state.room.height}
|
|
||||||
min={100}
|
|
||||||
max={5000}
|
|
||||||
width="100%"
|
|
||||||
onChange={(v) => setRoom({ height: v })}
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,38 +33,6 @@ export function RoomCanvas({ state, onStateChange, mode, selectedId, onSelect, s
|
|||||||
return () => clearInterval(t);
|
return () => clearInterval(t);
|
||||||
}, [showPaths]);
|
}, [showPaths]);
|
||||||
|
|
||||||
const [viewport, setViewport] = useState({ width: 1200, height: 800 });
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const resize = () => {
|
|
||||||
if (containerRef.current) {
|
|
||||||
setViewport({
|
|
||||||
width: Math.floor(containerRef.current.clientWidth),
|
|
||||||
height: Math.floor(containerRef.current.clientHeight),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
resize();
|
|
||||||
window.addEventListener('resize', resize);
|
|
||||||
return () => window.removeEventListener('resize', resize);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const canvas = canvasRef.current;
|
|
||||||
if (!canvas) return;
|
|
||||||
const dpr = Math.max(1, window.devicePixelRatio || 1);
|
|
||||||
const baseW = Math.min(state.room.width, viewport.width || state.room.width);
|
|
||||||
const baseH = Math.min(state.room.height, viewport.height || state.room.height);
|
|
||||||
canvas.style.width = `${baseW}px`;
|
|
||||||
canvas.style.height = `${baseH}px`;
|
|
||||||
canvas.width = baseW * dpr;
|
|
||||||
canvas.height = baseH * dpr;
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
if (ctx) ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
||||||
draw();
|
|
||||||
}, [state.room.width, state.room.height, zoom, viewport]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
draw();
|
draw();
|
||||||
}, [state, selectedId, mode, zoom, showPaths, phase]);
|
}, [state, selectedId, mode, zoom, showPaths, phase]);
|
||||||
@@ -74,14 +42,9 @@ export function RoomCanvas({ state, onStateChange, mode, selectedId, onSelect, s
|
|||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
const dpr = Math.max(1, window.devicePixelRatio || 1);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
||||||
ctx.clearRect(0, 0, canvas.width / dpr, canvas.height / dpr);
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
const scaleX = (canvas.width / dpr) / state.room.width;
|
ctx.scale(zoom, zoom);
|
||||||
const scaleY = (canvas.height / dpr) / state.room.height;
|
|
||||||
const s = Math.min(scaleX, scaleY);
|
|
||||||
ctx.scale(s, s);
|
|
||||||
|
|
||||||
ctx.fillStyle = '#12151b';
|
ctx.fillStyle = '#12151b';
|
||||||
ctx.fillRect(0, 0, state.room.width, state.room.height);
|
ctx.fillRect(0, 0, state.room.width, state.room.height);
|
||||||
@@ -90,21 +53,16 @@ export function RoomCanvas({ state, onStateChange, mode, selectedId, onSelect, s
|
|||||||
ctx.strokeStyle = 'rgba(255,255,255,0.035)';
|
ctx.strokeStyle = 'rgba(255,255,255,0.035)';
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
const step = 25;
|
const step = 25;
|
||||||
const maxLines = 2000;
|
for (let x = 0; x <= state.room.width; x += step) {
|
||||||
const xCount = Math.min(Math.floor(state.room.width / step) + 1, maxLines);
|
|
||||||
const yCount = Math.min(Math.floor(state.room.height / step) + 1, maxLines);
|
|
||||||
for (let i = 0; i < xCount; i++) {
|
|
||||||
const x = i * step;
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(x, 0);
|
ctx.moveTo(x, 0);
|
||||||
ctx.lineTo(x, Math.min(state.room.height, step * yCount));
|
ctx.lineTo(x, state.room.height);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
for (let i = 0; i < yCount; i++) {
|
for (let y = 0; y <= state.room.height; y += step) {
|
||||||
const y = i * step;
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(0, y);
|
ctx.moveTo(0, y);
|
||||||
ctx.lineTo(Math.min(state.room.width, step * xCount), y);
|
ctx.lineTo(state.room.width, y);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,19 +308,17 @@ export function RoomCanvas({ state, onStateChange, mode, selectedId, onSelect, s
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef} style={{ width: '100%', height: '100%' }}>
|
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
width={Math.min(state.room.width, 2000)}
|
width={Math.max(state.room.width, 400)}
|
||||||
height={Math.min(state.room.height, 2000)}
|
height={Math.max(state.room.height, 300)}
|
||||||
style={{ maxWidth: '100%', maxHeight: '100%', width: '100%', height: '100%', objectFit: 'contain' }}
|
style={{ maxWidth: '100%', height: 'auto' }}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
onMouseUp={handleMouseUp}
|
onMouseUp={handleMouseUp}
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
onDrop={handleDrop}
|
onDrop={handleDrop}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ export function colliderCorners(c: Collider): Point[] {
|
|||||||
function project(points: Point[], axis: Point): [number, number] {
|
function project(points: Point[], axis: Point): [number, number] {
|
||||||
let min = Infinity;
|
let min = Infinity;
|
||||||
let max = -Infinity;
|
let max = -Infinity;
|
||||||
for (let i = 0; i < points.length; i++) {
|
for (const p of points) {
|
||||||
const p = points[i];
|
|
||||||
const d = p.x * axis.x + p.y * axis.y;
|
const d = p.x * axis.x + p.y * axis.y;
|
||||||
if (d < min) min = d;
|
if (d < min) min = d;
|
||||||
if (d > max) max = d;
|
if (d > max) max = d;
|
||||||
|
|||||||
@@ -48,5 +48,6 @@ function cloneState(state: LayoutState): LayoutState {
|
|||||||
room: { ...state.room },
|
room: { ...state.room },
|
||||||
entrance: state.entrance ? { ...state.entrance } : null,
|
entrance: state.entrance ? { ...state.entrance } : null,
|
||||||
furniture: state.furniture.map((f) => new Furniture(f).toConfig()),
|
furniture: state.furniture.map((f) => new Furniture(f).toConfig()),
|
||||||
|
presets: state.presets?.map((p) => ({ ...p, shape: { ...p.shape }, conditions: p.conditions.map((c) => ({ ...c, params: { ...(c.params || {}) } })) })),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user