wadi-mcp 0.1.38 → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/http.mjs +179 -87
  2. package/dist/server.mjs +179 -87
  3. package/package.json +1 -1
package/dist/http.mjs CHANGED
@@ -326144,7 +326144,7 @@ var require_detect_gpu_umd = __commonJS({
326144
326144
  function e3(e4) {
326145
326145
  var o2;
326146
326146
  return n4(this, void 0, void 0, function() {
326147
- var n5, a2, i5, c2, u2, l2, d3, v2, p2, g3, m2, b2, y2, x3, P2, A2, C25, L2, M2, k2, j2, B2, R2, T2, U2, I2;
326147
+ var n5, a2, i5, c2, u2, l2, d3, v2, p2, g3, m2, b2, y2, x3, P2, A2, C26, L2, M2, k2, j2, B2, R2, T2, U2, I2;
326148
326148
  return t(this, function(t2) {
326149
326149
  switch (t2.label) {
326150
326150
  case 0:
@@ -326172,7 +326172,7 @@ var require_detect_gpu_umd = __commonJS({
326172
326172
  return [e5, h(p2, e5[2])];
326173
326173
  }).sort(function(e5, r4) {
326174
326174
  return e5[1] - r4[1];
326175
- })[0][0] : d3[0], m2 = g3[0], b2 = g3[4], y2 = Number.MAX_VALUE, P2 = window.devicePixelRatio, A2 = S.width * P2 * S.height * P2, C25 = 0, L2 = b2; C25 < L2.length; C25++) M2 = L2[C25], k2 = M2[0], j2 = M2[1], B2 = k2 * j2, (R2 = Math.abs(A2 - B2)) < y2 && (y2 = R2, x3 = M2);
326175
+ })[0][0] : d3[0], m2 = g3[0], b2 = g3[4], y2 = Number.MAX_VALUE, P2 = window.devicePixelRatio, A2 = S.width * P2 * S.height * P2, C26 = 0, L2 = b2; C26 < L2.length; C26++) M2 = L2[C26], k2 = M2[0], j2 = M2[1], B2 = k2 * j2, (R2 = Math.abs(A2 - B2)) < y2 && (y2 = R2, x3 = M2);
326176
326176
  return x3 ? (U2 = (T2 = x3)[2], I2 = T2[3], [2, [y2, U2, m2, I2]]) : [2];
326177
326177
  }
326178
326178
  });
@@ -337816,15 +337816,15 @@ var require_index_cjs3 = __commonJS({
337816
337816
  }, [r2, z3]), S.createElement("primitive", M.default({ ref: d2, object: z3 }, u2));
337817
337817
  });
