Confirms the units conversion (bufferCap 240 = 8.0s of cover at a 30/s
deficit) and reports scram survival: first scram t434, restart t934,
~718-tick duty cycle, ZERO brownout ticks across 20k, melt rate unchanged.
For the orchestrator:
- heat semantics need a one-line ruling. heatPerTick is GROSS in my model
(net = heatPerTick - coolPerTick). DATA's committed 0.0025 against the
0.004 default nets negative -- the decoder could never scram. Their
in-flight 0.0033/0.001 works, so we agree by luck of timing.
- the codex's literal bloom loop is not expressible with per-grade recipes
- asic-cooler does nothing without a spatial heat mechanic
- my sim code landed inside 45003db [ui] REMOVE mode: the shared tree has
one git index and an add-everything commit in another session swept it.
Not a UI ownership violation. Suggest a no-`git add -A` rule.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
108 lines
3.0 KiB
TypeScript
108 lines
3.0 KiB
TypeScript
/**
|
|
* LANE-RENDER — remove-mode hover.
|
|
*
|
|
* Two reads at once: a hazard-striped decal on the machine's footprint (this is the
|
|
* ground you are about to clear) and a red wash over its volume (this is the thing that
|
|
* is going away). Stripes because the codex dresses everything horrifying as routine
|
|
* industrial equipment — demolition should look like a permit, not an explosion.
|
|
*
|
|
* Driven by the `__remove` ghost sentinel; see ghost.ts.
|
|
*/
|
|
import * as THREE from 'three';
|
|
|
|
const DEMOLITION = 0xff3b30;
|
|
|
|
const DECAL_VERT = /* glsl */ `
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}
|
|
`;
|
|
|
|
const DECAL_FRAG = /* glsl */ `
|
|
precision highp float;
|
|
uniform float uTime;
|
|
uniform vec2 uScale; // footprint in tiles, so stripes don't stretch on big machines
|
|
uniform vec3 uColor;
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
// Border: constant thickness regardless of footprint.
|
|
vec2 d = min(vUv, 1.0 - vUv) * uScale;
|
|
float edge = min(d.x, d.y);
|
|
float border = 1.0 - smoothstep(0.04, 0.10, edge);
|
|
|
|
// Hazard stripes, crawling.
|
|
vec2 p = vUv * uScale;
|
|
float s = fract((p.x + p.y) * 1.6 - uTime * 0.5);
|
|
float stripe = step(0.5, s);
|
|
|
|
float a = max(border, stripe * 0.28);
|
|
if (a < 0.01) discard;
|
|
gl_FragColor = vec4(uColor, a * 0.85);
|
|
}
|
|
`;
|
|
|
|
export class RemoveHover {
|
|
readonly group = new THREE.Group();
|
|
private decal: THREE.Mesh;
|
|
private wash: THREE.Mesh;
|
|
private uniforms = {
|
|
uTime: { value: 0 },
|
|
uScale: { value: new THREE.Vector2(1, 1) },
|
|
uColor: { value: new THREE.Color(DEMOLITION) },
|
|
};
|
|
|
|
constructor() {
|
|
this.group.name = 'removeHover';
|
|
this.group.visible = false;
|
|
this.group.renderOrder = 11;
|
|
|
|
this.decal = new THREE.Mesh(
|
|
new THREE.PlaneGeometry(1, 1),
|
|
new THREE.ShaderMaterial({
|
|
uniforms: this.uniforms,
|
|
vertexShader: DECAL_VERT,
|
|
fragmentShader: DECAL_FRAG,
|
|
transparent: true,
|
|
depthWrite: false,
|
|
}),
|
|
);
|
|
this.decal.rotation.x = -Math.PI / 2;
|
|
this.decal.position.y = 0.02; // just clear of the ground plane
|
|
this.group.add(this.decal);
|
|
|
|
this.wash = new THREE.Mesh(
|
|
new THREE.BoxGeometry(1, 1, 1),
|
|
new THREE.MeshBasicMaterial({
|
|
color: DEMOLITION,
|
|
transparent: true,
|
|
opacity: 0.3,
|
|
depthWrite: false,
|
|
}),
|
|
);
|
|
this.group.add(this.wash);
|
|
}
|
|
|
|
hide(): void {
|
|
this.group.visible = false;
|
|
}
|
|
|
|
/**
|
|
* Frame the machine we're about to demolish. `w`/`d` are its ROTATED footprint, so a
|
|
* 2x3 turned east reads as 3x2 — the decal has to match what's actually occupied.
|
|
*/
|
|
show(cx: number, cz: number, w: number, d: number, height: number, timeSec: number): void {
|
|
this.group.visible = true;
|
|
this.uniforms.uTime.value = timeSec;
|
|
this.uniforms.uScale.value.set(w, d);
|
|
|
|
this.decal.scale.set(w, d, 1);
|
|
this.decal.position.set(cx, 0.02, cz);
|
|
|
|
this.wash.scale.set(w * 0.94, height, d * 0.94);
|
|
this.wash.position.set(cx, height / 2, cz);
|
|
}
|
|
}
|