337818
337818
  var ft = S.forwardRef(({ children: e2, domElement: t2, onChange: r2, onMouseDown: n5, onMouseUp: o2, onObjectChange: i3, object: s2, makeDefault: l2, camera: u2, enabled: d2, axis: m2, mode: f3, translationSnap: p2, rotationSnap: h2, scaleSnap: x2, space: y2, size: v2, showX: g2, showY: w2, showZ: z3, ...b2 }, E2) => {
337819
- const C25 = a.useThree((e3) => e3.controls), P2 = a.useThree((e3) => e3.gl), R2 = a.useThree((e3) => e3.events), D2 = a.useThree((e3) => e3.camera), F2 = a.useThree((e3) => e3.invalidate), k2 = a.useThree((e3) => e3.get), _2 = a.useThree((e3) => e3.set), A2 = u2 || D2, L2 = t2 || R2.connected || P2.domElement, I2 = S.useMemo(() => new c.TransformControls(A2, L2), [A2, L2]), B2 = S.useRef(null);
337819
+ const C26 = a.useThree((e3) => e3.controls), P2 = a.useThree((e3) => e3.gl), R2 = a.useThree((e3) => e3.events), D2 = a.useThree((e3) => e3.camera), F2 = a.useThree((e3) => e3.invalidate), k2 = a.useThree((e3) => e3.get), _2 = a.useThree((e3) => e3.set), A2 = u2 || D2, L2 = t2 || R2.connected || P2.domElement, I2 = S.useMemo(() => new c.TransformControls(A2, L2), [A2, L2]), B2 = S.useRef(null);
337820
337820
  S.useLayoutEffect(() => (s2 ? I2.attach(s2 instanceof T.Object3D ? s2 : s2.current) : B2.current instanceof T.Object3D && I2.attach(B2.current), () => {
337821
337821
  I2.detach();
337822
337822
  }), [s2, e2, I2]), S.useEffect(() => {
337823
- if (C25) {
337824
- const e3 = (e4) => C25.enabled = !e4.value;
337823
+ if (C26) {
337824
+ const e3 = (e4) => C26.enabled = !e4.value;
337825
337825
  return I2.addEventListener("dragging-changed", e3), () => I2.removeEventListener("dragging-changed", e3);
337826
337826
  }
337827
- }, [I2, C25]);
337827
+ }, [I2, C26]);
337828
337828
  const U2 = S.useRef(void 0), V3 = S.useRef(void 0), O2 = S.useRef(void 0), N2 = S.useRef(void 0);
337829
337829
  return S.useLayoutEffect(() => {
337830
337830
  U2.current = r2;
@@ -337894,7 +337894,7 @@ var require_index_cjs3 = __commonJS({
337894
337894
  const e3 = { Box3: n4.Box3, MathUtils: { clamp: n4.MathUtils.clamp }, Matrix4: n4.Matrix4, Quaternion: n4.Quaternion, Raycaster: n4.Raycaster, Sphere: n4.Sphere, Spherical: n4.Spherical, Vector2: n4.Vector2, Vector3: n4.Vector3, Vector4: n4.Vector4 };
337895
337895
  b2.install({ THREE: e3 }), a.extend({ CameraControlsImpl: b2 });
337896
337896
  }, [b2]);
337897
- const E2 = a.useThree((e3) => e3.camera), C25 = a.useThree((e3) => e3.gl), T2 = a.useThree((e3) => e3.invalidate), R2 = a.useThree((e3) => e3.events), D2 = a.useThree((e3) => e3.setEvents), F2 = a.useThree((e3) => e3.set), k2 = a.useThree((e3) => e3.get), _2 = a.useThree((e3) => e3.performance), A2 = i3 || E2, L2 = s2 || R2.connected || C25.domElement, I2 = t.useMemo(() => new b2(A2), [b2, A2]);
337897
+ const E2 = a.useThree((e3) => e3.camera), C26 = a.useThree((e3) => e3.gl), T2 = a.useThree((e3) => e3.invalidate), R2 = a.useThree((e3) => e3.events), D2 = a.useThree((e3) => e3.setEvents), F2 = a.useThree((e3) => e3.set), k2 = a.useThree((e3) => e3.get), _2 = a.useThree((e3) => e3.performance), A2 = i3 || E2, L2 = s2 || R2.connected || C26.domElement, I2 = t.useMemo(() => new b2(A2), [b2, A2]);
337898
337898
  return a.useFrame((e3, t2) => {
337899
337899
  I2.update(t2);
337900
337900
  }, -1), t.useEffect(() => (I2.connect(L2), () => {
@@ -338210,7 +338210,7 @@ var require_index_cjs3 = __commonJS({
338210
338210
  for (const n5 in e3) r3[n5] = t2(e3[n5]);
338211
338211
  return r3;
338212
338212
  }
338213
- }, []), C25 = S.useCallback(() => {
338213
+ }, []), C26 = S.useCallback(() => {
338214
338214
  const e3 = {}, t2 = u2.current, r3 = p2.current;
338215
338215
  if (t2) {
338216
338216
  if (r3 && Array.isArray(t2.frames)) {
@@ -338261,12 +338261,12 @@ var require_index_cjs3 = __commonJS({
338261
338261
  }
338262
338262
  u2.current && u2.current.frames && (u2.current.frames = M2(u2.current.frames));
338263
338263
  } else if (t2) {
338264
- u2.current = e3, u2.current.frames = C25(), d2.current = Array.isArray(e3.frames) ? e3.frames.length : Object.keys(e3.frames).length;
338264
+ u2.current = e3, u2.current.frames = C26(), d2.current = Array.isArray(e3.frames) ? e3.frames.length : Object.keys(e3.frames).length;
338265
338265
  const { w: t3, h: n5 } = or(e3.frames).sourceSize;
338266
338266
  r3 = b2(t3, n5, 0.1);
338267
338267
  }
338268
338268
  x2(u2.current), "encoding" in t2 ? t2.encoding = 3001 : "colorSpace" in t2 && (t2.colorSpace = T.SRGBColorSpace), v2(t2), z3({ spriteTexture: t2, spriteData: u2.current, aspect: r3 });
338269
- }, [E2, i3, C25, b2, M2]), R2 = S.useCallback((e3, t2, r3) => {
338269
+ }, [E2, i3, C26, b2, M2]), R2 = S.useCallback((e3, t2, r3) => {
338270
338270
  const n5 = fetch(e3).then((e4) => e4.json()), a2 = new Promise((e4) => {
338271
338271
  g2.load(t2, e4);
338272
338272
  });
@@ -338539,7 +338539,7 @@ var require_index_cjs3 = __commonJS({
338539
338539
  });
338540
338540
  var Or = S.createContext(null);
338541
338541
  var Nr = new T.PlaneGeometry(1, 1);
338542
- var jr = S.forwardRef(({ startFrame: e2 = 0, endFrame: t2, fps: r2 = 30, frameName: n5 = "", textureDataURL: o2, textureImageURL: i3, loop: s2 = false, numberOfFrames: l2 = 1, autoPlay: c2 = true, animationNames: u2, onStart: d2, onEnd: m2, onLoopEnd: f3, onFrame: p2, play: h2, pause: x2 = false, flipX: y2 = false, alphaTest: v2 = 0, children: g2, asSprite: w2 = false, offset: z3, playBackwards: b2 = false, resetOnEnd: E2 = false, maxItems: C25 = 1, instanceItems: P2 = [[0, 0, 0]], spriteDataset: R2, canvasRenderingContext2DSettings: D2, roundFramePosition: F2 = false, meshProps: k2 = {}, ..._2 }, A2) => {
338542
+ var jr = S.forwardRef(({ startFrame: e2 = 0, endFrame: t2, fps: r2 = 30, frameName: n5 = "", textureDataURL: o2, textureImageURL: i3, loop: s2 = false, numberOfFrames: l2 = 1, autoPlay: c2 = true, animationNames: u2, onStart: d2, onEnd: m2, onLoopEnd: f3, onFrame: p2, play: h2, pause: x2 = false, flipX: y2 = false, alphaTest: v2 = 0, children: g2, asSprite: w2 = false, offset: z3, playBackwards: b2 = false, resetOnEnd: E2 = false, maxItems: C26 = 1, instanceItems: P2 = [[0, 0, 0]], spriteDataset: R2, canvasRenderingContext2DSettings: D2, roundFramePosition: F2 = false, meshProps: k2 = {}, ..._2 }, A2) => {
338543
338543
  const L2 = S.useRef(new T.Group()), I2 = S.useRef(null), B2 = S.useRef(null), U2 = S.useRef(null), V3 = S.useRef(window.performance.now()), O2 = S.useRef(e2), N2 = S.useRef(n5), j2 = r2 > 0 ? 1e3 / r2 : 0, [W2, G2] = S.useState(new T.Texture()), H2 = S.useRef(0), [$2, q2] = S.useState(new T.Vector3(1, 1, 1)), X2 = y2 ? -1 : 1, Z2 = S.useRef(x2), Y2 = S.useRef(z3), Q2 = S.useRef(false), { spriteObj: K2, loadJsonAndTexture: J2 } = sr(null, null, u2, l2, void 0, D2), te2 = S.useRef(n5), re2 = S.useCallback((e3, t3) => {
338544
338544
  if (null === t3) l2 && (H2.current = l2, b2 && (O2.current = l2 - 1), I2.current = t3);
338545
338545
  else {
@@ -338615,7 +338615,7 @@ var require_index_cjs3 = __commonJS({
338615
338615
  })(), null == p2 || p2({ currentFrameName: N2.current, currentFrame: O2.current })));
338616
338616
  }), S.createElement("group", M.default({}, _2, { ref: L2, scale: function(e3 = new T.Vector3(1, 1, 1), t3 = 1) {
338617
338617
  return "number" == typeof t3 ? e3.multiplyScalar(t3) : Array.isArray(t3) ? e3.multiply(new T.Vector3(...t3)) : t3 instanceof T.Vector3 ? e3.multiply(t3) : void 0;
338618
- }($2, _2.scale) }), S.createElement(Or.Provider, { value: ae2 }, w2 && S.createElement(ee, null, S.createElement("mesh", M.default({ ref: U2, scale: 1, geometry: Nr }, k2), S.createElement("meshBasicMaterial", { premultipliedAlpha: false, toneMapped: false, side: T.DoubleSide, ref: B2, map: W2, transparent: true, alphaTest: null != v2 ? v2 : 0 }))), !w2 && S.createElement(Ir, M.default({ geometry: Nr, limit: null != C25 ? C25 : 1 }, k2), S.createElement("meshBasicMaterial", { premultipliedAlpha: false, toneMapped: false, side: T.DoubleSide, ref: B2, map: W2, transparent: true, alphaTest: null != v2 ? v2 : 0 }), (null != P2 ? P2 : [0]).map((e3, t3) => S.createElement(Lr, M.default({ key: t3, ref: 1 === (null == P2 ? void 0 : P2.length) ? U2 : null, position: e3, scale: 1 }, k2)))), g2));
338618
+ }($2, _2.scale) }), S.createElement(Or.Provider, { value: ae2 }, w2 && S.createElement(ee, null, S.createElement("mesh", M.default({ ref: U2, scale: 1, geometry: Nr }, k2), S.createElement("meshBasicMaterial", { premultipliedAlpha: false, toneMapped: false, side: T.DoubleSide, ref: B2, map: W2, transparent: true, alphaTest: null != v2 ? v2 : 0 }))), !w2 && S.createElement(Ir, M.default({ geometry: Nr, limit: null != C26 ? C26 : 1 }, k2), S.createElement("meshBasicMaterial", { premultipliedAlpha: false, toneMapped: false, side: T.DoubleSide, ref: B2, map: W2, transparent: true, alphaTest: null != v2 ? v2 : 0 }), (null != P2 ? P2 : [0]).map((e3, t3) => S.createElement(Lr, M.default({ key: t3, ref: 1 === (null == P2 ? void 0 : P2.length) ? U2 : null, position: e3, scale: 1 }, k2)))), g2));
338619
338619
  });
338620
338620
  var Wr = S.forwardRef(({ children: e2, curve: t2 }, r2) => {
338621
338621
  const [n5] = S.useState(() => new T.Scene()), [o2, i3] = S.useState(), s2 = S.useRef(null);
@@ -338877,12 +338877,12 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
338877
338877
  a.extend({ MeshReflectorMaterialImpl: Yr });
338878
338878
  const y2 = a.useThree(({ gl: e3 }) => e3), v2 = a.useThree(({ camera: e3 }) => e3), g2 = a.useThree(({ scene: e3 }) => e3), w2 = (o2 = Array.isArray(o2) ? o2 : [o2, o2])[0] + o2[1] > 0, z3 = o2[0], b2 = o2[1], E2 = S.useRef(null);
338879
338879
  S.useImperativeHandle(x2, () => E2.current, []);
338880
- const [C25] = S.useState(() => new n4.Plane()), [T2] = S.useState(() => new n4.Vector3()), [P2] = S.useState(() => new n4.Vector3()), [R2] = S.useState(() => new n4.Vector3()), [D2] = S.useState(() => new n4.Matrix4()), [F2] = S.useState(() => new n4.Vector3(0, 0, -1)), [k2] = S.useState(() => new n4.Vector4()), [_2] = S.useState(() => new n4.Vector3()), [A2] = S.useState(() => new n4.Vector3()), [L2] = S.useState(() => new n4.Vector4()), [I2] = S.useState(() => new n4.Matrix4()), [B2] = S.useState(() => new n4.PerspectiveCamera()), U2 = S.useCallback(() => {
338880
+ const [C26] = S.useState(() => new n4.Plane()), [T2] = S.useState(() => new n4.Vector3()), [P2] = S.useState(() => new n4.Vector3()), [R2] = S.useState(() => new n4.Vector3()), [D2] = S.useState(() => new n4.Matrix4()), [F2] = S.useState(() => new n4.Vector3(0, 0, -1)), [k2] = S.useState(() => new n4.Vector4()), [_2] = S.useState(() => new n4.Vector3()), [A2] = S.useState(() => new n4.Vector3()), [L2] = S.useState(() => new n4.Vector4()), [I2] = S.useState(() => new n4.Matrix4()), [B2] = S.useState(() => new n4.PerspectiveCamera()), U2 = S.useCallback(() => {
338881
338881
  var e3;
338882
338882
  const t3 = E2.current.parent || (null == (e3 = E2.current) || null == (e3 = e3.__r3f.parent) ? void 0 : e3.object);
338883
338883
  if (!t3) return;
338884
338884
  if (P2.setFromMatrixPosition(t3.matrixWorld), R2.setFromMatrixPosition(v2.matrixWorld), D2.extractRotation(t3.matrixWorld), T2.set(0, 0, 1), T2.applyMatrix4(D2), P2.addScaledVector(T2, p2), _2.subVectors(P2, R2), _2.dot(T2) > 0) return;
338885
- _2.reflect(T2).negate(), _2.add(P2), D2.extractRotation(v2.matrixWorld), F2.set(0, 0, -1), F2.applyMatrix4(D2), F2.add(R2), A2.subVectors(P2, F2), A2.reflect(T2).negate(), A2.add(P2), B2.position.copy(_2), B2.up.set(0, 1, 0), B2.up.applyMatrix4(D2), B2.up.reflect(T2), B2.lookAt(A2), B2.far = v2.far, B2.updateMatrixWorld(), B2.projectionMatrix.copy(v2.projectionMatrix), I2.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1), I2.multiply(B2.projectionMatrix), I2.multiply(B2.matrixWorldInverse), I2.multiply(t3.matrixWorld), C25.setFromNormalAndCoplanarPoint(T2, P2), C25.applyMatrix4(B2.matrixWorldInverse), k2.set(C25.normal.x, C25.normal.y, C25.normal.z, C25.constant);
338885
+ _2.reflect(T2).negate(), _2.add(P2), D2.extractRotation(v2.matrixWorld), F2.set(0, 0, -1), F2.applyMatrix4(D2), F2.add(R2), A2.subVectors(P2, F2), A2.reflect(T2).negate(), A2.add(P2), B2.position.copy(_2), B2.up.set(0, 1, 0), B2.up.applyMatrix4(D2), B2.up.reflect(T2), B2.lookAt(A2), B2.far = v2.far, B2.updateMatrixWorld(), B2.projectionMatrix.copy(v2.projectionMatrix), I2.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1), I2.multiply(B2.projectionMatrix), I2.multiply(B2.matrixWorldInverse), I2.multiply(t3.matrixWorld), C26.setFromNormalAndCoplanarPoint(T2, P2), C26.applyMatrix4(B2.matrixWorldInverse), k2.set(C26.normal.x, C26.normal.y, C26.normal.z, C26.constant);
338886
338886
  const r3 = B2.projectionMatrix;
338887
338887
  L2.x = (Math.sign(k2.x) + r3.elements[8]) / r3.elements[0], L2.y = (Math.sign(k2.y) + r3.elements[9]) / r3.elements[5], L2.z = -1, L2.w = (1 + r3.elements[10]) / r3.elements[14], k2.multiplyScalar(2 / k2.dot(L2)), r3.elements[2] = k2.x, r3.elements[6] = k2.y, r3.elements[10] = k2.z + 1, r3.elements[14] = k2.w;
338888
338888
  }, [v2, p2]), [V3, O2, N2, j2] = S.useMemo(() => {
@@ -339075,10 +339075,10 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339075
339075
  var tn = S.forwardRef(({ buffer: e2, transmissionSampler: t2 = false, backside: r2 = false, side: n5 = T.FrontSide, transmission: o2 = 1, thickness: i3 = 0, backsideThickness: s2 = 0, backsideEnvMapIntensity: l2 = 1, samples: c2 = 10, resolution: u2, backsideResolution: d2, background: m2, anisotropy: f3, anisotropicBlur: p2, ...h2 }, x2) => {
339076
339076
  a.extend({ MeshTransmissionMaterial: en });
339077
339077
  const y2 = S.useRef(null), [v2] = S.useState(() => new Jr()), g2 = rt(d2 || u2), w2 = rt(u2);
339078
- let z3, b2, E2, C25;
339078
+ let z3, b2, E2, C26;
339079
339079
  return a.useFrame((e3) => {
339080
339080
  var a2;
339081
- (y2.current.time = e3.clock.elapsedTime, y2.current.buffer !== w2.texture || t2) || (C25 = null == (a2 = y2.current.__r3f.parent) ? void 0 : a2.object, C25 && (E2 = e3.gl.toneMapping, z3 = e3.scene.background, b2 = y2.current.envMapIntensity, e3.gl.toneMapping = T.NoToneMapping, m2 && (e3.scene.background = m2), C25.material = v2, r2 && (e3.gl.setRenderTarget(g2), e3.gl.render(e3.scene, e3.camera), C25.material = y2.current, C25.material.buffer = g2.texture, C25.material.thickness = s2, C25.material.side = T.BackSide, C25.material.envMapIntensity = l2), e3.gl.setRenderTarget(w2), e3.gl.render(e3.scene, e3.camera), C25.material = y2.current, C25.material.thickness = i3, C25.material.side = n5, C25.material.buffer = w2.texture, C25.material.envMapIntensity = b2, e3.scene.background = z3, e3.gl.setRenderTarget(null), e3.gl.toneMapping = E2));
339081
+ (y2.current.time = e3.clock.elapsedTime, y2.current.buffer !== w2.texture || t2) || (C26 = null == (a2 = y2.current.__r3f.parent) ? void 0 : a2.object, C26 && (E2 = e3.gl.toneMapping, z3 = e3.scene.background, b2 = y2.current.envMapIntensity, e3.gl.toneMapping = T.NoToneMapping, m2 && (e3.scene.background = m2), C26.material = v2, r2 && (e3.gl.setRenderTarget(g2), e3.gl.render(e3.scene, e3.camera), C26.material = y2.current, C26.material.buffer = g2.texture, C26.material.thickness = s2, C26.material.side = T.BackSide, C26.material.envMapIntensity = l2), e3.gl.setRenderTarget(w2), e3.gl.render(e3.scene, e3.camera), C26.material = y2.current, C26.material.thickness = i3, C26.material.side = n5, C26.material.buffer = w2.texture, C26.material.envMapIntensity = b2, e3.scene.background = z3, e3.gl.setRenderTarget(null), e3.gl.toneMapping = E2));
339082
339082
  }), S.useImperativeHandle(x2, () => y2.current, []), S.createElement("meshTransmissionMaterial", M.default({ args: [c2, t2], ref: y2 }, h2, { buffer: e2 || w2.texture, _transmission: o2, anisotropicBlur: null != p2 ? p2 : f3, transmission: t2 ? o2 : 0, thickness: i3, side: n5 }));
339083
339083
  });
339084
339084
  var rn = S.forwardRef((e2, t2) => (a.extend({ DiscardMaterialImpl: Jr }), S.createElement("discardMaterialImpl", M.default({ ref: t2 }, e2))));
@@ -339387,11 +339387,11 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339387
339387
  }
339388
339388
  return Kn(l2, h2, z3, M2.texture, { backgroundBlurriness: null != c2 ? c2 : u2, backgroundIntensity: d2, backgroundRotation: m2, environmentIntensity: f3, environmentRotation: p2 });
339389
339389
  }, [e2, E2, M2.texture, h2, z3, l2, i3, w2]);
339390
- let C25 = 1;
339390
+ let C26 = 1;
339391
339391
  return a.useFrame(() => {
339392
- if (i3 === 1 / 0 || C25 < i3) {
339392
+ if (i3 === 1 / 0 || C26 < i3) {
339393
339393
  const e3 = w2.autoClear;
339394
- w2.autoClear = true, b2.current.update(w2, E2), w2.autoClear = e3, C25++;
339394
+ w2.autoClear = true, b2.current.update(w2, E2), w2.autoClear = e3, C26++;
339395
339395
  }
339396
339396
  }), S.createElement(S.Fragment, null, a.createPortal(S.createElement(S.Fragment, null, e2, S.createElement("cubeCamera", { ref: b2, args: [t2, r2, M2] }), x2 || v2 ? S.createElement(ea, { background: true, files: x2, preset: v2, path: y2, extensions: g2 }) : s2 ? S.createElement(Jn, { background: true, map: s2, extensions: g2 }) : null), E2));
339397
339397
  }
@@ -339410,7 +339410,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339410
339410
  var aa = S.forwardRef(({ scale: e2 = 10, frames: t2 = 1 / 0, opacity: r2 = 1, width: n5 = 1, height: o2 = 1, blur: i3 = 1, near: s2 = 0, far: l2 = 10, resolution: u2 = 512, smooth: d2 = true, color: m2 = "#000000", depthWrite: f3 = false, renderOrder: p2, ...h2 }, x2) => {
339411
339411
  const y2 = S.useRef(null), v2 = a.useThree((e3) => e3.scene), g2 = a.useThree((e3) => e3.gl), w2 = S.useRef(null);
339412
339412
  n5 *= Array.isArray(e2) ? e2[0] : e2 || 1, o2 *= Array.isArray(e2) ? e2[1] : e2 || 1;
339413
- const [z3, b2, E2, C25, P2, R2, D2] = S.useMemo(() => {
339413
+ const [z3, b2, E2, C26, P2, R2, D2] = S.useMemo(() => {
339414
339414
  const e3 = new T.WebGLRenderTarget(u2, u2), t3 = new T.WebGLRenderTarget(u2, u2);
339415
339415
  t3.texture.generateMipmaps = e3.texture.generateMipmaps = false;
339416
339416
  const r3 = new T.PlaneGeometry(n5, o2).rotateX(Math.PI / 2), a2 = new T.Mesh(r3), i4 = new T.MeshDepthMaterial();
@@ -339420,7 +339420,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339420
339420
  const s3 = new T.ShaderMaterial(c.HorizontalBlurShader), l3 = new T.ShaderMaterial(c.VerticalBlurShader);
339421
339421
  return l3.depthTest = s3.depthTest = false, [e3, r3, i4, a2, s3, l3, t3];
339422
339422
  }, [u2, n5, o2, e2, m2]), F2 = (e3) => {
339423
- C25.visible = true, C25.material = P2, P2.uniforms.tDiffuse.value = z3.texture, P2.uniforms.h.value = 1 * e3 / 256, g2.setRenderTarget(D2), g2.render(C25, w2.current), C25.material = R2, R2.uniforms.tDiffuse.value = D2.texture, R2.uniforms.v.value = 1 * e3 / 256, g2.setRenderTarget(z3), g2.render(C25, w2.current), C25.visible = false;
339423
+ C26.visible = true, C26.material = P2, P2.uniforms.tDiffuse.value = z3.texture, P2.uniforms.h.value = 1 * e3 / 256, g2.setRenderTarget(D2), g2.render(C26, w2.current), C26.material = R2, R2.uniforms.tDiffuse.value = D2.texture, R2.uniforms.v.value = 1 * e3 / 256, g2.setRenderTarget(z3), g2.render(C26, w2.current), C26.visible = false;
339424
339424
  };
339425
339425
  let k2, _2, A2 = 0;
339426
339426
  return a.useFrame(() => {
@@ -339560,7 +339560,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339560
339560
  var va = { minFilter: T.LinearMipmapLinearFilter, magFilter: T.LinearFilter, type: T.FloatType, generateMipmaps: true };
339561
339561
  var ga = S.forwardRef(({ debug: e2, children: t2, frames: r2 = 1, ior: n5 = 1.1, color: o2 = "white", causticsOnly: i3 = false, backside: s2 = false, backsideIOR: l2 = 1.1, worldRadius: u2 = 0.3125, intensity: d2 = 0.05, resolution: m2 = 2024, lightSource: f3 = [5, 5, 5], ...p2 }, h2) => {
339562
339562
  a.extend({ CausticsProjectionMaterial: ha });
339563
- const x2 = S.useRef(null), y2 = S.useRef(null), v2 = S.useRef(null), g2 = S.useRef(null), w2 = a.useThree((e3) => e3.gl), z3 = lr(e2 && y2, T.CameraHelper), b2 = rt(m2, m2, ya), E2 = rt(m2, m2, ya), C25 = rt(m2, m2, va), P2 = rt(m2, m2, va), [R2] = S.useState(() => pa()), [D2] = S.useState(() => pa(T.BackSide)), [F2] = S.useState(() => new xa()), [k2] = S.useState(() => new c.FullScreenQuad(F2));
339563
+ const x2 = S.useRef(null), y2 = S.useRef(null), v2 = S.useRef(null), g2 = S.useRef(null), w2 = a.useThree((e3) => e3.gl), z3 = lr(e2 && y2, T.CameraHelper), b2 = rt(m2, m2, ya), E2 = rt(m2, m2, ya), C26 = rt(m2, m2, va), P2 = rt(m2, m2, va), [R2] = S.useState(() => pa()), [D2] = S.useState(() => pa(T.BackSide)), [F2] = S.useState(() => new xa()), [k2] = S.useState(() => new c.FullScreenQuad(F2));
339564
339564
  S.useLayoutEffect(() => {
339565
339565
  x2.current.updateWorldMatrix(false, true);
339566
339566
  });
@@ -339584,9 +339584,9 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339584
339584
  const T2 = W2.map((e3, t4) => e3.add(H2[t4].copy(U2).multiplyScalar(-e3.y / U2.y))), _3 = T2.reduce((e3, t4) => e3.add(t4), A2.set(0, 0, 0)).divideScalar(T2.length), q2 = 2 * T2.map((e3) => Math.hypot(e3.x - _3.x, e3.z - _3.z)).reduce((e3, t4) => Math.max(e3, t4));
339585
339585
  g2.current.scale.setScalar(q2), g2.current.position.copy(_3), e2 && (null == (a2 = z3.current) || a2.update()), D2.viewMatrix.value = R2.viewMatrix.value = y2.current.matrixWorldInverse;
339586
339586
  const X2 = L2.setFromProjectionMatrix(I2.multiplyMatrices(y2.current.projectionMatrix, y2.current.matrixWorldInverse)).planes[4];
339587
- F2.cameraMatrixWorld = y2.current.matrixWorld, F2.cameraProjectionMatrixInv = y2.current.projectionMatrixInverse, F2.lightDir = V3, F2.lightPlaneNormal = X2.normal, F2.lightPlaneConstant = X2.constant, F2.near = y2.current.near, F2.far = y2.current.far, F2.resolution = m2, F2.size = c2, F2.intensity = d2, F2.worldRadius = u2, v2.current.visible = true, w2.setRenderTarget(b2), w2.clear(), v2.current.overrideMaterial = R2, w2.render(v2.current, y2.current), w2.setRenderTarget(E2), w2.clear(), s2 && (v2.current.overrideMaterial = D2, w2.render(v2.current, y2.current)), v2.current.overrideMaterial = null, F2.ior = n5, g2.current.material.lightProjMatrix = y2.current.projectionMatrix, g2.current.material.lightViewMatrix = y2.current.matrixWorldInverse, F2.normalTexture = b2.texture, F2.depthTexture = b2.depthTexture, w2.setRenderTarget(C25), w2.clear(), k2.render(w2), F2.ior = l2, F2.normalTexture = E2.texture, F2.depthTexture = E2.depthTexture, w2.setRenderTarget(P2), w2.clear(), s2 && k2.render(w2), w2.setRenderTarget(null), i3 && (v2.current.visible = false);
339587
+ F2.cameraMatrixWorld = y2.current.matrixWorld, F2.cameraProjectionMatrixInv = y2.current.projectionMatrixInverse, F2.lightDir = V3, F2.lightPlaneNormal = X2.normal, F2.lightPlaneConstant = X2.constant, F2.near = y2.current.near, F2.far = y2.current.far, F2.resolution = m2, F2.size = c2, F2.intensity = d2, F2.worldRadius = u2, v2.current.visible = true, w2.setRenderTarget(b2), w2.clear(), v2.current.overrideMaterial = R2, w2.render(v2.current, y2.current), w2.setRenderTarget(E2), w2.clear(), s2 && (v2.current.overrideMaterial = D2, w2.render(v2.current, y2.current)), v2.current.overrideMaterial = null, F2.ior = n5, g2.current.material.lightProjMatrix = y2.current.projectionMatrix, g2.current.material.lightViewMatrix = y2.current.matrixWorldInverse, F2.normalTexture = b2.texture, F2.depthTexture = b2.depthTexture, w2.setRenderTarget(C26), w2.clear(), k2.render(w2), F2.ior = l2, F2.normalTexture = E2.texture, F2.depthTexture = E2.depthTexture, w2.setRenderTarget(P2), w2.clear(), s2 && k2.render(w2), w2.setRenderTarget(null), i3 && (v2.current.visible = false);
339588
339588
  }
339589
- }), S.useImperativeHandle(h2, () => x2.current, []), S.createElement("group", M.default({ ref: x2 }, p2), S.createElement("scene", { ref: v2 }, S.createElement("orthographicCamera", { ref: y2, up: [0, 1, 0] }), t2), S.createElement("mesh", { renderOrder: 2, ref: g2, "rotation-x": -Math.PI / 2 }, S.createElement("planeGeometry", null), S.createElement("causticsProjectionMaterial", { transparent: true, color: o2, causticsTexture: C25.texture, causticsTextureB: P2.texture, blending: T.CustomBlending, blendSrc: T.OneFactor, blendDst: T.SrcAlphaFactor, depthWrite: false }), e2 && S.createElement(ke, null, S.createElement("lineBasicMaterial", { color: "#ffff00", toneMapped: false }))));
339589
+ }), S.useImperativeHandle(h2, () => x2.current, []), S.createElement("group", M.default({ ref: x2 }, p2), S.createElement("scene", { ref: v2 }, S.createElement("orthographicCamera", { ref: y2, up: [0, 1, 0] }), t2), S.createElement("mesh", { renderOrder: 2, ref: g2, "rotation-x": -Math.PI / 2 }, S.createElement("planeGeometry", null), S.createElement("causticsProjectionMaterial", { transparent: true, color: o2, causticsTexture: C26.texture, causticsTextureB: P2.texture, blending: T.CustomBlending, blendSrc: T.OneFactor, blendDst: T.SrcAlphaFactor, depthWrite: false }), e2 && S.createElement(ke, null, S.createElement("lineBasicMaterial", { color: "#ffff00", toneMapped: false }))));
339590
339590
  });
339591
339591
  var wa = class extends T.ShaderMaterial {
339592
339592
  constructor() {
@@ -339768,9 +339768,9 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
339768
339768
  const e3 = Math.min(i3, void 0 !== o2 ? o2 : i3, p2.current.length);
339769
339769
  f3.current.count = e3, br(f3.current.instanceMatrix, { start: 0, count: 16 * e3 }), f3.current.instanceColor && br(f3.current.instanceColor, { start: 0, count: 3 * e3 }), br(f3.current.geometry.attributes.cloudOpacity, { start: 0, count: e3 });
339770
339770
  });
339771
- let C25 = [null !== (u2 = y2.image.width) && void 0 !== u2 ? u2 : 1, null !== (d2 = y2.image.height) && void 0 !== d2 ? d2 : 1];
339772
- const T2 = Math.max(C25[0], C25[1]);
339773
- return C25 = [C25[0] / T2, C25[1] / T2], S.createElement("group", M.default({ ref: c2 }, l2), S.createElement(Ua.Provider, { value: p2 }, e2, S.createElement("instancedMesh", { matrixAutoUpdate: false, ref: f3, args: [null, null, i3], frustumCulled: s2 }, S.createElement("instancedBufferAttribute", { usage: n4.DynamicDrawUsage, attach: "instanceColor", args: [x2, 3] }), S.createElement("planeGeometry", { args: [...C25] }, S.createElement("instancedBufferAttribute", { usage: n4.DynamicDrawUsage, attach: "attributes-cloudOpacity", args: [h2, 1] })), S.createElement("cloudMaterial", { key: t2.name, map: y2, transparent: true, depthWrite: false }))));
339771
+ let C26 = [null !== (u2 = y2.image.width) && void 0 !== u2 ? u2 : 1, null !== (d2 = y2.image.height) && void 0 !== d2 ? d2 : 1];
339772
+ const T2 = Math.max(C26[0], C26[1]);
339773
+ return C26 = [C26[0] / T2, C26[1] / T2], S.createElement("group", M.default({ ref: c2 }, l2), S.createElement(Ua.Provider, { value: p2 }, e2, S.createElement("instancedMesh", { matrixAutoUpdate: false, ref: f3, args: [null, null, i3], frustumCulled: s2 }, S.createElement("instancedBufferAttribute", { usage: n4.DynamicDrawUsage, attach: "instanceColor", args: [x2, 3] }), S.createElement("planeGeometry", { args: [...C26] }, S.createElement("instancedBufferAttribute", { usage: n4.DynamicDrawUsage, attach: "attributes-cloudOpacity", args: [h2, 1] })), S.createElement("cloudMaterial", { key: t2.name, map: y2, transparent: true, depthWrite: false }))));
339774
339774
  });
339775
339775
  var Oa = S.forwardRef(({ opacity: e2 = 1, speed: t2 = 0, bounds: r2 = [5, 1, 1], segments: o2 = 20, color: i3 = "#ffffff", fade: s2 = 10, volume: l2 = 6, smallestVolume: c2 = 0.25, distribute: u2 = null, growth: d2 = 4, concentrate: m2 = "inside", seed: f3 = Math.random(), ...p2 }, h2) => {
339776
339776
  function x2() {
@@ -340123,13 +340123,13 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340123
340123
  }, t2), S.createElement(S.Fragment, null, r2);
340124
340124
  }
340125
340125
  var ko = S.forwardRef(({ children: e2, compute: t2, renderPriority: r2 = -1, eventPriority: n5 = 0, frames: o2 = 1 / 0, stencilBuffer: i3 = false, depthBuffer: s2 = true, generateMipmaps: l2 = false, resolution: c2 = 896, near: u2 = 0.1, far: d2 = 1e3, flip: m2 = false, position: f3, rotation: p2, scale: h2, quaternion: x2, matrix: y2, matrixAutoUpdate: v2, ...g2 }, w2) => {
340126
- const { size: z3, viewport: b2 } = a.useThree(), E2 = S.useRef(null), C25 = S.useMemo(() => {
340126
+ const { size: z3, viewport: b2 } = a.useThree(), E2 = S.useRef(null), C26 = S.useMemo(() => {
340127
340127
  const e3 = new T.WebGLCubeRenderTarget(Math.max((c2 || z3.width) * b2.dpr, (c2 || z3.height) * b2.dpr), { stencilBuffer: i3, depthBuffer: s2, generateMipmaps: l2 });
340128
340128
  return e3.texture.isRenderTargetTexture = !m2, e3.texture.flipY = true, e3.texture.type = T.HalfFloatType, e3;
340129
340129
  }, [c2, m2]);
340130
- S.useEffect(() => () => C25.dispose(), [C25]);
340130
+ S.useEffect(() => () => C26.dispose(), [C26]);
340131
340131
  const [P2] = S.useState(() => new T.Scene());
340132
- return S.useImperativeHandle(w2, () => ({ scene: P2, fbo: C25, camera: E2.current }), [C25]), S.createElement(S.Fragment, null, a.createPortal(S.createElement(_o, { renderPriority: r2, frames: o2, camera: E2 }, e2, S.createElement("group", { onPointerOver: () => null })), P2, { events: { compute: t2, priority: n5 } }), S.createElement("primitive", M.default({ object: C25.texture }, g2)), S.createElement("cubeCamera", { ref: E2, args: [u2, d2, C25], position: f3, rotation: p2, scale: h2, quaternion: x2, matrix: y2, matrixAutoUpdate: v2 }));
340132
+ return S.useImperativeHandle(w2, () => ({ scene: P2, fbo: C26, camera: E2.current }), [C26]), S.createElement(S.Fragment, null, a.createPortal(S.createElement(_o, { renderPriority: r2, frames: o2, camera: E2 }, e2, S.createElement("group", { onPointerOver: () => null })), P2, { events: { compute: t2, priority: n5 } }), S.createElement("primitive", M.default({ object: C26.texture }, g2)), S.createElement("cubeCamera", { ref: E2, args: [u2, d2, C26], position: f3, rotation: p2, scale: h2, quaternion: x2, matrix: y2, matrixAutoUpdate: v2 }));
340133
340133
  });
340134
340134
  function _o({ frames: e2, renderPriority: t2, children: r2, camera: n5 }) {
340135
340135
  let o2 = 0;
@@ -340354,12 +340354,12 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340354
340354
  var Jo = new T.Vector3(0, 1, 0);
340355
340355
  var ei = new T.Matrix4();
340356
340356
  var ti = ({ direction: e2, axis: t2 }) => {
340357
- const { translation: r2, translationLimits: n5, annotations: o2, annotationsClass: i3, depthTest: s2, scale: l2, lineWidth: c2, fixed: u2, axisColors: d2, hoveredColor: m2, opacity: f3, renderOrder: p2, onDragStart: h2, onDrag: x2, onDragEnd: y2, userData: v2 } = S.useContext(Yo), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(0), [M2, C25] = S.useState(false), P2 = S.useCallback((n6) => {
340357
+ const { translation: r2, translationLimits: n5, annotations: o2, annotationsClass: i3, depthTest: s2, scale: l2, lineWidth: c2, fixed: u2, axisColors: d2, hoveredColor: m2, opacity: f3, renderOrder: p2, onDragStart: h2, onDrag: x2, onDragEnd: y2, userData: v2 } = S.useContext(Yo), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(0), [M2, C26] = S.useState(false), P2 = S.useCallback((n6) => {
340358
340358
  o2 && (w2.current.innerText = `${r2.current[t2].toFixed(2)}`, w2.current.style.display = "block"), n6.stopPropagation();
340359
340359
  const a2 = new T.Matrix4().extractRotation(z3.current.matrixWorld), i4 = n6.point.clone(), s3 = new T.Vector3().setFromMatrixPosition(z3.current.matrixWorld), l3 = e2.clone().applyMatrix4(a2).normalize();
340360
340360
  b2.current = { clickPoint: i4, dir: l3 }, E2.current = r2.current[t2], h2({ component: "Arrow", axis: t2, origin: s3, directions: [l3] }), g2 && (g2.enabled = false), n6.target.setPointerCapture(n6.pointerId);
340361
340361
  }, [o2, e2, g2, h2, r2, t2]), R2 = S.useCallback((e3) => {
340362
- if (e3.stopPropagation(), M2 || C25(true), b2.current) {
340362
+ if (e3.stopPropagation(), M2 || C26(true), b2.current) {
340363
340363
  const { clickPoint: a2, dir: i4 } = b2.current, [s3, l3] = (null == n5 ? void 0 : n5[t2]) || [void 0, void 0];
340364
340364
  let c3 = ((e4, t3, r3, n6) => {
340365
340365
  const a3 = t3.dot(t3), o3 = t3.dot(e4) - t3.dot(r3), i5 = t3.dot(n6);
@@ -340370,7 +340370,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340370
340370
  }, [o2, x2, M2, r2, n5, t2]), D2 = S.useCallback((e3) => {
340371
340371
  o2 && (w2.current.style.display = "none"), e3.stopPropagation(), b2.current = null, y2(), g2 && (g2.enabled = true), e3.target.releasePointerCapture(e3.pointerId);
340372
340372
  }, [o2, g2, y2]), F2 = S.useCallback((e3) => {
340373
- e3.stopPropagation(), C25(false);
340373
+ e3.stopPropagation(), C26(false);
340374
340374
  }, []), { cylinderLength: k2, coneWidth: _2, coneLength: A2, matrixL: L2 } = S.useMemo(() => {
340375
340375
  const t3 = u2 ? c2 / l2 * 1.6 : l2 / 20, r3 = u2 ? 0.2 : l2 / 5, n6 = u2 ? 1 - r3 : l2 - r3, a2 = new T.Quaternion().setFromUnitVectors(Jo, e2.clone().normalize());
340376
340376
  return { cylinderLength: n6, coneWidth: t3, coneLength: r3, matrixL: new T.Matrix4().makeRotationFromQuaternion(a2) };
@@ -340392,12 +340392,12 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340392
340392
  var li = new T.Ray();
340393
340393
  var ci = new T.Vector3();
340394
340394
  var ui = ({ dir1: e2, dir2: t2, axis: r2 }) => {
340395
- const { rotationLimits: n5, annotations: o2, annotationsClass: i3, depthTest: s2, scale: l2, lineWidth: c2, fixed: u2, axisColors: d2, hoveredColor: m2, renderOrder: f3, opacity: p2, onDragStart: h2, onDrag: x2, onDragEnd: y2, userData: v2 } = S.useContext(Yo), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(0), E2 = S.useRef(0), M2 = S.useRef(null), [C25, P2] = S.useState(false), R2 = S.useCallback((e3) => {
340395
+ const { rotationLimits: n5, annotations: o2, annotationsClass: i3, depthTest: s2, scale: l2, lineWidth: c2, fixed: u2, axisColors: d2, hoveredColor: m2, renderOrder: f3, opacity: p2, onDragStart: h2, onDrag: x2, onDragEnd: y2, userData: v2 } = S.useContext(Yo), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(0), E2 = S.useRef(0), M2 = S.useRef(null), [C26, P2] = S.useState(false), R2 = S.useCallback((e3) => {
340396
340396
  o2 && (w2.current.innerText = `${ai(E2.current).toFixed(0)}\xBA`, w2.current.style.display = "block"), e3.stopPropagation();
340397
340397
  const t3 = e3.point.clone(), n6 = new T.Vector3().setFromMatrixPosition(z3.current.matrixWorld), a2 = new T.Vector3().setFromMatrixColumn(z3.current.matrixWorld, 0).normalize(), i4 = new T.Vector3().setFromMatrixColumn(z3.current.matrixWorld, 1).normalize(), s3 = new T.Vector3().setFromMatrixColumn(z3.current.matrixWorld, 2).normalize(), l3 = new T.Plane().setFromNormalAndCoplanarPoint(s3, n6);
340398
340398
  M2.current = { clickPoint: t3, origin: n6, e1: a2, e2: i4, normal: s3, plane: l3 }, h2({ component: "Rotator", axis: r2, origin: n6, directions: [a2, i4, s3] }), g2 && (g2.enabled = false), e3.target.setPointerCapture(e3.pointerId);
340399
340399
  }, [o2, g2, h2, r2]), D2 = S.useCallback((e3) => {
340400
- if (e3.stopPropagation(), C25 || P2(true), M2.current) {
340400
+ if (e3.stopPropagation(), C26 || P2(true), M2.current) {
340401
340401
  const { clickPoint: t3, origin: a2, e1: i4, e2: s3, normal: l3, plane: c3 } = M2.current, [u3, d3] = (null == n5 ? void 0 : n5[r2]) || [void 0, void 0];
340402
340402
  li.copy(e3.ray), li.intersectPlane(c3, ci), li.direction.negate(), li.intersectPlane(c3, ci);
340403
340403
  let m3 = ((e4, t4, r3, n6, a3) => {
@@ -340407,7 +340407,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340407
340407
  })(t3, ci, a2, i4, s3), f4 = ai(m3);
340408
340408
  e3.shiftKey && (f4 = 10 * Math.round(f4 / 10), m3 = ((e4) => e4 * Math.PI / 180)(f4)), void 0 !== u3 && void 0 !== d3 && d3 - u3 < 2 * Math.PI ? (m3 = oi(m3), m3 = m3 > Math.PI ? m3 - 2 * Math.PI : m3, m3 = T.MathUtils.clamp(m3, u3 - b2.current, d3 - b2.current), E2.current = b2.current + m3) : (E2.current = oi(b2.current + m3), E2.current = E2.current > Math.PI ? E2.current - 2 * Math.PI : E2.current), o2 && (f4 = ai(E2.current), w2.current.innerText = `${f4.toFixed(0)}\xBA`), ii.makeRotationAxis(l3, m3), si.copy(a2).applyMatrix4(ii).sub(a2).negate(), ii.setPosition(si), x2(ii);
340409
340409
  }
340410
- }, [o2, x2, C25, n5, r2]), F2 = S.useCallback((e3) => {
340410
+ }, [o2, x2, C26, n5, r2]), F2 = S.useCallback((e3) => {
340411
340411
  o2 && (w2.current.style.display = "none"), e3.stopPropagation(), b2.current = E2.current, M2.current = null, y2(), g2 && (g2.enabled = true), e3.target.releasePointerCapture(e3.pointerId);
340412
340412
  }, [o2, g2, y2]), k2 = S.useCallback((e3) => {
340413
340413
  e3.stopPropagation(), P2(false);
@@ -340422,16 +340422,16 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340422
340422
  }
340423
340423
  return e3;
340424
340424
  }, [A2]);
340425
- return S.createElement("group", { ref: z3, onPointerDown: R2, onPointerMove: D2, onPointerUp: F2, onPointerOut: k2, matrix: _2, matrixAutoUpdate: false }, o2 && S.createElement(j, { position: [A2, A2, 0] }, S.createElement("div", { style: { display: "none", background: "#151520", color: "white", padding: "6px 8px", borderRadius: 7, whiteSpace: "nowrap" }, className: i3, ref: w2 })), S.createElement(ce, { points: L2, lineWidth: 4 * c2, visible: false, userData: v2 }), S.createElement(ce, { transparent: true, raycast: () => null, depthTest: s2, points: L2, lineWidth: c2, side: T.DoubleSide, color: C25 ? m2 : d2[r2], opacity: p2, polygonOffset: true, polygonOffsetFactor: -10, renderOrder: f3, fog: false }));
340425
+ return S.createElement("group", { ref: z3, onPointerDown: R2, onPointerMove: D2, onPointerUp: F2, onPointerOut: k2, matrix: _2, matrixAutoUpdate: false }, o2 && S.createElement(j, { position: [A2, A2, 0] }, S.createElement("div", { style: { display: "none", background: "#151520", color: "white", padding: "6px 8px", borderRadius: 7, whiteSpace: "nowrap" }, className: i3, ref: w2 })), S.createElement(ce, { points: L2, lineWidth: 4 * c2, visible: false, userData: v2 }), S.createElement(ce, { transparent: true, raycast: () => null, depthTest: s2, points: L2, lineWidth: c2, side: T.DoubleSide, color: C26 ? m2 : d2[r2], opacity: p2, polygonOffset: true, polygonOffsetFactor: -10, renderOrder: f3, fog: false }));
340426
340426
  };
340427
340427
  var di = new T.Ray();
340428
340428
  var mi = new T.Vector3();
340429
340429
  var fi = new T.Matrix4();
340430
340430
  var pi = ({ dir1: e2, dir2: t2, axis: r2 }) => {
340431
- const { translation: n5, translationLimits: o2, annotations: i3, annotationsClass: s2, depthTest: l2, scale: c2, lineWidth: u2, fixed: d2, axisColors: m2, hoveredColor: f3, opacity: p2, renderOrder: h2, onDragStart: x2, onDrag: y2, onDragEnd: v2, userData: g2 } = S.useContext(Yo), w2 = a.useThree((e3) => e3.controls), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(null), M2 = S.useRef(0), C25 = S.useRef(0), [P2, R2] = S.useState(false), D2 = S.useCallback((e3) => {
340431
+ const { translation: n5, translationLimits: o2, annotations: i3, annotationsClass: s2, depthTest: l2, scale: c2, lineWidth: u2, fixed: d2, axisColors: m2, hoveredColor: f3, opacity: p2, renderOrder: h2, onDragStart: x2, onDrag: y2, onDragEnd: v2, userData: g2 } = S.useContext(Yo), w2 = a.useThree((e3) => e3.controls), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(null), M2 = S.useRef(0), C26 = S.useRef(0), [P2, R2] = S.useState(false), D2 = S.useCallback((e3) => {
340432
340432
  i3 && (z3.current.innerText = `${n5.current[(r2 + 1) % 3].toFixed(2)}, ${n5.current[(r2 + 2) % 3].toFixed(2)}`, z3.current.style.display = "block"), e3.stopPropagation();
340433
340433
  const t3 = e3.point.clone(), a2 = new T.Vector3().setFromMatrixPosition(b2.current.matrixWorld), o3 = new T.Vector3().setFromMatrixColumn(b2.current.matrixWorld, 0).normalize(), s3 = new T.Vector3().setFromMatrixColumn(b2.current.matrixWorld, 1).normalize(), l3 = new T.Vector3().setFromMatrixColumn(b2.current.matrixWorld, 2).normalize(), c3 = new T.Plane().setFromNormalAndCoplanarPoint(l3, a2);
340434
- E2.current = { clickPoint: t3, e1: o3, e2: s3, plane: c3 }, M2.current = n5.current[(r2 + 1) % 3], C25.current = n5.current[(r2 + 2) % 3], x2({ component: "Slider", axis: r2, origin: a2, directions: [o3, s3, l3] }), w2 && (w2.enabled = false), e3.target.setPointerCapture(e3.pointerId);
340434
+ E2.current = { clickPoint: t3, e1: o3, e2: s3, plane: c3 }, M2.current = n5.current[(r2 + 1) % 3], C26.current = n5.current[(r2 + 2) % 3], x2({ component: "Slider", axis: r2, origin: a2, directions: [o3, s3, l3] }), w2 && (w2.enabled = false), e3.target.setPointerCapture(e3.pointerId);
340435
340435
  }, [i3, w2, x2, r2]), F2 = S.useCallback((e3) => {
340436
340436
  if (e3.stopPropagation(), P2 || R2(true), E2.current) {
340437
340437
  const { clickPoint: t3, e1: a2, e2: s3, plane: l3 } = E2.current, [c3, u3] = (null == o2 ? void 0 : o2[(r2 + 1) % 3]) || [void 0, void 0], [d3, m3] = (null == o2 ? void 0 : o2[(r2 + 2) % 3]) || [void 0, void 0];
@@ -340440,7 +340440,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340440
340440
  const n6 = Math.abs(e4.x) >= Math.abs(e4.y) && Math.abs(e4.x) >= Math.abs(e4.z) ? 0 : Math.abs(e4.y) >= Math.abs(e4.x) && Math.abs(e4.y) >= Math.abs(e4.z) ? 1 : 2, a3 = [0, 1, 2].sort((e5, r4) => Math.abs(t4.getComponent(r4)) - Math.abs(t4.getComponent(e5))), o3 = n6 === a3[0] ? a3[1] : a3[0], i4 = e4.getComponent(n6), s4 = e4.getComponent(o3), l4 = t4.getComponent(n6), c4 = t4.getComponent(o3), u4 = r3.getComponent(n6), d4 = (r3.getComponent(o3) - u4 * (s4 / i4)) / (c4 - l4 * (s4 / i4));
340441
340441
  return [(u4 - d4 * l4) / i4, d4];
340442
340442
  })(a2, s3, mi);
340443
- void 0 !== c3 && (f4 = Math.max(f4, c3 - M2.current)), void 0 !== u3 && (f4 = Math.min(f4, u3 - M2.current)), void 0 !== d3 && (p3 = Math.max(p3, d3 - C25.current)), void 0 !== m3 && (p3 = Math.min(p3, m3 - C25.current)), n5.current[(r2 + 1) % 3] = M2.current + f4, n5.current[(r2 + 2) % 3] = C25.current + p3, i3 && (z3.current.innerText = `${n5.current[(r2 + 1) % 3].toFixed(2)}, ${n5.current[(r2 + 2) % 3].toFixed(2)}`), fi.makeTranslation(f4 * a2.x + p3 * s3.x, f4 * a2.y + p3 * s3.y, f4 * a2.z + p3 * s3.z), y2(fi);
340443
+ void 0 !== c3 && (f4 = Math.max(f4, c3 - M2.current)), void 0 !== u3 && (f4 = Math.min(f4, u3 - M2.current)), void 0 !== d3 && (p3 = Math.max(p3, d3 - C26.current)), void 0 !== m3 && (p3 = Math.min(p3, m3 - C26.current)), n5.current[(r2 + 1) % 3] = M2.current + f4, n5.current[(r2 + 2) % 3] = C26.current + p3, i3 && (z3.current.innerText = `${n5.current[(r2 + 1) % 3].toFixed(2)}, ${n5.current[(r2 + 2) % 3].toFixed(2)}`), fi.makeTranslation(f4 * a2.x + p3 * s3.x, f4 * a2.y + p3 * s3.y, f4 * a2.z + p3 * s3.z), y2(fi);
340444
340444
  }
340445
340445
  }, [i3, y2, P2, n5, o2, r2]), k2 = S.useCallback((e3) => {
340446
340446
  i3 && (z3.current.style.display = "none"), e3.stopPropagation(), E2.current = null, v2(), w2 && (w2.enabled = true), e3.target.releasePointerCapture(e3.pointerId);
@@ -340458,13 +340458,13 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340458
340458
  var vi = new T.Vector3();
340459
340459
  var gi = new T.Matrix4();
340460
340460
  var wi = ({ direction: e2, axis: t2 }) => {
340461
- const { scaleLimits: r2, annotations: n5, annotationsClass: o2, depthTest: i3, scale: s2, lineWidth: l2, fixed: c2, axisColors: u2, hoveredColor: d2, opacity: m2, renderOrder: f3, onDragStart: p2, onDrag: h2, onDragEnd: x2, userData: y2 } = S.useContext(Yo), v2 = a.useThree((e3) => e3.size), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(1), M2 = S.useRef(1), C25 = S.useRef(null), [P2, R2] = S.useState(false), D2 = c2 ? 1.2 : 1.2 * s2, F2 = S.useCallback((r3) => {
340461
+ const { scaleLimits: r2, annotations: n5, annotationsClass: o2, depthTest: i3, scale: s2, lineWidth: l2, fixed: c2, axisColors: u2, hoveredColor: d2, opacity: m2, renderOrder: f3, onDragStart: p2, onDrag: h2, onDragEnd: x2, userData: y2 } = S.useContext(Yo), v2 = a.useThree((e3) => e3.size), g2 = a.useThree((e3) => e3.controls), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(1), M2 = S.useRef(1), C26 = S.useRef(null), [P2, R2] = S.useState(false), D2 = c2 ? 1.2 : 1.2 * s2, F2 = S.useCallback((r3) => {
340462
340462
  n5 && (w2.current.innerText = `${M2.current.toFixed(2)}`, w2.current.style.display = "block"), r3.stopPropagation();
340463
340463
  const a2 = new T.Matrix4().extractRotation(z3.current.matrixWorld), o3 = r3.point.clone(), i4 = new T.Vector3().setFromMatrixPosition(z3.current.matrixWorld), l3 = e2.clone().applyMatrix4(a2).normalize(), u3 = z3.current.matrixWorld.clone(), d3 = u3.clone().invert(), m3 = c2 ? 1 / ie(z3.current.getWorldPosition(hi), s2, r3.camera, v2) : 1;
340464
- C25.current = { clickPoint: o3, dir: l3, mPLG: u3, mPLGInv: d3, offsetMultiplier: m3 }, p2({ component: "Sphere", axis: t2, origin: i4, directions: [l3] }), g2 && (g2.enabled = false), r3.target.setPointerCapture(r3.pointerId);
340464
+ C26.current = { clickPoint: o3, dir: l3, mPLG: u3, mPLGInv: d3, offsetMultiplier: m3 }, p2({ component: "Sphere", axis: t2, origin: i4, directions: [l3] }), g2 && (g2.enabled = false), r3.target.setPointerCapture(r3.pointerId);
340465
340465
  }, [n5, g2, e2, p2, t2, c2, s2, v2]), k2 = S.useCallback((e3) => {
340466
- if (e3.stopPropagation(), P2 || R2(true), C25.current) {
340467
- const { clickPoint: a2, dir: o3, mPLG: i4, mPLGInv: l3, offsetMultiplier: u3 } = C25.current, [d3, m3] = (null == r2 ? void 0 : r2[t2]) || [1e-5, void 0], f4 = ((e4, t3, r3, n6) => {
340466
+ if (e3.stopPropagation(), P2 || R2(true), C26.current) {
340467
+ const { clickPoint: a2, dir: o3, mPLG: i4, mPLGInv: l3, offsetMultiplier: u3 } = C26.current, [d3, m3] = (null == r2 ? void 0 : r2[t2]) || [1e-5, void 0], f4 = ((e4, t3, r3, n6) => {
340468
340468
  const a3 = t3.dot(t3), o4 = t3.dot(e4) - t3.dot(r3), i5 = t3.dot(n6);
340469
340469
  return 0 === i5 ? -o4 / a3 : (hi.copy(n6).multiplyScalar(a3 / i5).sub(t3), xi.copy(n6).multiplyScalar(o4 / i5).add(r3).sub(e4), -hi.dot(xi) / hi.dot(hi));
340470
340470
  })(a2, o3, e3.ray.origin, e3.ray.direction), p3 = f4 * u3, x3 = c2 ? p3 : p3 / s2;
@@ -340472,7 +340472,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340472
340472
  e3.shiftKey && (y3 = Math.round(10 * y3) / 10), y3 = Math.max(y3, d3 / E2.current), void 0 !== m3 && (y3 = Math.min(y3, m3 / E2.current)), M2.current = E2.current * y3, b2.current.position.set(0, D2 + p3, 0), n5 && (w2.current.innerText = `${M2.current.toFixed(2)}`), vi.set(1, 1, 1), vi.setComponent(t2, y3), gi.makeScale(vi.x, vi.y, vi.z).premultiply(i4).multiply(l3), h2(gi);
340473
340473
  }
340474
340474
  }, [n5, D2, h2, P2, r2, t2]), _2 = S.useCallback((e3) => {
340475
- n5 && (w2.current.style.display = "none"), e3.stopPropagation(), E2.current = M2.current, C25.current = null, b2.current.position.set(0, D2, 0), x2(), g2 && (g2.enabled = true), e3.target.releasePointerCapture(e3.pointerId);
340475
+ n5 && (w2.current.style.display = "none"), e3.stopPropagation(), E2.current = M2.current, C26.current = null, b2.current.position.set(0, D2, 0), x2(), g2 && (g2.enabled = true), e3.target.releasePointerCapture(e3.pointerId);
340476
340476
  }, [n5, g2, x2, D2]), A2 = S.useCallback((e3) => {
340477
340477
  e3.stopPropagation(), R2(false);
340478
340478
  }, []), { radius: L2, matrixL: I2 } = S.useMemo(() => {
@@ -340500,7 +340500,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340500
340500
  var Bi = new T.Vector3(1, 0, 0);
340501
340501
  var Ui = new T.Vector3(0, 1, 0);
340502
340502
  var Vi = new T.Vector3(0, 0, 1);
340503
- var Oi = S.forwardRef(({ enabled: e2 = true, matrix: t2, onDragStart: r2, onDrag: n5, onDragEnd: o2, autoTransform: i3 = true, anchor: s2, disableAxes: l2 = false, disableSliders: c2 = false, disableRotations: u2 = false, disableScaling: d2 = false, activeAxes: m2 = [true, true, true], offset: f3 = [0, 0, 0], rotation: p2 = [0, 0, 0], scale: h2 = 1, lineWidth: x2 = 4, fixed: y2 = false, translationLimits: v2, rotationLimits: g2, scaleLimits: w2, depthTest: z3 = true, renderOrder: b2 = 500, axisColors: E2 = ["#ff2060", "#20df80", "#2080ff"], hoveredColor: C25 = "#ffff40", annotations: P2 = false, annotationsClass: R2, opacity: D2 = 1, visible: F2 = true, userData: k2, children: _2, ...A2 }, L2) => {
340503
+ var Oi = S.forwardRef(({ enabled: e2 = true, matrix: t2, onDragStart: r2, onDrag: n5, onDragEnd: o2, autoTransform: i3 = true, anchor: s2, disableAxes: l2 = false, disableSliders: c2 = false, disableRotations: u2 = false, disableScaling: d2 = false, activeAxes: m2 = [true, true, true], offset: f3 = [0, 0, 0], rotation: p2 = [0, 0, 0], scale: h2 = 1, lineWidth: x2 = 4, fixed: y2 = false, translationLimits: v2, rotationLimits: g2, scaleLimits: w2, depthTest: z3 = true, renderOrder: b2 = 500, axisColors: E2 = ["#ff2060", "#20df80", "#2080ff"], hoveredColor: C26 = "#ffff40", annotations: P2 = false, annotationsClass: R2, opacity: D2 = 1, visible: F2 = true, userData: k2, children: _2, ...A2 }, L2) => {
340504
340504
  const I2 = a.useThree((e3) => e3.invalidate), B2 = S.useRef(null), U2 = S.useRef(null), V3 = S.useRef(null), O2 = S.useRef(null), N2 = S.useRef([0, 0, 0]), j2 = S.useRef(new T.Vector3(1, 1, 1)), W2 = S.useRef(new T.Vector3(1, 1, 1));
340505
340505
  S.useLayoutEffect(() => {
340506
340506
  s2 && (O2.current.updateWorldMatrix(true, true), Mi.copy(O2.current.matrixWorld).invert(), Di.makeEmpty(), O2.current.traverse((e3) => {
@@ -340513,7 +340513,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340513
340513
  Ei.copy(B2.current.matrixWorld), Mi.copy(Ei).invert(), Si.copy(bi).premultiply(e3), Ci.copy(Si).premultiply(Mi), Ti.copy(zi).invert(), Pi.copy(Ci).multiply(Ti), i3 && U2.current.matrix.copy(Ci), n5 && n5(Ci, Pi, Si, e3), I2();
340514
340514
  }, onDragEnd: () => {
340515
340515
  o2 && o2(), I2();
340516
- }, translation: N2, translationLimits: v2, rotationLimits: g2, axisColors: E2, hoveredColor: C25, opacity: D2, scale: h2, lineWidth: x2, fixed: y2, depthTest: z3, renderOrder: b2, userData: k2, annotations: P2, annotationsClass: R2 }), [r2, n5, o2, N2, v2, g2, w2, z3, h2, x2, y2, ...E2, C25, D2, k2, i3, P2, R2]), H2 = new T.Vector3();
340516
+ }, translation: N2, translationLimits: v2, rotationLimits: g2, axisColors: E2, hoveredColor: C26, opacity: D2, scale: h2, lineWidth: x2, fixed: y2, depthTest: z3, renderOrder: b2, userData: k2, annotations: P2, annotationsClass: R2 }), [r2, n5, o2, N2, v2, g2, w2, z3, h2, x2, y2, ...E2, C26, D2, k2, i3, P2, R2]), H2 = new T.Vector3();
340517
340517
  return a.useFrame((e3) => {
340518
340518
  if (y2) {
340519
340519
  const t3 = ie(V3.current.getWorldPosition(H2), h2, e3.camera, e3.size);
@@ -340544,7 +340544,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340544
340544
  var Hi = S.forwardRef(({ points: e2 = Xi.SAMPLE_FACELANDMARKER_RESULT.faceLandmarks[0], face: t2, facialTransformationMatrix: r2, faceBlendshapes: n5, offset: o2, offsetScalar: i3 = 80, width: s2, height: l2, depth: c2 = 1, verticalTri: u2 = [159, 386, 152], origin: d2, eyes: m2 = true, eyesAsOrigin: f3 = false, debug: p2 = false, children: h2, ...x2 }, y2) => {
340545
340545
  var v2;
340546
340546
  t2 && (e2 = t2.keypoints, console.warn("Facemesh `face` prop is deprecated: use `points` instead"));
340547
- const g2 = S.useRef(null), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(null), M2 = S.useRef(null), C25 = S.useRef(null), [P2] = S.useState(() => new T.Vector3()), [R2] = S.useState(() => new T.Object3D()), [D2] = S.useState(() => new T.Quaternion()), [F2] = S.useState(() => new T.Vector3()), { invalidate: k2 } = a.useThree();
340547
+ const g2 = S.useRef(null), w2 = S.useRef(null), z3 = S.useRef(null), b2 = S.useRef(null), E2 = S.useRef(null), M2 = S.useRef(null), C26 = S.useRef(null), [P2] = S.useState(() => new T.Vector3()), [R2] = S.useState(() => new T.Object3D()), [D2] = S.useState(() => new T.Quaternion()), [F2] = S.useState(() => new T.Vector3()), { invalidate: k2 } = a.useThree();
340548
340548
  S.useEffect(() => {
340549
340549
  var e3;
340550
340550
  null == (e3 = E2.current) || e3.geometry.setIndex(Xi.TRIANGULATION);
@@ -340558,12 +340558,12 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340558
340558
  (h3.setFromPoints(e2), h3.setDrawRange(0, Xi.TRIANGULATION.length), r2) ? (R2.matrix.fromArray(r2.data), R2.matrix.decompose(R2.position, R2.quaternion, R2.scale), R2.rotation.y *= -1, R2.rotation.z *= -1, D2.setFromEuler(R2.rotation), o2 ? (R2.position.y *= -1, R2.position.z *= -1, null == (x3 = g2.current) || x3.position.copy(R2.position.divideScalar(i3))) : null == (y3 = g2.current) || y3.position.set(0, 0, 0)) : (Gi(e2[u2[0]], e2[u2[1]], e2[u2[2]], P2), D2.setFromUnitVectors(Wi, P2));
340559
340559
  const v3 = D2.clone().invert();
340560
340560
  if (h3.computeBoundingBox(), p2 && k2(), h3.center(), h3.applyQuaternion(v3), null == (a2 = b2.current) || a2.setRotationFromQuaternion(D2), m2) if (n5) {
340561
- if (M2.current && C25.current && z3.current) if (f3) {
340562
- const e3 = M2.current._computeSphere(h3), t4 = C25.current._computeSphere(h3), r3 = function(e4, t5) {
340561
+ if (M2.current && C26.current && z3.current) if (f3) {
340562
+ const e3 = M2.current._computeSphere(h3), t4 = C26.current._computeSphere(h3), r3 = function(e4, t5) {
340563
340563
  return e4.clone().add(t5).multiplyScalar(0.5);
340564
340564
  }(e3.center, t4.center);
340565
- d2 = r3.negate(), M2.current._update(h3, n5, e3), C25.current._update(h3, n5, t4);
340566
- } else M2.current._update(h3, n5), C25.current._update(h3, n5);
340565
+ d2 = r3.negate(), M2.current._update(h3, n5, e3), C26.current._update(h3, n5, t4);
340566
+ } else M2.current._update(h3, n5), C26.current._update(h3, n5);
340567
340567
  } else console.warn("Facemesh `eyes` option only works if `faceBlendshapes` is provided: skipping.");
340568
340568
  if (z3.current) {
340569
340569
  if (void 0 !== d2) if ("number" == typeof d2) {
@@ -340579,10 +340579,10 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340579
340579
  }
340580
340580
  h3.computeVertexNormals(), h3.attributes.position.needsUpdate = true;
340581
340581
  }, [e2, r2, n5, R2, o2, i3, s2, l2, c2, u2, d2, m2, p2, k2, P2, D2, _2, F2]);
340582
- const A2 = S.useMemo(() => ({ outerRef: b2, meshRef: E2, eyeRightRef: M2, eyeLeftRef: C25 }), []);
340582
+ const A2 = S.useMemo(() => ({ outerRef: b2, meshRef: E2, eyeRightRef: M2, eyeLeftRef: C26 }), []);
340583
340583
  S.useImperativeHandle(y2, () => A2, [A2]);
340584
340584
  const [L2] = S.useState(() => new T.Vector3()), I2 = null == (v2 = E2.current) ? void 0 : v2.geometry.boundingBox, B2 = (null == I2 ? void 0 : I2.getSize(L2).z) || 1;
340585
- return S.createElement("group", x2, S.createElement("group", { ref: g2 }, S.createElement("group", { ref: b2 }, S.createElement("group", { ref: w2 }, p2 ? S.createElement(S.Fragment, null, S.createElement("axesHelper", { args: [B2] }), S.createElement(ce, { points: [[0, 0, 0], [0, 0, -B2]], color: 65535 })) : null, S.createElement("group", { ref: z3 }, m2 && n5 && S.createElement("group", { name: "eyes" }, S.createElement(qi, { side: "left", ref: M2, debug: p2 }), S.createElement(qi, { side: "right", ref: C25, debug: p2 })), S.createElement("mesh", { ref: E2, name: "face" }, h2, p2 ? S.createElement(S.Fragment, null, I2 && S.createElement("box3Helper", { args: [I2] })) : null))))));
340585
+ return S.createElement("group", x2, S.createElement("group", { ref: g2 }, S.createElement("group", { ref: b2 }, S.createElement("group", { ref: w2 }, p2 ? S.createElement(S.Fragment, null, S.createElement("axesHelper", { args: [B2] }), S.createElement(ce, { points: [[0, 0, 0], [0, 0, -B2]], color: 65535 })) : null, S.createElement("group", { ref: z3 }, m2 && n5 && S.createElement("group", { name: "eyes" }, S.createElement(qi, { side: "left", ref: M2, debug: p2 }), S.createElement(qi, { side: "right", ref: C26, debug: p2 })), S.createElement("mesh", { ref: E2, name: "face" }, h2, p2 ? S.createElement(S.Fragment, null, I2 && S.createElement("box3Helper", { args: [I2] })) : null))))));
340586
340586
  });
340587
340587
  var $i = { contourLandmarks: { right: [33, 133, 159, 145, 153], left: [263, 362, 386, 374, 380] }, blendshapes: { right: [14, 16, 18, 12], left: [13, 15, 17, 11] }, color: { right: "red", left: "#00ff00" }, fov: { horizontal: 100, vertical: 90 } };
340588
340588
  var qi = S.forwardRef(({ side: e2, debug: t2 = true }, r2) => {
@@ -340628,27 +340628,27 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
340628
340628
  var ts = t.createContext({});
340629
340629
  var rs = t.forwardRef(({ camera: e2, videoTexture: r2 = { start: true }, manualDetect: n5 = false, faceLandmarkerResult: o2, manualUpdate: i3 = false, makeDefault: l2, smoothTime: c2 = 0.25, offset: u2 = true, offsetScalar: d2 = 80, eyes: m2 = false, eyesAsOrigin: f3 = true, depth: p2 = 0.15, debug: h2 = false, facemesh: x2 }, y2) => {
340630
340630
  var v2, g2;
340631
- const w2 = a.useThree((e3) => e3.scene), z3 = a.useThree((e3) => e3.camera), b2 = a.useThree((e3) => e3.set), E2 = a.useThree((e3) => e3.get), C25 = e2 || z3, P2 = t.useRef(null), [R2] = t.useState(() => new T.Object3D()), [D2] = t.useState(() => new T.Vector3()), [F2] = t.useState(() => new T.Vector3()), [k2] = t.useState(() => new T.Vector3()), [_2] = t.useState(() => new T.Vector3()), A2 = t.useCallback(() => {
340632
- R2.parent = C25.parent;
340631
+ const w2 = a.useThree((e3) => e3.scene), z3 = a.useThree((e3) => e3.camera), b2 = a.useThree((e3) => e3.set), E2 = a.useThree((e3) => e3.get), C26 = e2 || z3, P2 = t.useRef(null), [R2] = t.useState(() => new T.Object3D()), [D2] = t.useState(() => new T.Vector3()), [F2] = t.useState(() => new T.Vector3()), [k2] = t.useState(() => new T.Vector3()), [_2] = t.useState(() => new T.Vector3()), A2 = t.useCallback(() => {
340632
+ R2.parent = C26.parent;
340633
340633
  const e3 = P2.current;
340634
340634
  if (e3) {
340635
340635
  const { outerRef: t2, eyeRightRef: r3, eyeLeftRef: n6 } = e3;
340636
340636
  if (r3.current && n6.current) {
340637
340637
  const { irisDirRef: e4 } = r3.current, { irisDirRef: a2 } = n6.current;
340638
- e4.current && a2.current && t2.current && (D2.copy(es(e4.current, new T.Vector3(0, 0, 0), t2.current)), F2.copy(es(a2.current, new T.Vector3(0, 0, 0), t2.current)), R2.position.copy(es(t2.current, Ji(D2, F2), C25.parent || w2)), k2.copy(es(e4.current, new T.Vector3(0, 0, 1), t2.current)), _2.copy(es(a2.current, new T.Vector3(0, 0, 1), t2.current)), R2.lookAt(t2.current.localToWorld(Ji(k2, _2))));
340639
- } else t2.current && (R2.position.copy(es(t2.current, new T.Vector3(0, 0, 0), C25.parent || w2)), R2.lookAt(t2.current.localToWorld(new T.Vector3(0, 0, 1))));
340638
+ e4.current && a2.current && t2.current && (D2.copy(es(e4.current, new T.Vector3(0, 0, 0), t2.current)), F2.copy(es(a2.current, new T.Vector3(0, 0, 0), t2.current)), R2.position.copy(es(t2.current, Ji(D2, F2), C26.parent || w2)), k2.copy(es(e4.current, new T.Vector3(0, 0, 1), t2.current)), _2.copy(es(a2.current, new T.Vector3(0, 0, 1), t2.current)), R2.lookAt(t2.current.localToWorld(Ji(k2, _2))));
340639
+ } else t2.current && (R2.position.copy(es(t2.current, new T.Vector3(0, 0, 0), C26.parent || w2)), R2.lookAt(t2.current.localToWorld(new T.Vector3(0, 0, 1))));
340640
340640
  }
340641
340641
  return R2;
340642
- }, [C25, F2, _2, D2, k2, w2, R2]), [L2] = t.useState(() => new T.Object3D()), I2 = t.useCallback(function(e3, t2) {
340643
- if (C25) {
340642
+ }, [C26, F2, _2, D2, k2, w2, R2]), [L2] = t.useState(() => new T.Object3D()), I2 = t.useCallback(function(e3, t2) {
340643
+ if (C26) {
340644
340644
  var r3;
340645
340645
  if (null !== (r3 = t2) && void 0 !== r3 || (t2 = A2()), c2 > 0) {
340646
340646
  const r4 = 1e-9;
340647
340647
  s.easing.damp3(L2.position, t2.position, c2, e3, void 0, void 0, r4), s.easing.dampE(L2.rotation, t2.rotation, c2, e3, void 0, void 0, r4);
340648
340648
  } else L2.position.copy(t2.position), L2.rotation.copy(t2.rotation);
340649
- C25.position.copy(L2.position), C25.rotation.copy(L2.rotation);
340649
+ C26.position.copy(L2.position), C26.rotation.copy(L2.rotation);
340650
340650
  }
340651
- }, [C25, A2, c2, L2.position, L2.rotation]);
340651
+ }, [C26, A2, c2, L2.position, L2.rotation]);
340652
340652
  a.useFrame((e3, t2) => {
340653
340653
  i3 || I2(t2);
340654
340654
  });
@@ -341013,14 +341013,14 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
341013
341013
  v2.style.cursor = "default", y2.domElement.style.cursor = "default";
341014
341014
  };
341015
341015
  }, [r2, l2, v2, e2]);
341016
- const [E2] = S.useState({ scale: 1, rotation: b2, damping: h2 }), C25 = S.useRef(null);
341016
+ const [E2] = S.useState({ scale: 1, rotation: b2, damping: h2 }), C26 = S.useRef(null);
341017
341017
  a.useFrame((e3, t3) => {
341018
- s.easing.damp3(C25.current.scale, E2.scale, E2.damping, t3), s.easing.dampE(C25.current.rotation, E2.rotation, E2.damping, t3);
341018
+ s.easing.damp3(C26.current.scale, E2.scale, E2.damping, t3), s.easing.dampE(C26.current.rotation, E2.rotation, E2.damping, t3);
341019
341019
  });
341020
341020
  const T2 = i2.useGesture({ onHover: ({ last: t3 }) => {
341021
341021
  l2 && !r2 && e2 && (v2.style.cursor = t3 ? "auto" : "grab");
341022
341022
  }, onDrag: ({ down: r3, delta: [a2, o3], memo: [i3, s2] = E2.rotation || b2 }) => e2 ? (l2 && (v2.style.cursor = r3 ? "grabbing" : "grab"), a2 = n4.MathUtils.clamp(s2 + a2 / g2.width * Math.PI * u2, ...z3), o3 = n4.MathUtils.clamp(i3 + o3 / g2.height * Math.PI * u2, ...w2), E2.scale = r3 && o3 > w2[1] / 2 ? m2 : 1, E2.rotation = t2 && !r3 ? b2 : [o3, a2, 0], E2.damping = t2 && !r3 && "boolean" != typeof t2 ? t2 : h2, [o3, a2]) : [o3, a2] }, { target: r2 ? v2 : void 0 });
341023
- return S.createElement("group", M.default({ ref: C25 }, null == T2 ? void 0 : T2()), c2);
341023
+ return S.createElement("group", M.default({ ref: C26 }, null == T2 ? void 0 : T2()), c2);
341024
341024
  }, exports2.Progress = function({ children: e2 }) {
341025
341025
  const t2 = G();
341026
341026
  return S.createElement(S.Fragment, null, null == e2 ? void 0 : e2(t2));
@@ -341081,18 +341081,18 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
341081
341081
  };
341082
341082
  }
341083
341083
  }, [g2, v2, x2, r2, M2, y2, n5, t2]);
341084
- let C25 = 0;
341084
+ let C26 = 0;
341085
341085
  return a.useFrame((t3, r3) => {
341086
- C25 = M2.offset, s.easing.damp(M2, "offset", E2.current, l2, r3, c2, void 0, e2), s.easing.damp(M2, "delta", Math.abs(C25 - M2.offset), l2, r3, c2, void 0, e2), M2.delta > e2 && y2();
341086
+ C26 = M2.offset, s.easing.damp(M2, "offset", E2.current, l2, r3, c2, void 0, e2), s.easing.damp(M2, "delta", Math.abs(C26 - M2.offset), l2, r3, c2, void 0, e2), M2.delta > e2 && y2();
341087
341087
  }), S.createElement(q.Provider, { value: M2 }, m2);
341088
341088
  }, exports2.Segment = Eo, exports2.SegmentObject = zo, exports2.Segments = wo, exports2.Select = function({ box: e2, multiple: t2, children: r2, onChange: n5, onChangePointerUp: o2, border: i3 = "1px solid #55aaff", backgroundColor: s2 = "rgba(75, 160, 255, 0.1)", filter: l2 = (e3) => e3, ...d2 }) {
341089
- const [m2, f3] = S.useState(false), { setEvents: p2, camera: h2, raycaster: x2, gl: y2, controls: v2, size: g2, get: w2 } = a.useThree(), [z3, b2] = S.useState(false), [E2, C25] = S.useReducer((e3, { object: t3, shift: r3 }) => void 0 === t3 ? [] : Array.isArray(t3) ? t3 : r3 ? e3.includes(t3) ? e3.filter((e4) => e4 !== t3) : [t3, ...e3] : e3[0] === t3 ? [] : [t3], []);
341089
+ const [m2, f3] = S.useState(false), { setEvents: p2, camera: h2, raycaster: x2, gl: y2, controls: v2, size: g2, get: w2 } = a.useThree(), [z3, b2] = S.useState(false), [E2, C26] = S.useReducer((e3, { object: t3, shift: r3 }) => void 0 === t3 ? [] : Array.isArray(t3) ? t3 : r3 ? e3.includes(t3) ? e3.filter((e4) => e4 !== t3) : [t3, ...e3] : e3[0] === t3 ? [] : [t3], []);
341090
341090
  S.useEffect(() => {
341091
341091
  m2 ? null == n5 || n5(E2) : null == o2 || o2(E2);
341092
341092
  }, [E2, m2]);
341093
341093
  const P2 = S.useCallback((e3) => {
341094
- e3.stopPropagation(), C25({ object: l2([e3.object])[0], shift: t2 && e3.shiftKey });
341095
- }, []), R2 = S.useCallback((e3) => !z3 && C25({}), [z3]), D2 = S.useRef(null);
341094
+ e3.stopPropagation(), C26({ object: l2([e3.object])[0], shift: t2 && e3.shiftKey });
341095
+ }, []), R2 = S.useCallback((e3) => !z3 && C26({}), [z3]), D2 = S.useRef(null);
341096
341096
  return S.useEffect(() => {
341097
341097
  if (!e2 || !t2) return;
341098
341098
  const r3 = new c.SelectionBox(h2, D2.current), n6 = document.createElement("div");
@@ -341116,7 +341116,7 @@ vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){ret
341116
341116
  d3.x = Math.max(a2.x, e4.clientX), d3.y = Math.max(a2.y, e4.clientY), o3.x = Math.min(a2.x, e4.clientX), o3.y = Math.min(a2.y, e4.clientY), n6.style.left = `${o3.x}px`, n6.style.top = `${o3.y}px`, n6.style.width = d3.x - o3.x + "px", n6.style.height = d3.y - o3.y + "px";
341117
341117
  }(e3), b3(e3, r3.endPoint);
341118
341118
  const t3 = r3.select().sort((e4) => e4.uuid).filter((e4) => e4.isMesh);
341119
- u.shallow(t3, M2) || (M2 = t3, C25({ object: l2(t3) }));
341119
+ u.shallow(t3, M2) || (M2 = t3, C26({ object: l2(t3) }));
341120
341120
  }
341121
341121
  }
341122
341122
  function P3(e3) {
@@ -341262,11 +341262,11 @@ float PCSS (sampler2D shadowMap, vec4 coords) {
341262
341262
  return e2.shader ? S.createElement(Ea, e2) : S.createElement(Ma, e2);
341263
341263
  }, exports2.SpriteAnimator = jr, exports2.Stage = function({ children: e2, center: t2, adjustCamera: r2 = true, intensity: n5 = 0.5, shadows: a2 = "contact", environment: o2 = "city", preset: i3 = "rembrandt", ...s2 }) {
341264
341264
  var l2, c2, u2, d2, m2, f3, p2, h2;
341265
- const x2 = "string" == typeof i3 ? ua[i3] : i3, [{ radius: y2, height: v2 }, g2] = S.useState({ radius: 0, width: 0, height: 0, depth: 0 }), w2 = null !== (l2 = null == a2 ? void 0 : a2.bias) && void 0 !== l2 ? l2 : -1e-4, z3 = null !== (c2 = null == a2 ? void 0 : a2.normalBias) && void 0 !== c2 ? c2 : 0, b2 = null !== (u2 = null == a2 ? void 0 : a2.size) && void 0 !== u2 ? u2 : 1024, E2 = null !== (d2 = null == a2 ? void 0 : a2.offset) && void 0 !== d2 ? d2 : 0, C25 = "contact" === a2 || "contact" === (null == a2 ? void 0 : a2.type), T2 = "accumulative" === a2 || "accumulative" === (null == a2 ? void 0 : a2.type), P2 = { ..."object" == typeof a2 ? a2 : {} }, R2 = o2 ? "string" == typeof o2 ? { preset: o2 } : o2 : null, D2 = S.useCallback((e3) => {
341265
+ const x2 = "string" == typeof i3 ? ua[i3] : i3, [{ radius: y2, height: v2 }, g2] = S.useState({ radius: 0, width: 0, height: 0, depth: 0 }), w2 = null !== (l2 = null == a2 ? void 0 : a2.bias) && void 0 !== l2 ? l2 : -1e-4, z3 = null !== (c2 = null == a2 ? void 0 : a2.normalBias) && void 0 !== c2 ? c2 : 0, b2 = null !== (u2 = null == a2 ? void 0 : a2.size) && void 0 !== u2 ? u2 : 1024, E2 = null !== (d2 = null == a2 ? void 0 : a2.offset) && void 0 !== d2 ? d2 : 0, C26 = "contact" === a2 || "contact" === (null == a2 ? void 0 : a2.type), T2 = "accumulative" === a2 || "accumulative" === (null == a2 ? void 0 : a2.type), P2 = { ..."object" == typeof a2 ? a2 : {} }, R2 = o2 ? "string" == typeof o2 ? { preset: o2 } : o2 : null, D2 = S.useCallback((e3) => {
341266
341266
  const { width: r3, height: n6, depth: a3, boundingSphere: o3 } = e3;
341267
341267
  g2({ radius: o3.radius, width: r3, height: n6, depth: a3 }), null != t2 && t2.onCentered && t2.onCentered(e3);
341268
341268
  }, []);
341269
- return S.createElement(S.Fragment, null, S.createElement("ambientLight", { intensity: n5 / 3 }), S.createElement("spotLight", { penumbra: 1, position: [x2.main[0] * y2, x2.main[1] * y2, x2.main[2] * y2], intensity: 2 * n5, castShadow: !!a2, "shadow-bias": w2, "shadow-normalBias": z3, "shadow-mapSize": b2 }), S.createElement("pointLight", { position: [x2.fill[0] * y2, x2.fill[1] * y2, x2.fill[2] * y2], intensity: n5 }), S.createElement(Un, M.default({ fit: !!r2, clip: !!r2, margin: Number(r2), observe: true }, s2), S.createElement(da, { radius: y2, adjustCamera: r2 }), S.createElement(wr, M.default({}, t2, { position: [0, E2 / 2, 0], onCentered: D2 }), e2)), S.createElement("group", { position: [0, -v2 / 2 - E2 / 2, 0] }, C25 && S.createElement(aa, M.default({ scale: 4 * y2, far: y2, blur: 2 }, P2)), T2 && S.createElement(sa, M.default({ temporal: true, frames: 100, alphaTest: 0.9, toneMapped: true, scale: 4 * y2 }, P2), S.createElement(la, { amount: null !== (m2 = P2.amount) && void 0 !== m2 ? m2 : 8, radius: null !== (f3 = P2.radius) && void 0 !== f3 ? f3 : y2, ambient: null !== (p2 = P2.ambient) && void 0 !== p2 ? p2 : 0.5, intensity: null !== (h2 = P2.intensity) && void 0 !== h2 ? h2 : 1, position: [x2.main[0] * y2, x2.main[1] * y2, x2.main[2] * y2], size: 4 * y2, bias: -w2, mapSize: b2 }))), o2 && S.createElement(na, R2));
341269
+ return S.createElement(S.Fragment, null, S.createElement("ambientLight", { intensity: n5 / 3 }), S.createElement("spotLight", { penumbra: 1, position: [x2.main[0] * y2, x2.main[1] * y2, x2.main[2] * y2], intensity: 2 * n5, castShadow: !!a2, "shadow-bias": w2, "shadow-normalBias": z3, "shadow-mapSize": b2 }), S.createElement("pointLight", { position: [x2.fill[0] * y2, x2.fill[1] * y2, x2.fill[2] * y2], intensity: n5 }), S.createElement(Un, M.default({ fit: !!r2, clip: !!r2, margin: Number(r2), observe: true }, s2), S.createElement(da, { radius: y2, adjustCamera: r2 }), S.createElement(wr, M.default({}, t2, { position: [0, E2 / 2, 0], onCentered: D2 }), e2)), S.createElement("group", { position: [0, -v2 / 2 - E2 / 2, 0] }, C26 && S.createElement(aa, M.default({ scale: 4 * y2, far: y2, blur: 2 }, P2)), T2 && S.createElement(sa, M.default({ temporal: true, frames: 100, alphaTest: 0.9, toneMapped: true, scale: 4 * y2 }, P2), S.createElement(la, { amount: null !== (m2 = P2.amount) && void 0 !== m2 ? m2 : 8, radius: null !== (f3 = P2.radius) && void 0 !== f3 ? f3 : y2, ambient: null !== (p2 = P2.ambient) && void 0 !== p2 ? p2 : 0.5, intensity: null !== (h2 = P2.intensity) && void 0 !== h2 ? h2 : 1, position: [x2.main[0] * y2, x2.main[1] * y2, x2.main[2] * y2], size: 4 * y2, bias: -w2, mapSize: b2 }))), o2 && S.createElement(na, R2));
341270
341270
  }, exports2.Stars = Fa, exports2.Stats = function({ showPanel: e2 = 0, className: t2, parent: r2 }) {
341271
341271
  const n5 = function(e3, t3 = [], r3) {
341272
341272
  const [n6, a2] = S.useState();
@@ -421010,24 +421010,24 @@ function convertToString(attrs) {
421010
421010
  function intersectLine2Line(line1, line2) {
421011
421011
  let ip = [];
421012
421012
  let [A1, B1, C110] = line1.standard;
421013
- let [A2, B2, C25] = line2.standard;
421013
+ let [A2, B2, C26] = line2.standard;
421014
421014
  let det = A1 * B2 - B1 * A2;
421015
- let detX = C110 * B2 - B1 * C25;
421016
- let detY = A1 * C25 - C110 * A2;
421015
+ let detX = C110 * B2 - B1 * C26;
421016
+ let detY = A1 * C26 - C110 * A2;
421017
421017
  if (!Flatten.Utils.EQ_0(det)) {
421018
421018
  let x, y;
421019
421019
  if (B1 === 0) {
421020
421020
  x = C110 / A1;
421021
421021
  y = detY / det;
421022
421022
  } else if (B2 === 0) {
421023
- x = C25 / A2;
421023
+ x = C26 / A2;
421024
421024
  y = detY / det;
421025
421025
  } else if (A1 === 0) {
421026
421026
  x = detX / det;
421027
421027
  y = C110 / B1;
421028
421028
  } else if (A2 === 0) {
421029
421029
  x = detX / det;
421030
- y = C25 / B2;
421030
+ y = C26 / B2;
421031
421031
  } else {
421032
421032
  x = detX / det;
421033
421033
  y = detY / det;
@@ -429173,9 +429173,10 @@ var C21 = {
429173
429173
  const rooms = ctx.model.byType("room");
429174
429174
  if (rooms.length === 0) return findings;
429175
429175
  const lowest = Math.min(...rooms.map((r) => r.floor));
429176
+ const tol = Math.max(ctx.defaults.wall_thickness, 8);
429176
429177
  for (const { floorNum, summary } of eachStaircaseSummary(ctx)) {
429177
429178
  if (!summary.box || floorNum !== lowest) continue;
429178
- const fp = boxFootprint(summary.box);
429179
+ const fp = boxFootprint(summary.box, tol) ?? boxFootprint(summary.box);
429179
429180
  if (!fp) continue;
429180
429181
  if (!footprintContains(plinthArea, fp)) {
429181
429182
  const b = summary.box;
@@ -429429,14 +429430,25 @@ var C24 = {
429429
429430
  },
429430
429431
  check(ctx) {
429431
429432
  const { findings, report } = makeReport("C24", "warn");
429432
- const model = ctx.model;
429433
+ const tol = Math.max(ctx.defaults.wall_thickness, 8);
429434
+ const floors = ctx.resolved.floors ?? [];
429435
+ const decksByFloor = /* @__PURE__ */ new Map();
429436
+ for (const fl of floors) {
429437
+ const fps = [];
429438
+ for (const o of fl.objects ?? []) {
429439
+ if (o.type !== "floor_slab" || o.enabled === false) continue;
429440
+ const fp = boxFootprint({ x: num2(o.x), y: num2(o.y), width: num2(o.width), length: num2(o.length) });
429441
+ if (fp) fps.push(fp);
429442
+ }
429443
+ decksByFloor.set(num2(fl.floor_number), fps);
429444
+ }
429433
429445
  for (const { floorNum, floorSlabThickness, summary } of eachStaircaseSummary(ctx)) {
429434
429446
  if (!summary.box) continue;
429435
429447
  if (!(floorSlabThickness > 0)) continue;
429436
- const fp = boxFootprint(summary.box);
429448
+ const fp = boxFootprint(summary.box, tol) ?? boxFootprint(summary.box);
429437
429449
  if (!fp) continue;
429438
- const slabs = model.byType("slab").filter((s) => s.floor === floorNum);
429439
- const covered2 = slabs.length > 0 && footprintContains(footprintUnion(slabs.map((s) => s.footprint)), fp);
429450
+ const decks = decksByFloor.get(floorNum) ?? [];
429451
+ const covered2 = decks.length > 0 && footprintContains(footprintUnion(decks), fp);
429440
429452
  if (!covered2) {
429441
429453
  const b = summary.box;
429442
429454
  report(
@@ -429475,7 +429487,7 @@ function house23(slabThickness, objects) {
429475
429487
  };
429476
429488
  }
429477
429489
  function slab(x, y, width, length) {
429478
- return { type: "slab", name: "Slab", x, y, width, length };
429490
+ return { type: "floor_slab", name: "Slab", x, y, width, length };
429479
429491
  }
429480
429492
  function stair5(start_x, start_y, width, length) {
429481
429493
  return {
@@ -429492,6 +429504,85 @@ function stair5(start_x, start_y, width, length) {
429492
429504
  };
429493
429505
  }
429494
429506
 
429507
+ // ../editor/src/lint/constraints/c25_pillar_reach.ts
429508
+ function isLanding(n4) {
429509
+ return /_L\d+$/.test(String(n4.raw?.name ?? ""));
429510
+ }
429511
+ var C25 = {
429512
+ id: "C25",
429513
+ title: "A pillar under a slab or landing should reach it",
429514
+ level: "warn",
429515
+ doc: {
429516
+ statement: "When a floor slab or a staircase landing sits directly over a pillar, the pillar should rise to the underside of it. A pillar that stops short leaves a gap and carries nothing.",
429517
+ rationale: "A column exists to carry the slab or landing above it; if it stops below that level there is a gap and the load has nothing to bear on. Agents often shrink a copied pillar's height (or a configurator lowers it) so it no longer reaches. This checks the LOWEST floor slab / staircase landing that actually sits over the pillar \u2014 so a pillar added to carry a stair's turn landings is checked against those landings, and a pillar supporting only a roof (which slopes, no flat datum) or with nothing above is never flagged. (A warning \u2014 a deliberately low post under a slab is allowed.)",
429518
+ fix: "Raise the pillar height so its top meets the slab/landing above it. The warning reports the gap and a suggested height."
429519
+ },
429520
+ check(ctx) {
429521
+ const { findings, report } = makeReport("C25", "warn");
429522
+ const model = ctx.model;
429523
+ const slabs = model.byType("floor_slab");
429524
+ const maxGap = Math.max(ctx.defaults.slab_thickness / 2, 2);
429525
+ const eps = 1;
429526
+ for (const p of model.byType("pillar")) {
429527
+ if (p.raw.enabled === false) continue;
429528
+ const above2 = slabs.filter(
429529
+ (s) => s.z.lo > p.z.lo + eps && footprintsOverlap(s.footprint, p.footprint)
429530
+ );
429531
+ if (above2.length === 0) continue;
429532
+ const deckTops = above2.filter((s) => !isLanding(s)).map((s) => s.z.lo);
429533
+ const cap2 = deckTops.length ? Math.min(...deckTops) : Infinity;
429534
+ const inReach = above2.filter((s) => s.z.lo <= cap2 + eps);
429535
+ const target = inReach.reduce((a, s) => s.z.lo > a.z.lo ? s : a, inReach[0]);
429536
+ const gap = target.z.lo - p.z.hi;
429537
+ if (gap > maxGap) {
429538
+ const kind = isLanding(target) ? "landing" : "slab";
429539
+ const suggested = Math.round(num2(p.raw.height) + gap);
429540
+ report(
429541
+ `Pillar ${objLabel(p.raw)} on floor ${p.floor} is short of the ${kind} above it \u2014 its top is ${Math.round(gap)} below the underside of that ${kind}, leaving a gap with nothing bearing on it. Raise its height to about ${suggested} so it meets the ${kind}.`,
429542
+ { floor: p.floor, where: objLabel(p.raw) }
429543
+ );
429544
+ }
429545
+ }
429546
+ return findings;
429547
+ },
429548
+ fixtures: {
429549
+ pass: [
429550
+ {
429551
+ name: "a full-height pillar reaches the slab above",
429552
+ config: house24(116, true)
429553
+ },
429554
+ {
429555
+ name: "a short pillar with NO slab above (supports a roof) is not flagged",
429556
+ config: house24(75, false)
429557
+ }
429558
+ ],
429559
+ fail: [
429560
+ {
429561
+ name: "a short pillar under a slab",
429562
+ config: house24(75, true),
429563
+ expect: { count: 1, level: "warn", messageIncludes: "short of the slab" }
429564
+ }
429565
+ ]
429566
+ }
429567
+ };
429568
+ function house24(pillarHeight, slabAbove) {
429569
+ const floor2Objects = slabAbove ? [{ type: "floor_slab", name: "Deck", x: 0, y: 0, width: 100, length: 100 }] : [];
429570
+ return {
429571
+ floors: [
429572
+ {
429573
+ floor_number: 1,
429574
+ name: "Ground",
429575
+ height: 116,
429576
+ slab_thickness: 8,
429577
+ objects: [
429578
+ { type: "pillar", name: "P", x: 40, y: 40, width: 12, length: 12, height: pillarHeight }
429579
+ ]
429580
+ },
429581
+ { floor_number: 2, name: "Upper", height: 116, slab_thickness: 8, objects: floor2Objects }
429582
+ ]
429583
+ };
429584
+ }
429585
+
429495
429586
  // ../editor/src/lint/constraints/index.ts
429496
429587
  var CONSTRAINTS = [
429497
429588
  C1,
@@ -429517,7 +429608,8 @@ var CONSTRAINTS = [
429517
429608
  C21,
429518
429609
  C22,
429519
429610
  C23,
429520
- C24
429611
+ C24,
429612
+ C25
429521
429613
  ];
429522
429614
  function allConstraints() {
429523
429615
  const primitive = allNodes().flatMap((n4) => n4.constraints ?? []);
@@ -429566,7 +429658,7 @@ function wallRings(obj) {
429566
429658
  ]
429567
429659
  ];
429568
429660
  }
429569
- var BASE_Z_TYPES = /* @__PURE__ */ new Set(["floor_slab", "slab", "beam", "roof", "gable_roof", "ground"]);
429661
+ var BASE_Z_TYPES = /* @__PURE__ */ new Set(["floor_slab", "slab", "beam", "roof", "gable_roof", "ground", "pillar"]);
429570
429662
  function zBandOf(type, obj, band) {
429571
429663
  const zOffDefault = BASE_Z_TYPES.has(type) ? 0 : band.slabThickness;
429572
429664
  const z0 = band.slabZ + num4(obj.z_offset, zOffDefault);
@@ -434287,7 +434379,7 @@ var DOCS = {
434287
434379
  },
434288
434380
  "conventions": {
434289
434381
  "title": "Structural coding conventions (C1/C2/C3\u2026)",
434290
- "body": "# Wadi structural conventions (coding guidelines)\n\n<!-- GENERATED FILE \u2014 do not edit conventions.md by hand. It is built from\n conventions.preamble.md + the constraint modules in editor/src/lint/constraints.\n Regenerate with `npm --prefix editor run gen-conventions-doc`. -->\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026). Each convention is a\nself-contained module under `editor/src/lint/constraints/` (its check + this doc +\nits example fixtures), and **this file is generated from those modules**\n(`editor/scripts/gen-conventions-doc.mjs`) \u2014 so the doc and the linter cannot\ndrift. Add a rule by adding a constraint module and regenerating.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor's base elevation = the running sum of the previous floors' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor's walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor's height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set an explicit `height`, and that height must equal the plinth block's `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth block rises to `plinth.height`. If they differ, the floor above floats above the plinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor `height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 \"Plinth\" height 40 { // == the plinth block height below\n ground name \"Ground\" at (0,0) size (500,500)\n plinth name \"Plinth\" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is consistent by construction \u2014 but set the floor `height` explicitly anyway, so the stack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every side that faces **outside** (no room beyond it). Interior (shared) sides may be omitted \u2014 the neighbour's wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no `wall` lines) is enclosed on all four sides**. But the moment you add a `wall` line to hang a door or window, the room switches to a *whitelist* \u2014 every side you don't list is now a hole. An exterior hole leaves the room open to the weather. It is a **warning**, not an error, because an open exterior side is sometimes intentional (a verandah / open padvi).\n\n**Fix.**\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object** must set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor's walls stand on (`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is no deck, so every wall on the floor floats `slab_thickness` units above the floor base. Setting it to `0` puts the walls on the floor base; alternatively, model the deck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor of just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is harmless.)*\n\n---\n\n## C4 \u2014 A stacked floor's height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set `height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor's walls stand on the deck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor above leaves a gap over the walls; when smaller, the walls poke through it. It is a **warning** \u2014 a deliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they should match.\n\n**Fix.**\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing stacks on its walls.)*\n\n---\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase's descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Only a `climb down` (top-anchored) stair can fall below ground: you place it on the **upper** floor and it **descends**. Put it on the wrong floor, or give it too large a `total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D plans (which ignore Z) but is **buried and invisible in 3D**, with no other error. A `climb up` stair is anchored on its own floor and ascends, so it never trips this.\n\n**Fix.**\n\nPrefer **`climb up`**: put the stair on the **lower** floor it rises FROM and let it ascend.\n\n```wdl\nfloor 1 \"Ground Floor\" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name \"Stair\" at (212, 64) step (7, 11, 44) // `at` = the BOTTOM (this floor)\n direction south climb up // ascends to the floor above\n}\n```\n\n(Or, if you must keep it `climb down`, move it **up one floor** or reduce `total_height`.)\n\n---\n\n## C6 \u2014 Openings on the same wall must not overlap \xB7 **error**\n\n**Statement.** Two openings (doors/windows) cut into the **same physical wall** must not overlap along it. This includes openings that belong to **two different rooms sharing a boundary wall**.\n\n**Rationale.** Each opening is a boolean-subtract from the wall. Overlapping spans merge into one ragged hole (or fight over the same brick), which is never what you meant \u2014 and on a shared wall it silently punches a bigger gap than either room's plan shows.\n\n**Fix.**\n\nOffset or narrow one opening so the spans are disjoint. An opening's span is its resolved `[offset, offset+width]` along the wall \u2014 the `from start|center|end` anchor is honoured (its offset is converted to a start-based position first, exactly as the renderer does).\n\n---\n\n## C7 \u2014 Furniture items should not overlap \xB7 **warning**\n\n**Statement.** Two furniture `item`s whose plan footprints overlap are flagged \u2014 as a **warning**, because it is sometimes intentional (a rug under a table, a lamp on a desk, deliberately stacked pieces).\n\n**Rationale.** More often it's a placement slip \u2014 two beds dropped on the same spot, or an anchored piece that reflowed into another when a room was resized. The footprint used is the item's rotated bounding box (yaw-aware), so it matches what the plan draws.\n\n**Fix.**\n\nReposition one item, or ignore the warning if the overlap is deliberate.\n\n---\n\n## C8 \u2014 Two abutting rooms need a partition between them \xB7 **warning**\n\n**Statement.** Where two rooms share a boundary line and **neither** declares a wall on it, there is no partition between them.\n\n**Rationale.** A bare room (no `wall` lines) is enclosed on all four sides, so two bare neighbours have two walls on their shared line. But once **both** rooms switch to partial `walls` lists and both omit the shared side, the centreline is left open \u2014 the rooms merge into one space with no divider. C2 only guards *exterior* sides; this is its interior counterpart. It is a **warning** because an intentional open-plan link (kitchen into living) is legitimate.\n\n**Fix.**\n\nDeclare the wall on **one** of the two rooms (the neighbour's wall stands on the shared centreline, so one is enough):\n\n```wdl\nroom Kitchen at (\u2026) size (\u2026) { wall north south east } // east = the shared line\nroom Living at (\u2026) size (\u2026) { wall north south west }\n```\n\n---\n\n## C9 \u2014 A floor's slab_thickness should match its slab object's thickness \xB7 **warning**\n\n**Statement.** When a floor carries a `floor_slab` object with an explicit `thickness`, that thickness should equal the floor's `slab_thickness`.\n\n**Rationale.** The floor's `slab_thickness` is the deck the walls stand on (`wallZ = base + slab_thickness`); the slab object's own `thickness` is how thick the slab MESH is drawn. If they differ, the walls sit at the floor's `slab_thickness` while the slab top is at the object's `thickness`, so the walls float above or sink into the drawn deck. (A slab with no explicit `thickness` follows the floor's `slab_thickness` and is consistent by construction \u2014 this only fires when both are set and disagree.)\n\n**Fix.**\n\nMake them equal \u2014 most simply, drop the slab's explicit `thickness` so it follows the floor:\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 8 {\n slab name \"Deck\" at (\u2026) size (\u2026) // no thickness \u2192 uses 8\n}\n```\n\n---\n\n## C10 \u2014 The roof should cover the rooms of the top occupied floor \xB7 **warning**\n\n**Statement.** Every room on the top occupied floor should sit under a roof segment \u2014 no room left entirely uncovered.\n\n**Rationale.** The roof's segments span a plan area (each segment's ridge line \xB1 its `width`). A room on the top floor whose footprint does not overlap **any** roof segment has open sky above it \u2014 usually a roof that was sized to the wrong footprint, or a room added after the roof. (Only a *completely* uncovered room is flagged, so eave overhangs and partial coverage never false-warn; a house with no roof at all \u2014 a terrace \u2014 is not flagged.)\n\n**Fix.**\n\nExtend or add a roof segment to span the room, or reduce the room. Roof segments cover `start \u2192 end` along the ridge, `width` across it, so grow `width`/`end` (or the plot variables they derive from) until the room is under it.\n\n---\n\n## C11 \u2014 A declared connection must overlap on a wall and be passable (door or open) \xB7 **error**\n\n**Statement.** For every `connect`ion a room declares, the two rooms must **overlap on a wall** (not necessarily the whole wall), and that overlap must be **passable**: either a **door** lies in it, or the wall is **left off both rooms** (an open passage).\n\n**Rationale.** A connection is a FUNCTIONAL requirement \u2014 `Living` opens into `Kitchen`. It is design intent, not geometry (the renderer never draws it), so this constraint is what verifies the intent is physically realized. It fails two ways: the rooms' walls don't overlap at all, or they overlap but a solid wall (present on either room, no door in the overlap) blocks the way. No door is ever generated \u2014 a room authors its own openings, or omits the shared wall to leave the rooms open to each other.\n\n**Fix.**\n\nOverlap the two rooms on a wall, then EITHER put a door in the overlap (on either room), OR omit that wall on both:\n\n```wdl\n// door in the shared wall\nroom Living at (\u2026) size (\u2026) { connect Kitchen wall east { door D at 80 size (40,210) } }\nroom Kitchen at (\u2026) size (\u2026)\n\n// open passage \u2014 neither room walls the shared side\nroom Living at (\u2026) size (\u2026) { connect Kitchen wall north south west }\nroom Kitchen at (\u2026) size (\u2026) { wall north south east }\n```\n\n---\n\n## C12 \u2014 Rooms should not overlap (they share walls, not floor area) \xB7 **warning**\n\n**Statement.** Two `room`s on the same floor should not overlap in plan \u2014 flagged as a **warning**, because it is occasionally intentional (embedding a corner room to carve an L-shaped space). Adjacent rooms may **touch** on a shared wall (their edges coincide); a larger intersection is reported.\n\n**Rationale.** Rooms usually share walls, not floor area. A real overlap means two rooms were placed on the same spot \u2014 the renderer draws one over the other. It most often happens when a room is placed by absolute coordinates, or when a band (a verandah, a corridor) is dropped across an existing wing. C11 checks that declared connections are realized; this checks that the geometry is physically consistent. It stays a warning because an L-shaped room is modelled by overlapping a small corner room onto a larger bounding one.\n\n**Fix.**\n\nIf the overlap is unintended, move or resize one room so they only touch on a shared wall (prefer relative placement \u2014 abut a neighbour on a side \u2014 over absolute coordinates that can land on top of another room). Ignore the warning if it is a deliberate corner embed.\n\n---\n\n## C13 \u2014 The lowest floor should carry a plinth \xB7 **warning**\n\n**Statement.** A house should rest on a plinth: the lowest floor should contain a `plinth` object.\n\n**Rationale.** The plinth is the raised base the building sits on \u2014 it lifts the ground floor above grade and gives the walls a footing. A lowest floor with rooms but no plinth reads as a slab-on-grade shortcut; most Konkan houses want an explicit plinth. (A style guide, so it only warns \u2014 a deliberately plinth-less design is allowed.)\n\n**Fix.**\n\nAdd a `plinth` to the lowest floor (usually the Plinth floor 0, alongside the `ground`), sized to cover the built footprint.\n\n---\n\n## C14 \u2014 The highest floor should carry a roof \xB7 **warning**\n\n**Statement.** A house should be capped by a roof: the highest floor should contain a `roof` object.\n\n**Rationale.** The roof sits on its own floor stacked above the walls (see the roof convention). A design whose top floor has no roof leaves the house open \u2014 usually a roof that was forgotten, or a floor added above the roof. (A style guide, so it only warns \u2014 a deliberate flat terrace with no roof is allowed.)\n\n**Fix.**\n\nAdd a `roof` to the highest floor (a floor stacked above the top occupied floor), with segments spanning the footprint.\n\n---\n\n## C15 \u2014 The plinth should cover the rooms that rest on it \xB7 **warning**\n\n**Statement.** The plinth footprint should contain every room on the lowest occupied floor \u2014 no ground-floor room sticking out past the plinth.\n\n**Rationale.** The plinth is the base the ground floor stands on. A room whose footprint extends beyond the plinth has part of its floor unsupported by the base. (Upper floors that cantilever past the plinth are a different case \u2014 those want pillars; see the cantilever guidance. This checks only the floor that sits directly on the plinth.)\n\n**Fix.**\n\nGrow the plinth (its size, or the plot variables it derives from) to cover the room, or pull the room back within the plinth.\n\n---\n\n## C16 \u2014 A room overhanging the floor below should have pillars under it \xB7 **warning**\n\n**Statement.** If a room on floor N extends beyond the rooms of the floor below (a cantilever), there should be pillars supporting the overhang.\n\n**Rationale.** An upper-floor room that sticks out past the walls below has nothing under its overhang. In a real build that extension needs columns at its outside edge. This warns when an overhanging room has no pillar anywhere near it. (A style guide \u2014 a genuinely cantilevered slab design is allowed; the warning just flags the missing support.)\n\n**Fix.**\n\nAdd `pillar` objects at the outside of the extension (under the overhanging edge), or pull the room back over the floor below.\n\n---\n\n## C17 \u2014 A hip roof segment's span should not exceed its ridge run \xB7 **warning**\n\n**Statement.** On a pitched roof with closed (hip) ends, a segment's span (`width`) should not exceed its ridge run (the `start`\u2192`end` length).\n\n**Rationale.** A closed hip end pulls the ridge inward by half the span to make room for the hip face. When the span exceeds the run, the two hip ends would meet past the centre, so the roof is clipped to a pyramid (the hip faces meet at a single apex) rather than the intended ridged hip. That is almost always a mis-oriented segment \u2014 the ridge drawn along the SHORTER dimension. It still renders as a valid pyramid, so this only warns.\n\n**Fix.**\n\nOrient the ridge along the LONGER dimension: swap the segment's `start`/`end` so it runs the long way, and set `width` to the shorter span. If a pyramid is genuinely intended, ignore this.\n\n---\n\n## C18 \u2014 Don't roof the same area twice \xB7 **warning**\n\n**Statement.** A roof segment should not sit entirely within an area another roof segment already covers.\n\n**Rationale.** Each roof segment spans a plan area (its ridge line \xB1 `width`). When a new segment (often a whole new `roof` object an agent added) falls completely inside the area an existing roof already covers, the two roofs overlap \u2014 redundant geometry that renders as z-fighting and doubles the material take-off. Almost always the fix is to extend the existing roof, not add another. (Only a segment FULLY inside prior coverage is flagged, so abutting segments and ridge joints in a legitimate multi-segment roof never false-warn.)\n\n**Fix.**\n\nRemove the redundant roof/segment, or if you meant to cover more area, extend an existing segment's `width`/`end` instead of adding an overlapping one.\n\n---\n\n## C19 \u2014 Prefer one or two flights per floor when space allows \xB7 **warning**\n\n**Statement.** A staircase should climb a floor in one or two flights unless the floor space is genuinely tight.\n\n**Rationale.** A box-model staircase derives its flight count from the run it is given: too short a box forces extra switchback flights. Agents routinely under-size the box and get cramped 3-4 flight stairs where the floor had room for a straight run or a single U-turn. Fewer flights are easier to build and to walk. (A warning, since a tight plot may legitimately need a compact switchback.)\n\n**Fix.**\n\nLengthen the staircase along its run axis (the box `length` for a N/S stair, `width` for E/W) to the reported minimum, or reduce `landing_depth`. The warning gives the exact length for one and two flights.\n\n---\n\n## C20 \u2014 A staircase's top landing must reach a room \xB7 **warning**\n\n**Statement.** The top landing of a staircase should abut (or sit inside) a room on the floor it arrives at, so there is a way off the stair onto the floor.\n\n**Rationale.** A switchback's arrival landing lands wherever the run ends, which is hard to predict and easy to get wrong (often the direction is simply flipped). When the top landing ends against a blank wall or in open space, the stair reaches the next level but there is no way onto the floor. This checks the resolved arrival rectangle against the rooms of the arrival floor. (A warning, since a landing that opens onto an outdoor terrace may not overlap a room.)\n\n**Fix.**\n\nPlace the staircase so its top landing meets a room (leave that room's wall open there or add a door), or flip the `direction`/`turn` so the landing ends on the room side. The warning reports the arrival rectangle and which way it faces.\n\n---\n\n## C21 \u2014 The plinth should extend under a staircase \xB7 **warning**\n\n**Statement.** A staircase on the lowest occupied floor should sit entirely on the plinth \u2014 the plinth footprint should cover it.\n\n**Rationale.** The plinth is the base the ground floor stands on. An external staircase added past the building edge has its flights and landings resting on nothing unless the plinth is extended under it. Agents routinely add a stair to the outside and forget to grow the plinth. (Checks only the lowest occupied floor, the one that sits on the plinth; upper-floor stairs bear on that floor's slab.)\n\n**Fix.**\n\nGrow the plinth (its size, or the plot variables it derives from) so it covers the whole staircase footprint, or move the staircase inside the building over the plinth.\n\n---\n\n## C22 \u2014 A staircase needs an enclosing room or pillars to carry its landings \xB7 **warning**\n\n**Statement.** A staircase should be enclosed by a room of (at least) its own footprint, or have pillars under it \u2014 something to carry the flights and turn landings.\n\n**Rationale.** Switchback landings are elevated slabs; the flights land on them. In a real build the surrounding walls (a stairwell) or columns carry that load. A free-standing staircase with no enclosing room and no pillars has landings hanging in the air. (A warning: an open stair against a structural wall may be fine, but the common agent mistake is a stair floating in open space.)\n\n**Fix.**\n\nPut the staircase inside a room that covers its footprint (the walls carry the landings), or add `pillar` objects under the landings.\n\n---\n\n## C23 \u2014 A staircase's steps should be a realistic size \xB7 **warning**\n\n**Statement.** A staircase's `step_rise` and `step_tread`, converted to real-world size, should fall in the human range \u2014 about a 6-7 in rise and a 10-12 in going.\n\n**Rationale.** Stair steps are physically fixed regardless of the house, so they are the reliable tell for a scale mistake. Agents often copy a staircase from another example that is in different units (metres vs feet), producing steps that are absurdly large or tiny. This converts the steps to inches using the model's `units` and flags anything outside a generous human range.\n\n**Fix.**\n\nRescale the staircase to THIS model's units. The warning gives the sensible `step_rise`/`step_tread` for this model (1 ft = `per_unit` units by default 10, so about `step_rise 6`, `step_tread 10`).\n\n---\n\n## C24 \u2014 A staircase needs a slab under it, not just a plinth \xB7 **warning**\n\n**Statement.** When a staircase's floor has a slab (slab_thickness > 0), a slab should extend under the whole staircase footprint.\n\n**Rationale.** A staircase's base rests at the floor's walking surface \u2014 its `z_offset` defaults to the floor `slab_thickness`, so it sits on TOP of the slab. If the slab does not reach under the stair (a common miss on an external stair, where the plinth was extended but the slab was not), there is a `slab_thickness` gap between the bottom of the stairs and the plinth where the slab should be. Extending only the plinth (C21) is not enough. (Skipped when the floor has no slab \u2014 `slab_thickness 0` \u2014 since the stair then rests directly on the plinth.)\n\n**Fix.**\n\nAdd or grow a `slab` on the staircase's floor so it covers the whole staircase footprint, matching the plinth below it.\n\n---\n\n## SP1 \u2014 A spiral staircase's central pole must be smaller than its radius \xB7 **error**\n\n**Statement.** A `spiral_staircase`'s `pole_radius` must be less than its outer `radius`.\n\n**Rationale.** The treads run from the central pole out to the outer radius. If the pole is as wide as (or wider than) the stair, there is no tread left to stand on \u2014 the geometry collapses.\n\n**Fix.**\n\nReduce `pole_radius` below `radius` (a pole is typically a small fraction of the radius).\n\n---\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Design guidelines (advisory \u2014 NOT linted)\n\nGood-practice guidance the linter does not check. Apply your judgement; these are\nstyle, not rules:\n\n- **Compact, rectangular layout.** Keep the plan as rectangular as possible, with\n the minimum of nooks and crannies. A blocky footprint is cheaper to build, easier\n to roof, and wastes less wall.\n- **Room sizes follow use.** Size each room to its utilisation. The living room is\n usually the largest, then rooms like the kitchen, workshop, and bedrooms; a\n bathroom should be smaller than the bedroom it serves.\n- **Verandahs & balconies get half-height walls.** Give a verandah or balcony a\n half-height (parapet) wall rather than a full-height one \u2014 a full-height verandah\n reads as an enclosed room. (Not linted: Wadi has no verandah/balcony marker, so\n there is nothing to key a warning on without matching room names.)\n- **Staircase in a multi-storey house.** Reserve a dedicated stair space on each\n floor. The staircase starts on the lowest floor and rises to the underside of the\n topmost occupied floor (not the roof floor). Size the stair space so climbing one\n storey takes at most two flights (use `max_run` on the `staircase` to switchback).\n"
434382
+ "body": "# Wadi structural conventions (coding guidelines)\n\n<!-- GENERATED FILE \u2014 do not edit conventions.md by hand. It is built from\n conventions.preamble.md + the constraint modules in editor/src/lint/constraints.\n Regenerate with `npm --prefix editor run gen-conventions-doc`. -->\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026). Each convention is a\nself-contained module under `editor/src/lint/constraints/` (its check + this doc +\nits example fixtures), and **this file is generated from those modules**\n(`editor/scripts/gen-conventions-doc.mjs`) \u2014 so the doc and the linter cannot\ndrift. Add a rule by adding a constraint module and regenerating.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor's base elevation = the running sum of the previous floors' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor's walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor's height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set an explicit `height`, and that height must equal the plinth block's `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth block rises to `plinth.height`. If they differ, the floor above floats above the plinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor `height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 \"Plinth\" height 40 { // == the plinth block height below\n ground name \"Ground\" at (0,0) size (500,500)\n plinth name \"Plinth\" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is consistent by construction \u2014 but set the floor `height` explicitly anyway, so the stack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every side that faces **outside** (no room beyond it). Interior (shared) sides may be omitted \u2014 the neighbour's wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no `wall` lines) is enclosed on all four sides**. But the moment you add a `wall` line to hang a door or window, the room switches to a *whitelist* \u2014 every side you don't list is now a hole. An exterior hole leaves the room open to the weather. It is a **warning**, not an error, because an open exterior side is sometimes intentional (a verandah / open padvi).\n\n**Fix.**\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object** must set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor's walls stand on (`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is no deck, so every wall on the floor floats `slab_thickness` units above the floor base. Setting it to `0` puts the walls on the floor base; alternatively, model the deck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor of just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is harmless.)*\n\n---\n\n## C4 \u2014 A stacked floor's height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set `height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor's walls stand on the deck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor above leaves a gap over the walls; when smaller, the walls poke through it. It is a **warning** \u2014 a deliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they should match.\n\n**Fix.**\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing stacks on its walls.)*\n\n---\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase's descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Only a `climb down` (top-anchored) stair can fall below ground: you place it on the **upper** floor and it **descends**. Put it on the wrong floor, or give it too large a `total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D plans (which ignore Z) but is **buried and invisible in 3D**, with no other error. A `climb up` stair is anchored on its own floor and ascends, so it never trips this.\n\n**Fix.**\n\nPrefer **`climb up`**: put the stair on the **lower** floor it rises FROM and let it ascend.\n\n```wdl\nfloor 1 \"Ground Floor\" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name \"Stair\" at (212, 64) step (7, 11, 44) // `at` = the BOTTOM (this floor)\n direction south climb up // ascends to the floor above\n}\n```\n\n(Or, if you must keep it `climb down`, move it **up one floor** or reduce `total_height`.)\n\n---\n\n## C6 \u2014 Openings on the same wall must not overlap \xB7 **error**\n\n**Statement.** Two openings (doors/windows) cut into the **same physical wall** must not overlap along it. This includes openings that belong to **two different rooms sharing a boundary wall**.\n\n**Rationale.** Each opening is a boolean-subtract from the wall. Overlapping spans merge into one ragged hole (or fight over the same brick), which is never what you meant \u2014 and on a shared wall it silently punches a bigger gap than either room's plan shows.\n\n**Fix.**\n\nOffset or narrow one opening so the spans are disjoint. An opening's span is its resolved `[offset, offset+width]` along the wall \u2014 the `from start|center|end` anchor is honoured (its offset is converted to a start-based position first, exactly as the renderer does).\n\n---\n\n## C7 \u2014 Furniture items should not overlap \xB7 **warning**\n\n**Statement.** Two furniture `item`s whose plan footprints overlap are flagged \u2014 as a **warning**, because it is sometimes intentional (a rug under a table, a lamp on a desk, deliberately stacked pieces).\n\n**Rationale.** More often it's a placement slip \u2014 two beds dropped on the same spot, or an anchored piece that reflowed into another when a room was resized. The footprint used is the item's rotated bounding box (yaw-aware), so it matches what the plan draws.\n\n**Fix.**\n\nReposition one item, or ignore the warning if the overlap is deliberate.\n\n---\n\n## C8 \u2014 Two abutting rooms need a partition between them \xB7 **warning**\n\n**Statement.** Where two rooms share a boundary line and **neither** declares a wall on it, there is no partition between them.\n\n**Rationale.** A bare room (no `wall` lines) is enclosed on all four sides, so two bare neighbours have two walls on their shared line. But once **both** rooms switch to partial `walls` lists and both omit the shared side, the centreline is left open \u2014 the rooms merge into one space with no divider. C2 only guards *exterior* sides; this is its interior counterpart. It is a **warning** because an intentional open-plan link (kitchen into living) is legitimate.\n\n**Fix.**\n\nDeclare the wall on **one** of the two rooms (the neighbour's wall stands on the shared centreline, so one is enough):\n\n```wdl\nroom Kitchen at (\u2026) size (\u2026) { wall north south east } // east = the shared line\nroom Living at (\u2026) size (\u2026) { wall north south west }\n```\n\n---\n\n## C9 \u2014 A floor's slab_thickness should match its slab object's thickness \xB7 **warning**\n\n**Statement.** When a floor carries a `floor_slab` object with an explicit `thickness`, that thickness should equal the floor's `slab_thickness`.\n\n**Rationale.** The floor's `slab_thickness` is the deck the walls stand on (`wallZ = base + slab_thickness`); the slab object's own `thickness` is how thick the slab MESH is drawn. If they differ, the walls sit at the floor's `slab_thickness` while the slab top is at the object's `thickness`, so the walls float above or sink into the drawn deck. (A slab with no explicit `thickness` follows the floor's `slab_thickness` and is consistent by construction \u2014 this only fires when both are set and disagree.)\n\n**Fix.**\n\nMake them equal \u2014 most simply, drop the slab's explicit `thickness` so it follows the floor:\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 8 {\n slab name \"Deck\" at (\u2026) size (\u2026) // no thickness \u2192 uses 8\n}\n```\n\n---\n\n## C10 \u2014 The roof should cover the rooms of the top occupied floor \xB7 **warning**\n\n**Statement.** Every room on the top occupied floor should sit under a roof segment \u2014 no room left entirely uncovered.\n\n**Rationale.** The roof's segments span a plan area (each segment's ridge line \xB1 its `width`). A room on the top floor whose footprint does not overlap **any** roof segment has open sky above it \u2014 usually a roof that was sized to the wrong footprint, or a room added after the roof. (Only a *completely* uncovered room is flagged, so eave overhangs and partial coverage never false-warn; a house with no roof at all \u2014 a terrace \u2014 is not flagged.)\n\n**Fix.**\n\nExtend or add a roof segment to span the room, or reduce the room. Roof segments cover `start \u2192 end` along the ridge, `width` across it, so grow `width`/`end` (or the plot variables they derive from) until the room is under it.\n\n---\n\n## C11 \u2014 A declared connection must overlap on a wall and be passable (door or open) \xB7 **error**\n\n**Statement.** For every `connect`ion a room declares, the two rooms must **overlap on a wall** (not necessarily the whole wall), and that overlap must be **passable**: either a **door** lies in it, or the wall is **left off both rooms** (an open passage).\n\n**Rationale.** A connection is a FUNCTIONAL requirement \u2014 `Living` opens into `Kitchen`. It is design intent, not geometry (the renderer never draws it), so this constraint is what verifies the intent is physically realized. It fails two ways: the rooms' walls don't overlap at all, or they overlap but a solid wall (present on either room, no door in the overlap) blocks the way. No door is ever generated \u2014 a room authors its own openings, or omits the shared wall to leave the rooms open to each other.\n\n**Fix.**\n\nOverlap the two rooms on a wall, then EITHER put a door in the overlap (on either room), OR omit that wall on both:\n\n```wdl\n// door in the shared wall\nroom Living at (\u2026) size (\u2026) { connect Kitchen wall east { door D at 80 size (40,210) } }\nroom Kitchen at (\u2026) size (\u2026)\n\n// open passage \u2014 neither room walls the shared side\nroom Living at (\u2026) size (\u2026) { connect Kitchen wall north south west }\nroom Kitchen at (\u2026) size (\u2026) { wall north south east }\n```\n\n---\n\n## C12 \u2014 Rooms should not overlap (they share walls, not floor area) \xB7 **warning**\n\n**Statement.** Two `room`s on the same floor should not overlap in plan \u2014 flagged as a **warning**, because it is occasionally intentional (embedding a corner room to carve an L-shaped space). Adjacent rooms may **touch** on a shared wall (their edges coincide); a larger intersection is reported.\n\n**Rationale.** Rooms usually share walls, not floor area. A real overlap means two rooms were placed on the same spot \u2014 the renderer draws one over the other. It most often happens when a room is placed by absolute coordinates, or when a band (a verandah, a corridor) is dropped across an existing wing. C11 checks that declared connections are realized; this checks that the geometry is physically consistent. It stays a warning because an L-shaped room is modelled by overlapping a small corner room onto a larger bounding one.\n\n**Fix.**\n\nIf the overlap is unintended, move or resize one room so they only touch on a shared wall (prefer relative placement \u2014 abut a neighbour on a side \u2014 over absolute coordinates that can land on top of another room). Ignore the warning if it is a deliberate corner embed.\n\n---\n\n## C13 \u2014 The lowest floor should carry a plinth \xB7 **warning**\n\n**Statement.** A house should rest on a plinth: the lowest floor should contain a `plinth` object.\n\n**Rationale.** The plinth is the raised base the building sits on \u2014 it lifts the ground floor above grade and gives the walls a footing. A lowest floor with rooms but no plinth reads as a slab-on-grade shortcut; most Konkan houses want an explicit plinth. (A style guide, so it only warns \u2014 a deliberately plinth-less design is allowed.)\n\n**Fix.**\n\nAdd a `plinth` to the lowest floor (usually the Plinth floor 0, alongside the `ground`), sized to cover the built footprint.\n\n---\n\n## C14 \u2014 The highest floor should carry a roof \xB7 **warning**\n\n**Statement.** A house should be capped by a roof: the highest floor should contain a `roof` object.\n\n**Rationale.** The roof sits on its own floor stacked above the walls (see the roof convention). A design whose top floor has no roof leaves the house open \u2014 usually a roof that was forgotten, or a floor added above the roof. (A style guide, so it only warns \u2014 a deliberate flat terrace with no roof is allowed.)\n\n**Fix.**\n\nAdd a `roof` to the highest floor (a floor stacked above the top occupied floor), with segments spanning the footprint.\n\n---\n\n## C15 \u2014 The plinth should cover the rooms that rest on it \xB7 **warning**\n\n**Statement.** The plinth footprint should contain every room on the lowest occupied floor \u2014 no ground-floor room sticking out past the plinth.\n\n**Rationale.** The plinth is the base the ground floor stands on. A room whose footprint extends beyond the plinth has part of its floor unsupported by the base. (Upper floors that cantilever past the plinth are a different case \u2014 those want pillars; see the cantilever guidance. This checks only the floor that sits directly on the plinth.)\n\n**Fix.**\n\nGrow the plinth (its size, or the plot variables it derives from) to cover the room, or pull the room back within the plinth.\n\n---\n\n## C16 \u2014 A room overhanging the floor below should have pillars under it \xB7 **warning**\n\n**Statement.** If a room on floor N extends beyond the rooms of the floor below (a cantilever), there should be pillars supporting the overhang.\n\n**Rationale.** An upper-floor room that sticks out past the walls below has nothing under its overhang. In a real build that extension needs columns at its outside edge. This warns when an overhanging room has no pillar anywhere near it. (A style guide \u2014 a genuinely cantilevered slab design is allowed; the warning just flags the missing support.)\n\n**Fix.**\n\nAdd `pillar` objects at the outside of the extension (under the overhanging edge), or pull the room back over the floor below.\n\n---\n\n## C17 \u2014 A hip roof segment's span should not exceed its ridge run \xB7 **warning**\n\n**Statement.** On a pitched roof with closed (hip) ends, a segment's span (`width`) should not exceed its ridge run (the `start`\u2192`end` length).\n\n**Rationale.** A closed hip end pulls the ridge inward by half the span to make room for the hip face. When the span exceeds the run, the two hip ends would meet past the centre, so the roof is clipped to a pyramid (the hip faces meet at a single apex) rather than the intended ridged hip. That is almost always a mis-oriented segment \u2014 the ridge drawn along the SHORTER dimension. It still renders as a valid pyramid, so this only warns.\n\n**Fix.**\n\nOrient the ridge along the LONGER dimension: swap the segment's `start`/`end` so it runs the long way, and set `width` to the shorter span. If a pyramid is genuinely intended, ignore this.\n\n---\n\n## C18 \u2014 Don't roof the same area twice \xB7 **warning**\n\n**Statement.** A roof segment should not sit entirely within an area another roof segment already covers.\n\n**Rationale.** Each roof segment spans a plan area (its ridge line \xB1 `width`). When a new segment (often a whole new `roof` object an agent added) falls completely inside the area an existing roof already covers, the two roofs overlap \u2014 redundant geometry that renders as z-fighting and doubles the material take-off. Almost always the fix is to extend the existing roof, not add another. (Only a segment FULLY inside prior coverage is flagged, so abutting segments and ridge joints in a legitimate multi-segment roof never false-warn.)\n\n**Fix.**\n\nRemove the redundant roof/segment, or if you meant to cover more area, extend an existing segment's `width`/`end` instead of adding an overlapping one.\n\n---\n\n## C19 \u2014 Prefer one or two flights per floor when space allows \xB7 **warning**\n\n**Statement.** A staircase should climb a floor in one or two flights unless the floor space is genuinely tight.\n\n**Rationale.** A box-model staircase derives its flight count from the run it is given: too short a box forces extra switchback flights. Agents routinely under-size the box and get cramped 3-4 flight stairs where the floor had room for a straight run or a single U-turn. Fewer flights are easier to build and to walk. (A warning, since a tight plot may legitimately need a compact switchback.)\n\n**Fix.**\n\nLengthen the staircase along its run axis (the box `length` for a N/S stair, `width` for E/W) to the reported minimum, or reduce `landing_depth`. The warning gives the exact length for one and two flights.\n\n---\n\n## C20 \u2014 A staircase's top landing must reach a room \xB7 **warning**\n\n**Statement.** The top landing of a staircase should abut (or sit inside) a room on the floor it arrives at, so there is a way off the stair onto the floor.\n\n**Rationale.** A switchback's arrival landing lands wherever the run ends, which is hard to predict and easy to get wrong (often the direction is simply flipped). When the top landing ends against a blank wall or in open space, the stair reaches the next level but there is no way onto the floor. This checks the resolved arrival rectangle against the rooms of the arrival floor. (A warning, since a landing that opens onto an outdoor terrace may not overlap a room.)\n\n**Fix.**\n\nPlace the staircase so its top landing meets a room (leave that room's wall open there or add a door), or flip the `direction`/`turn` so the landing ends on the room side. The warning reports the arrival rectangle and which way it faces.\n\n---\n\n## C21 \u2014 The plinth should extend under a staircase \xB7 **warning**\n\n**Statement.** A staircase on the lowest occupied floor should sit entirely on the plinth \u2014 the plinth footprint should cover it.\n\n**Rationale.** The plinth is the base the ground floor stands on. An external staircase added past the building edge has its flights and landings resting on nothing unless the plinth is extended under it. Agents routinely add a stair to the outside and forget to grow the plinth. (Checks only the lowest occupied floor, the one that sits on the plinth; upper-floor stairs bear on that floor's slab.)\n\n**Fix.**\n\nGrow the plinth (its size, or the plot variables it derives from) so it covers the whole staircase footprint, or move the staircase inside the building over the plinth.\n\n---\n\n## C22 \u2014 A staircase needs an enclosing room or pillars to carry its landings \xB7 **warning**\n\n**Statement.** A staircase should be enclosed by a room of (at least) its own footprint, or have pillars under it \u2014 something to carry the flights and turn landings.\n\n**Rationale.** Switchback landings are elevated slabs; the flights land on them. In a real build the surrounding walls (a stairwell) or columns carry that load. A free-standing staircase with no enclosing room and no pillars has landings hanging in the air. (A warning: an open stair against a structural wall may be fine, but the common agent mistake is a stair floating in open space.)\n\n**Fix.**\n\nPut the staircase inside a room that covers its footprint (the walls carry the landings), or add `pillar` objects under the landings.\n\n---\n\n## C23 \u2014 A staircase's steps should be a realistic size \xB7 **warning**\n\n**Statement.** A staircase's `step_rise` and `step_tread`, converted to real-world size, should fall in the human range \u2014 about a 6-7 in rise and a 10-12 in going.\n\n**Rationale.** Stair steps are physically fixed regardless of the house, so they are the reliable tell for a scale mistake. Agents often copy a staircase from another example that is in different units (metres vs feet), producing steps that are absurdly large or tiny. This converts the steps to inches using the model's `units` and flags anything outside a generous human range.\n\n**Fix.**\n\nRescale the staircase to THIS model's units. The warning gives the sensible `step_rise`/`step_tread` for this model (1 ft = `per_unit` units by default 10, so about `step_rise 6`, `step_tread 10`).\n\n---\n\n## C24 \u2014 A staircase needs a slab under it, not just a plinth \xB7 **warning**\n\n**Statement.** When a staircase's floor has a slab (slab_thickness > 0), a slab should extend under the whole staircase footprint.\n\n**Rationale.** A staircase's base rests at the floor's walking surface \u2014 its `z_offset` defaults to the floor `slab_thickness`, so it sits on TOP of the slab. If the slab does not reach under the stair (a common miss on an external stair, where the plinth was extended but the slab was not), there is a `slab_thickness` gap between the bottom of the stairs and the plinth where the slab should be. Extending only the plinth (C21) is not enough. (Skipped when the floor has no slab \u2014 `slab_thickness 0` \u2014 since the stair then rests directly on the plinth.)\n\n**Fix.**\n\nAdd or grow a `slab` on the staircase's floor so it covers the whole staircase footprint, matching the plinth below it.\n\n---\n\n## C25 \u2014 A pillar under a slab or landing should reach it \xB7 **warning**\n\n**Statement.** When a floor slab or a staircase landing sits directly over a pillar, the pillar should rise to the underside of it. A pillar that stops short leaves a gap and carries nothing.\n\n**Rationale.** A column exists to carry the slab or landing above it; if it stops below that level there is a gap and the load has nothing to bear on. Agents often shrink a copied pillar's height (or a configurator lowers it) so it no longer reaches. This checks the LOWEST floor slab / staircase landing that actually sits over the pillar \u2014 so a pillar added to carry a stair's turn landings is checked against those landings, and a pillar supporting only a roof (which slopes, no flat datum) or with nothing above is never flagged. (A warning \u2014 a deliberately low post under a slab is allowed.)\n\n**Fix.**\n\nRaise the pillar height so its top meets the slab/landing above it. The warning reports the gap and a suggested height.\n\n---\n\n## SP1 \u2014 A spiral staircase's central pole must be smaller than its radius \xB7 **error**\n\n**Statement.** A `spiral_staircase`'s `pole_radius` must be less than its outer `radius`.\n\n**Rationale.** The treads run from the central pole out to the outer radius. If the pole is as wide as (or wider than) the stair, there is no tread left to stand on \u2014 the geometry collapses.\n\n**Fix.**\n\nReduce `pole_radius` below `radius` (a pole is typically a small fraction of the radius).\n\n---\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Design guidelines (advisory \u2014 NOT linted)\n\nGood-practice guidance the linter does not check. Apply your judgement; these are\nstyle, not rules:\n\n- **Compact, rectangular layout.** Keep the plan as rectangular as possible, with\n the minimum of nooks and crannies. A blocky footprint is cheaper to build, easier\n to roof, and wastes less wall.\n- **Room sizes follow use.** Size each room to its utilisation. The living room is\n usually the largest, then rooms like the kitchen, workshop, and bedrooms; a\n bathroom should be smaller than the bedroom it serves.\n- **Verandahs & balconies get half-height walls.** Give a verandah or balcony a\n half-height (parapet) wall rather than a full-height one \u2014 a full-height verandah\n reads as an enclosed room. (Not linted: Wadi has no verandah/balcony marker, so\n there is nothing to key a warning on without matching room names.)\n- **Staircase in a multi-storey house.** Reserve a dedicated stair space on each\n floor. The staircase starts on the lowest floor and rises to the underside of the\n topmost occupied floor (not the roof floor). Size the stair space so climbing one\n storey takes at most two flights (use `max_run` on the `staircase` to switchback).\n"
434291
434383
  },
434292
434384
  "coordinate-system": {
434293
434385
  "title": "Coordinates, units & the centreline convention",