three-slicer 0.1.0

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 (54) hide show
  1. package/LICENSE.txt +661 -0
  2. package/README.md +44 -0
  3. package/components/README.md +39 -0
  4. package/components/dist/SettingsPanel.js +180 -0
  5. package/components/styles.css +84 -0
  6. package/data/README.md +22 -0
  7. package/data/config-schema-builddump.json +12921 -0
  8. package/data/config-schema.json +12685 -0
  9. package/data/invalidation-map.json +631 -0
  10. package/data/toggle-rules.json +2277 -0
  11. package/data/ui-tree.json +1586 -0
  12. package/engine/README.md +52 -0
  13. package/engine/examples/headless.mjs +37 -0
  14. package/engine/index.d.ts +29 -0
  15. package/engine/index.js +45 -0
  16. package/engine/src/settings.js +130 -0
  17. package/engine/src/slicer.worker.js +73 -0
  18. package/engine/src/slicer_core.js +0 -0
  19. package/engine/src/slicer_core.mt.js +0 -0
  20. package/engine/src/toggle_eval.js +78 -0
  21. package/package.json +74 -0
  22. package/viewer/README.md +68 -0
  23. package/viewer/dist/Viewport.js +1108 -0
  24. package/viewer/dist/make_worker.js +9 -0
  25. package/viewer/dist/model_loaders.js +144 -0
  26. package/viewer/dist/toolpath_gpu.js +386 -0
  27. package/viewer/src/Viewport.jsx +1353 -0
  28. package/viewer/src/assets/add.svg +1 -0
  29. package/viewer/src/assets/arrange.svg +1 -0
  30. package/viewer/src/assets/boolean.svg +1 -0
  31. package/viewer/src/assets/cut.svg +1 -0
  32. package/viewer/src/assets/delete.svg +1 -0
  33. package/viewer/src/assets/deleteall.svg +1 -0
  34. package/viewer/src/assets/duplicate.svg +1 -0
  35. package/viewer/src/assets/measure.svg +1 -0
  36. package/viewer/src/assets/mmu.svg +1 -0
  37. package/viewer/src/assets/move.svg +1 -0
  38. package/viewer/src/assets/negative.svg +1 -0
  39. package/viewer/src/assets/onbed.svg +1 -0
  40. package/viewer/src/assets/open.svg +1 -0
  41. package/viewer/src/assets/orient.svg +1 -0
  42. package/viewer/src/assets/paint.svg +1 -0
  43. package/viewer/src/assets/rotate.svg +1 -0
  44. package/viewer/src/assets/scale.svg +1 -0
  45. package/viewer/src/assets/seam.svg +1 -0
  46. package/viewer/src/assets/split.svg +1 -0
  47. package/viewer/src/assets/textmark.svg +1 -0
  48. package/viewer/src/assets/varlayer.svg +1 -0
  49. package/viewer/src/icons.js +23 -0
  50. package/viewer/src/make_worker.js +9 -0
  51. package/viewer/src/model_loaders.js +178 -0
  52. package/viewer/src/shadow_host.jsx +30 -0
  53. package/viewer/src/toolpath_gpu.js +430 -0
  54. package/viewer/styles.css +231 -0
@@ -0,0 +1,1108 @@
1
+ import n, { useRef as g, useState as x, useLayoutEffect as Wr, useEffect as We } from "react";
2
+ import * as f from "three";
3
+ import { OrbitControls as Xr } from "three/examples/jsm/controls/OrbitControls.js";
4
+ import { TransformControls as Yr } from "three/examples/jsm/controls/TransformControls.js";
5
+ import { deriveKernelParams as Gt, settingRaw as gt } from "three-slicer/settings";
6
+ import { makeSlicerWorker as Kr } from "./make_worker.js";
7
+ import { createPortal as Jr } from "react-dom";
8
+ import { VIEW_TYPES as Qr, DEFAULT_RANGES_COLORS as ea, roleRatios as Fn, buildSegmentData as ta, makeToolpath as na, computeColors as Vn } from "./toolpath_gpu.js";
9
+ import { splitConnectedComponents as ra, SUPPORTED_EXT as aa, fileExt as oa, loadModel as la } from "./model_loaders.js";
10
+ function sa({ css: L, className: $, children: R }) {
11
+ const J = g(null), [c] = x(() => {
12
+ const N = document.createElement("div");
13
+ return N.style.display = "contents", N;
14
+ });
15
+ return Wr(() => {
16
+ const N = J.current, z = N.shadowRoot || N.attachShadow({ mode: "open" });
17
+ let w = z.querySelector("style[data-ts-css]");
18
+ w || (w = document.createElement("style"), w.setAttribute("data-ts-css", ""), z.append(w)), w.textContent = L, z.contains(c) || z.append(c);
19
+ }, [L, c]), /* @__PURE__ */ n.createElement("div", { ref: J, className: $ }, Jr(R, c));
20
+ }
21
+ const ia = ":host{display:contents}*{box-sizing:border-box}.app-shell{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;background:#0e1216;color:#cdd6dd;font:14px/1.5 -apple-system,Segoe UI,sans-serif}.app-body{flex:1 1 auto;display:flex;min-height:0}.topbar{flex:0 0 44px;height:44px;display:flex;align-items:center;padding:0 12px;gap:10px;background:#161b21;border-bottom:1px solid #262d35}.topbar .tb-left,.topbar .tb-right{flex:1 1 0;display:flex;align-items:center;gap:8px}.topbar .tb-right{justify-content:flex-end}.tb-logo{font-size:15px;color:#e6edf3;letter-spacing:.01em}.tb-logo b{color:#00ae42}.tb-re{font-size:10px;background:#00ae42;color:#fff;padding:1px 5px;border-radius:4px;margin-left:2px}.tb-btn{display:inline-flex;align-items:center;gap:5px;background:#20272f;border:1px solid #2c353d;color:#cdd6dd;border-radius:6px;padding:4px 10px;cursor:pointer;font-size:12px}.tb-btn img{width:15px;height:15px}.tb-btn:hover{background:#28313a}.tb-tabs{display:flex;border:1px solid #2c353d;border-radius:8px;overflow:hidden;flex:0 0 auto}.tb-tabs button{padding:6px 24px;border:0;background:#1a2027;color:#9fb3c0;font-weight:600;font-size:13px;cursor:pointer}.tb-tabs button.on{background:#00ae42;color:#fff}.tb-tabs button:disabled{color:#5a6570;cursor:not-allowed}.tb-icon{width:28px;height:28px;border:1px solid #2c353d;background:#20272f;color:#7d8b96;border-radius:6px;font-size:15px;cursor:not-allowed}.left-rail{flex:0 0 48px;display:flex;flex-direction:column;align-items:center;gap:6px;padding:9px 0;background:#12171c;border-right:1px solid #232a31}.left-rail button{width:36px;height:36px;border:1px solid transparent;border-radius:8px;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}.left-rail button img{width:21px;height:21px;opacity:.72}.left-rail button:hover{background:#1e252c}.left-rail button.on{background:#00ae42}.left-rail button.on img{opacity:1;filter:brightness(1.6)}.rail-sep{width:26px;height:1px;background:#2a323a;margin:3px 0}.viewport-col{position:relative;flex:1 1 auto;min-width:0;background:#161a1e}.vp-top-toolbar{position:absolute;top:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:3px;background:#12171cd9;padding:4px;border-radius:9px;border:1px solid #2a323a;z-index:3;max-width:calc(100% - 24px);overflow-x:auto;scrollbar-width:none}.vp-top-toolbar::-webkit-scrollbar{display:none}.vp-top-toolbar>*{flex:0 0 auto}.vp-top-toolbar button{width:32px;height:32px;border:0;background:transparent;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center}.vp-top-toolbar button img{width:18px;height:18px;opacity:.82}.vp-top-toolbar button:hover:not(:disabled){background:#2a333c}.vp-top-toolbar button:disabled{opacity:.32;cursor:not-allowed}.vtt-sep{width:1px;align-self:stretch;background:#333c45;margin:3px}.plate-bar{position:absolute;right:14px;bottom:30px;display:flex;align-items:center;gap:4px;z-index:3;background:#12171cd9;border:1px solid #2a323a;border-radius:9px;padding:4px}.plate-bar button{min-width:26px;height:26px;border:1px solid #2c353d;background:#1a2027;color:#9fb3c0;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600}.plate-tab.on{background:#00ae42;color:#fff;border-color:#00ae42}.plate-add{color:#7ad19a!important}.plate-del{color:#e08a8a!important}.plate-bar button:disabled{opacity:.4;cursor:not-allowed}.slice-dd{position:relative;flex:1.4}.slice-dd .slice-btn{width:100%}.slice-menu{position:absolute;bottom:calc(100% + 6px);left:0;right:0;background:#fff;border:1px solid #d5d8dd;border-radius:8px;box-shadow:0 4px 16px #0000002e;overflow:hidden;z-index:10}.slice-menu button{display:block;width:100%;text-align:left;padding:9px 12px;border:0;background:#fff;color:#24282e;cursor:pointer;font-size:13px}.slice-menu button:hover{background:#eef7f1}.brush-panel{position:absolute;top:58px;left:14px;width:214px;background:#161b21f2;border:1px solid #2c353d;border-radius:10px;padding:10px;z-index:4;box-shadow:0 3px 14px #00000073}.bp-title{font-weight:600;margin-bottom:6px;color:#cdd6dd}.bp-modes{display:flex;gap:4px;flex-wrap:wrap}.bp-modes button{padding:3px 9px;border:1px solid #2c353d;background:#1a2027;color:#cdd6dd;border-radius:5px;cursor:pointer;font-size:12px}.bp-modes button.enf.on{background:#2b6cff;color:#fff;border-color:#2b6cff}.bp-modes button.blk.on{background:#e23b3b;color:#fff;border-color:#e23b3b}.bp-radius{display:block;font-size:12px;color:#aebcc6;margin-top:8px}.bp-radius input{width:100%}.bp-counts{margin-top:6px;font-size:11px}.stats-card{position:absolute;left:14px;bottom:32px;background:#161b21ed;border:1px solid #2c353d;border-radius:10px;padding:10px 14px;font-size:13px;line-height:1.7;z-index:2;color:#cdd6dd}.stats-card b{color:#9fe3bd}.sidebar{flex:0 0 384px;width:384px;display:flex;flex-direction:column;background:#eef0f2;color:#24282e;border-left:1px solid #d5d8dd;min-height:0}.sidebar-scroll{flex:1 1 auto;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:10px}.side-card{background:#fff;border:1px solid #e2e4e8;border-radius:10px;padding:10px 12px}.sc-head{font-weight:700;font-size:13px;color:#2a2f36;display:flex;align-items:center;gap:6px;margin-bottom:7px}.sc-count{background:#00ae42;color:#fff;font-size:10px;border-radius:8px;padding:0 6px;font-weight:700}.sc-head-btns{margin-left:auto;display:flex;gap:4px}.sc-head-btns button{width:22px;height:22px;border:1px solid #d3d6db;background:#f6f7f8;border-radius:5px;cursor:pointer;font-size:14px;line-height:1;color:#333}.sc-head-btns button:disabled{opacity:.4;cursor:not-allowed}.sc-info{display:flex;justify-content:space-between;font-size:12px;color:#5a6069;padding:2px 0}.sc-info b{color:#24282e}.side-warn{margin:0 2px;font-size:12px}.filament-row{display:flex;align-items:center;gap:8px;padding:3px 0}.filament-row input[type=color]{width:28px;height:22px;border:1px solid #ccc;border-radius:5px;padding:0;cursor:pointer;background:none}.fil-t{font-weight:700;font-size:12px;width:20px}.fil-swatch{width:15px;height:15px;border-radius:4px;border:1px solid rgba(0,0,0,.15)}.fil-hex{font-size:11px;margin-left:auto}.obj-list2{list-style:none;margin:0 0 6px;padding:0}.obj-list2 li{display:flex;align-items:center;gap:6px;padding:3px 0;font-size:12px}.obj-list2 li.obj-hidden{opacity:.5}.obj-eye{border:0;background:none;cursor:pointer;font-size:13px;padding:0}.obj-list2 .obj-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#24282e}.obj-list2 .obj-ext{border:1px solid #d0d3d8;border-radius:5px;font-size:11px;padding:1px 3px;background:#fff}.obj-del{border:0;background:#fbe9ec;color:#d0435a;border-radius:5px;cursor:pointer;padding:0 6px}.side-card .slice-support{color:#444;font-size:12px;margin:5px 0 0}.process-card{padding:8px}.side-card .view-type-row{color:#444}.side-card .view-type-row select,.side-card .obj-ext{background:#fff;color:#222;border:1px solid #ccd0d5}.side-card .slice-layer label{color:#444;font-size:12px}.side-card .grad-title{color:#333}.side-card .grad-minmax{color:#666}.side-card .role-legend,.side-card .slice-travel{color:#555}.side-card .layer-ctl button{background:#f1f2f4;color:#333;border:1px solid #d3d6db}.side-card .layer-ctl button.on{background:#00ae42;color:#fff;border-color:#00ae42}.side-bottom{flex:0 0 auto;display:flex;gap:8px;padding:10px;border-top:1px solid #dcdfe3;background:#e6e9ec}.side-bottom .slice-btn{flex:1.4;margin:0}.export-btn{flex:1;text-align:center;padding:9px;border-radius:8px;background:#dfe6ea;color:#1f6feb;border:1px solid #c7d2da;text-decoration:none;font-weight:600;cursor:pointer;font-size:13px}.export-btn:hover{background:#d3dee4}.export-btn:disabled{color:#9aa4ad;background:#e9ecef;cursor:not-allowed}.vp-canvas{position:absolute;top:0;right:0;bottom:0;left:0}.vp-canvas canvas{display:block}.vp-canvas.fail{display:flex;align-items:center;justify-content:center}.vp-fallback{color:#f0c9a8;padding:24px;text-align:center;max-width:560px;line-height:1.5}.vp-status{position:absolute;bottom:8px;left:12px;right:12px;z-index:1;font-size:11.5px;color:#9fe3bd;font-family:ui-monospace,monospace;text-shadow:0 1px 2px #000;pointer-events:none}.slice-warn{color:#f0c060;margin:4px 0}.slice-btn{width:100%;margin-top:6px;padding:7px;border:0;border-radius:7px;background:#00ae42;color:#fff;font-weight:700;cursor:pointer}.slice-btn:disabled{background:#3a4650;color:#8b98a2;cursor:not-allowed}.slice-err{color:#ff8b8b;margin-top:6px}.slice-stats{margin-top:8px;line-height:1.5}.slice-stats b{color:#9fe3bd}.slice-layer{margin-top:8px;display:flex;flex-direction:column;gap:4px}.slice-layer input[type=range]{width:100%}.slice-travel{color:#aebcc6;display:flex;align-items:center;gap:4px}.view-type-row{display:flex;align-items:center;justify-content:space-between;gap:6px;color:#aebcc6}.view-type-row select{flex:1;background:#10141a;color:#eee;border:1px solid #2c353d;border-radius:4px;padding:2px 4px}.dual-slider{position:relative;height:22px}.dual-slider input[type=range]{position:absolute;left:0;top:0;width:100%;margin:0;pointer-events:none;background:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.dual-slider input[type=range]::-webkit-slider-thumb{pointer-events:auto;-webkit-appearance:none;width:13px;height:13px;border-radius:50%;background:#00ae42;border:2px solid #0c1013;cursor:pointer}.dual-slider input[type=range]::-moz-range-thumb{pointer-events:auto;width:13px;height:13px;border-radius:50%;background:#00ae42;border:2px solid #0c1013;cursor:pointer}.dual-slider input[type=range]::-webkit-slider-runnable-track{height:4px;background:#2c353d;border-radius:2px}.dual-slider input[type=range]:first-child{z-index:2}.layer-ctl{display:flex;align-items:center;gap:8px}.layer-ctl button{padding:2px 8px;border:1px solid #2c353d;border-radius:5px;background:#1a2027;color:#cdd6dd;font-size:11px;cursor:pointer}.layer-ctl button.on{background:#00ae42;color:#fff;border-color:#00ae42}.grad-legend{margin-top:6px}.grad-title{font-size:11px;color:#cdd6dd;margin-bottom:3px}.grad-bar{height:10px;border-radius:3px;border:1px solid #2c353d}.grad-minmax{display:flex;justify-content:space-between;font-size:10px;color:#aebcc6;margin-top:2px}.role-legend{display:flex;flex-wrap:wrap;gap:4px 10px;margin-top:6px;font-size:11px;color:#aebcc6}.role-item{display:inline-flex;align-items:center;gap:4px}.role-item i{width:10px;height:6px;border-radius:2px;display:inline-block}.role-item b{color:#cdd6dd}.vp-canvas.drag-over{outline:3px dashed #00ae42;outline-offset:-6px}.empty-hint{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;pointer-events:none;color:#9fb3c0;text-align:center}.empty-hint .eh-icon{font-size:46px;opacity:.8}.empty-hint .eh-title{font-size:16px;font-weight:600;color:#cdd6dd}.empty-hint .eh-sub{font-size:12px;color:#7d8b96;letter-spacing:.04em}.empty-hint .eh-btn{pointer-events:auto;margin-top:8px;padding:7px 18px;border:0;border-radius:7px;background:#00ae42;color:#fff;font-weight:600;cursor:pointer}.empty-hint .eh-btn:hover{background:#06c04d}.drop-overlay{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:#00ae4224;color:#d7f7e3;font-size:18px;font-weight:700;pointer-events:none;border:3px dashed #00ae42;box-sizing:border-box}.obj-split{border:0;background:transparent;cursor:pointer;padding:0 3px;line-height:0}.obj-split img{width:13px;height:13px;opacity:.6}.obj-split:hover img{opacity:1}.ctx-scrim{position:absolute;top:0;right:0;bottom:0;left:0;z-index:24}.ctx-menu{position:absolute;z-index:25;min-width:168px;padding:4px;background:#1b2027;border:1px solid #2f3944;border-radius:8px;box-shadow:0 8px 24px #00000080}.ctx-menu button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:16px;padding:6px 10px;border:0;border-radius:5px;background:transparent;color:#dfe6ee;font-size:12px;text-align:left;cursor:pointer}.ctx-menu button:hover:not(:disabled){background:#273140}.ctx-menu button:disabled{color:#64707d;cursor:not-allowed}.ctx-menu button.danger:hover:not(:disabled){background:#4a2229;color:#ffb3b3}.ctx-menu hr{margin:4px 6px;border:0;border-top:1px solid #2f3944}.ctx-key{color:#7d8b96;font-family:ui-monospace,monospace;font-size:11px}.help-overlay{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:#080c10b8;z-index:20}.help-card{background:#1b2027;color:#dfe6ee;border:1px solid #2f3944;border-radius:10px;padding:18px 22px;max-width:720px;box-shadow:0 12px 40px #00000080}.help-card h3{margin:0 0 12px;font-size:15px}.help-card h4{margin:0 0 6px;font-size:12px;color:#00ae42;text-transform:uppercase;letter-spacing:.04em}.help-cols{display:flex;gap:26px;flex-wrap:wrap}.help-card dl{display:grid;grid-template-columns:auto 1fr;gap:3px 12px;margin:0;font-size:12px}.help-card dt{color:#9fb0c2;font-family:ui-monospace,monospace;white-space:nowrap}.help-card dd{margin:0}.slice-support{display:flex;align-items:center;gap:5px;margin:6px 0;color:#cdd6dd;font-size:12px}.slice-support .muted{font-size:10px}.sc-bed{display:inline-flex;align-items:center;gap:4px;font-weight:700;color:#222}.sc-bed input{width:54px;padding:1px 4px;font-size:12px;font-weight:600;text-align:right;border:1px solid #ccd0d5;border-radius:5px;background:#fff;color:#222}", ca = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h3m2,0h3m-4-4v8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), da = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M33.5,35H5.5A1.5,1.5,0,0,1,4,33.5V5.5A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v28A1.5,1.5,0,0,1,33.5,35ZM5.5,5a.5.5,0,0,0-.5.5v28a.5.5,0,0,0,.5.5h28a.5.5,0,0,0,.5-.5V5.5a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/><path d="M30.5,32H8.5A1.5,1.5,0,0,1,7,30.5v-6A1.5,1.5,0,0,1,8.5,23h22A1.5,1.5,0,0,1,32,24.5v6A1.5,1.5,0,0,1,30.5,32Zm-22-8a.5.5,0,0,0-.5.5v6a.5.5,0,0,0,.5.5h22a.5.5,0,0,0,.5-.5v-6a.5.5,0,0,0-.5-.5Zm22-2h-6A1.5,1.5,0,0,1,23,20.5V8.5A1.5,1.5,0,0,1,24.5,7h6A1.5,1.5,0,0,1,32,8.5v12A1.5,1.5,0,0,1,30.5,22Zm-6-14a.5.5,0,0,0-.5.5v12a.5.5,0,0,0,.5.5h6a.5.5,0,0,0,.5-.5V8.5a.5.5,0,0,0-.5-.5Zm-6,6h-8a3.5,3.5,0,0,1,0-7h8a3.5,3.5,0,0,1,0,7Zm-8-6a2.5,2.5,0,0,0,0,5h8a2.5,2.5,0,0,0,0-5Zm8,14A3.5,3.5,0,1,1,22,18.5,3.5,3.5,0,0,1,18.5,22Zm0-6A2.5,2.5,0,1,0,21,18.5,2.5,2.5,0,0,0,18.5,16Zm-8,6A3.5,3.5,0,1,1,14,18.5,3.5,3.5,0,0,1,10.5,22Zm0-6A2.5,2.5,0,1,0,13,18.5,2.5,2.5,0,0,0,10.5,16Z" style="fill:#009688"/></svg>'), pa = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6.2,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4.6,8a2.6,2.6,0,1,0,5.2,0a2.6,2.6,0,1,0,-5.2,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ua = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3.5,9h2m2,0h2m2,0h2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5l1.8,3h-3.6z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ma = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Zm3-6h8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), fa = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M5,5l6,6" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M11,5l-6,6" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ba = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M4,4h5v5H4z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M7,7h5v5H7z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ha = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2.5,8h11" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M2.5,6v4" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M13.5,6v4" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M6,7v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M10,7v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ga = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M4,8a4,4,0,1,0,8,0a4,4,0,1,0,-8,0" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,4a4,4,0,0,1,0,8z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;fill:#949494;stroke:none"/></svg>'), xa = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M34.854,19.146l-4-4a.5.5,0,0,0-.708.708L33.293,19H28.5a.5.5,0,0,0,0,1h4.793l-3.147,3.146a.5.5,0,0,0,.708.708l4-4A.5.5,0,0,0,34.854,19.146Z" style="fill:#009688"/><path d="M19.854,4.146a.5.5,0,0,0-.708,0l-4,4a.5.5,0,0,0,.708.708L19,5.707V10.5a.5.5,0,0,0,1,0V5.707l3.146,3.147a.5.5,0,0,0,.708-.708Z" style="fill:#009688"/><path d="M23.146,30.146,20,33.293V28.5a.5.5,0,0,0-1,0v4.793l-3.146-3.147a.5.5,0,0,0-.708.708l4,4a.5.5,0,0,0,.708,0l4-4a.5.5,0,0,0-.708-.708Z" style="fill:#009688"/><path d="M10.5,19H5.707l3.147-3.146a.5.5,0,0,0-.708-.708l-4,4a.5.5,0,0,0,0,.708l4,4a.5.5,0,0,0,.708-.708L5.707,20H10.5a.5.5,0,0,0,0-1Z" style="fill:#009688"/><path d="M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/></svg>'), va = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M5,5h6v6H5z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1;stroke-dasharray:2 1.5"/></svg>'), wa = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v5m-2-2 2,2 2-2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4,11.5h8" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), ya = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M34.923,10.25a.392.392,0,0,0-.033-.05.5.5,0,0,0-.2-.162l0,0-15-6a.5.5,0,0,0-.372,0l-15,6,0,0a.5.5,0,0,0-.2.162.392.392,0,0,0-.033.05A.478.478,0,0,0,4,10.5v18a.464.464,0,0,0,.028.138.429.429,0,0,0,.011.054l.01.015a.51.51,0,0,0,.1.144l.008,0a.5.5,0,0,0,.156.1l0,0,14.989,6,0,0,.006,0a.5.5,0,0,0,.372,0l.006,0,0,0,1.989-.8a.5.5,0,0,0-.372-.928L20,33.762V16.839l14-5.6V21.5a.5.5,0,0,0,1,0v-11A.481.481,0,0,0,34.923,10.25ZM19,33.762l-14-5.6V11.239l14,5.6Zm.5-17.8L5.846,10.5,19.5,5.039,33.153,10.5Z" style="fill:#b6b6b6"/><path d="M33.5,24h-8A1.5,1.5,0,0,0,24,25.5v8A1.5,1.5,0,0,0,25.5,35h8A1.5,1.5,0,0,0,35,33.5v-8A1.5,1.5,0,0,0,33.5,24Zm.5,9.5a.5.5,0,0,1-.5.5h-8a.5.5,0,0,1-.5-.5v-8a.5.5,0,0,1,.5-.5h8a.5.5,0,0,1,.5.5Z" style="fill:#009688"/><path d="M32.5,29H30V26.5a.5.5,0,0,0-1,0V29H26.5a.5.5,0,0,0,0,1H29v2.5a.5.5,0,0,0,1,0V30h2.5a.5.5,0,0,0,0-1Z" style="fill:#009688"/></svg>'), ka = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M25.5,22a.5.5,0,0,1-.5-.5V18H18v3.5a.5.5,0,0,1-1,0v-6a.5.5,0,0,1,.084-.277l2-3A.5.5,0,0,1,19.5,12h4a.5.5,0,0,1,.416.223l2,3A.5.5,0,0,1,26,15.5v6A.5.5,0,0,1,25.5,22ZM18,17h7V15.651L23.232,13H19.768L18,15.651Z" style="fill:#009688"/><path d="M11.964,29.314a.5.5,0,0,0-.65-.278L7.152,30.7a17.321,17.321,0,0,1,3.739-6.888.5.5,0,1,0-.782-.624A19.312,19.312,0,0,0,6.359,29.8L4.964,26.314a.5.5,0,1,0-.928.372l2,5c0,.01.016.015.021.025a.475.475,0,0,0,.15.185c.009.007.016.017.025.023a.5.5,0,0,0,.2.076A.367.367,0,0,0,6.5,32h0a.475.475,0,0,0,.181-.036h0l5-2A.5.5,0,0,0,11.964,29.314Z" style="fill:#009688"/><rect x="4" y="34" width="31" height="1" style="fill:#009688"/><path d="M34.854,17.146l-13-13a.5.5,0,0,0-.708,0l-13,13a.5.5,0,0,0,.708.708L21.5,5.207,33.793,17.5,21.146,30.146a.5.5,0,0,0,.708.708l13-13A.5.5,0,0,0,34.854,17.146Z" style="fill:#b6b6b6"/><path d="M21.5,31a.5.5,0,0,1-.354-.146l-13-13a.5.5,0,0,1,.708-.708l13,13A.5.5,0,0,1,21.5,31Z" style="fill:#009688"/></svg>'), Ea = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M27.878,34.926h-4.4c-.509,0-.845,0-.955-.394a.593.593,0,0,1,.36-.67,2.3,2.3,0,0,0,1.2-2.189,3.253,3.253,0,1,1,3.8,3.206Zm-3.538-1h2.988a2.253,2.253,0,1,0-2.253-2.253A3.445,3.445,0,0,1,24.34,33.926Z" style="fill:#009688"/><path d="M30.5,30.289l-.846-.535,4.364-6.9a.222.222,0,0,0-.36-.258l-5.4,6.644-.776-.631,5.4-6.644a1.222,1.222,0,0,1,1.982,1.423Z" style="fill:#009688"/><path d="M33.5,35h-1a.5.5,0,0,1,0-1h1a.5.5,0,0,0,.5-.5v-5a.5.5,0,0,1,1,0v5A1.5,1.5,0,0,1,33.5,35Z" style="fill:#b6b6b6"/><path d="M7.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,7.5,35Z" style="fill:#009688"/><path d="M10.5,35a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,1,0v20A.5.5,0,0,1,10.5,35Z" style="fill:#009688"/><path d="M13.5,35h-9a.5.5,0,0,1-.5-.5v-20a.5.5,0,0,1,.5-.5h9a.5.5,0,0,1,.5.5v20A.5.5,0,0,1,13.5,35ZM5,34h8V15H5Z" style="fill:#009688"/><path d="M22.5,29a.5.5,0,0,1-.5-.5V15H4.5a.5.5,0,0,1-.5-.5v-9A1.5,1.5,0,0,1,5.5,4h28A1.5,1.5,0,0,1,35,5.5v13a.5.5,0,0,1-1,0V5.5a.5.5,0,0,0-.5-.5H5.5a.5.5,0,0,0-.5.5V14H22.5a.5.5,0,0,1,.5.5v14A.5.5,0,0,1,22.5,29Z" style="fill:#b6b6b6"/></svg>'), Ma = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M24.5,26h-10A1.5,1.5,0,0,1,13,24.5v-10A1.5,1.5,0,0,1,14.5,13h10A1.5,1.5,0,0,1,26,14.5v10A1.5,1.5,0,0,1,24.5,26Zm-10-12a.5.5,0,0,0-.5.5v10a.5.5,0,0,0,.5.5h10a.5.5,0,0,0,.5-.5v-10a.5.5,0,0,0-.5-.5Z" style="fill:#b6b6b6"/><path d="M35,19.5A15.517,15.517,0,0,1,19.5,35a15.767,15.767,0,0,1-2.063-.136.5.5,0,0,1-.43-.562.507.507,0,0,1,.562-.43A14.5,14.5,0,1,0,19.5,5,14.43,14.43,0,0,0,7.751,11H11.5a.5.5,0,0,1,0,1h-5a.5.5,0,0,1-.5-.5v-5a.5.5,0,0,1,1,0v3.836A15.5,15.5,0,0,1,35,19.5ZM5.943,24.66a.5.5,0,1,0-.933.356A15.426,15.426,0,0,0,7.354,29.13a.5.5,0,0,0,.783-.621A14.533,14.533,0,0,1,5.943,24.66Zm8.4,8.4a14.523,14.523,0,0,1-3.85-2.194.5.5,0,0,0-.621.784,15.455,15.455,0,0,0,4.115,2.343.487.487,0,0,0,.178.033.5.5,0,0,0,.178-.966ZM5.128,21.431A14.621,14.621,0,0,1,5,19.5a.5.5,0,0,0-1,0,15.729,15.729,0,0,0,.136,2.062.5.5,0,0,0,.992-.131Z" style="fill:#009688"/></svg>'), Ca = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><path d="M25.5,5h-2a.5.5,0,0,1,0-1h2a.5.5,0,0,1,0,1ZM21,4.5a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,4.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,4.5Zm10,30a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,26,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,21,34.5Zm-5,0a.5.5,0,0,0-.5-.5h-2a.5.5,0,0,0,0,1h2A.5.5,0,0,0,16,34.5ZM5,15.5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm30-10v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm0,5v-2a.5.5,0,0,0-1,0v2a.5.5,0,0,0,1,0Zm-9-1v-10A1.5,1.5,0,0,0,24.5,13h-10A1.5,1.5,0,0,0,13,14.5v10A1.5,1.5,0,0,0,14.5,26h10A1.5,1.5,0,0,0,26,24.5ZM24.5,14a.5.5,0,0,1,.5.5v10a.5.5,0,0,1-.5.5h-10a.5.5,0,0,1-.5-.5v-10a.5.5,0,0,1,.5-.5Z" style="fill:#b6b6b6"/><path d="M34.962,4.309A.5.5,0,0,0,34.5,4h-5a.5.5,0,0,0,0,1h3.793l-6.147,6.146a.5.5,0,0,0,.708.708L34,5.707V9.5a.5.5,0,0,0,1,0v-5A.5.5,0,0,0,34.962,4.309Z" style="fill:#009688"/><path d="M5.707,5H9.5a.5.5,0,0,0,0-1h-5a.5.5,0,0,0-.5.5v5a.5.5,0,0,0,1,0V5.707l6.146,6.147a.5.5,0,0,0,.708-.708Z" style="fill:#009688"/><path d="M34.5,29a.5.5,0,0,0-.5.5v3.793l-6.146-6.147a.5.5,0,0,0-.708.708L33.293,34H29.5a.5.5,0,0,0,0,1h5a.5.5,0,0,0,.5-.5v-5A.5.5,0,0,0,34.5,29Z" style="fill:#009688"/><path d="M11.146,27.146,5,33.293V29.5a.5.5,0,0,0-1,0v5a.5.5,0,0,0,.5.5h5a.5.5,0,0,0,0-1H5.707l6.147-6.146a.5.5,0,0,0-.708-.708Z" style="fill:#009688"/></svg>'), ja = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v2m0,2v2m0,2v2" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), $n = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,3.5v9" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M6,6.5,4,8l2,1.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M10,6.5,12,8l-2,1.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), Na = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M.5,13.5V1.5a1,1,0,0,1,1-1h12a1,1,0,0,1,1,1v12a1,1,0,0,1-1,1H1.5A1,1,0,0,1,.5,13.5Z" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M4.5,5h7" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M8,5v6.5" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>'), _a = "data:image/svg+xml;utf8," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3,4.5h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,7h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,9h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,10.5h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/><path d="M3,11.6h10" style="fill:none;stroke:#949494;stroke-linecap:square;stroke-linejoin:round;opacity:1"/></svg>');
22
+ function Aa(L) {
23
+ const $ = L.length, R = new Float32Array($);
24
+ for (let y = 0; y < $; y += 3)
25
+ R[y] = L[y], R[y + 1] = L[y + 2], R[y + 2] = -L[y + 1];
26
+ let J = 1 / 0, c = 1 / 0, N = 1 / 0, z = -1 / 0, w = -1 / 0, Q = -1 / 0;
27
+ for (let y = 0; y < $; y += 3)
28
+ J = Math.min(J, R[y]), z = Math.max(z, R[y]), c = Math.min(c, R[y + 1]), w = Math.max(w, R[y + 1]), N = Math.min(N, R[y + 2]), Q = Math.max(Q, R[y + 2]);
29
+ const U = (J + z) / 2, le = (N + Q) / 2;
30
+ for (let y = 0; y < $; y += 3)
31
+ R[y] -= U, R[y + 1] -= c, R[y + 2] -= le;
32
+ return { localPos: R, size: { w: z - J, d: Q - N, h: w - c } };
33
+ }
34
+ const Sa = 40, Le = (L) => L + Sa, Un = 9, Ht = (L) => {
35
+ const $ = Math.sqrt(L), R = Math.round($);
36
+ return $ > R ? R + 1 : R;
37
+ };
38
+ function Ia({ settings: L = {}, setSettings: $ = () => {
39
+ }, processPanel: R = null }) {
40
+ var Mn, Cn;
41
+ const J = g(null), c = g(null), N = g({}), z = g(null), w = g([]), Q = g(null), U = g(null), le = g(null), y = g({}), Xe = g(null), Ye = g(null), xt = g(!1), vt = g("feature"), ue = g(0), ee = g(0), me = g("prepare"), qt = g(0.42), q = g("off"), Ke = g(5), wt = g(null), Je = g(null), Qe = g(!1), te = g({}), et = g({}), ye = g(null), yt = g(null), kt = g(!1), se = g(0), Oe = g(1), Pe = g(0), tt = g(200), nt = g(200), [W, Dn] = x(!0), [Et, Gn] = x("translate"), [Wt, ie] = x("์ดˆ๊ธฐํ™” ์ค‘โ€ฆ"), [Ce, rt] = x([]), [Xt, Yt] = x(""), [Mt, fe] = x(!1), [Hn, Ze] = x(0), [Kt, _] = x(""), [be, at] = x(null), [qn, ot] = x(!1), [je, lt] = x(0), [Wn, Ne] = x(0), [ne, Jt] = x(1);
42
+ function Ct(e) {
43
+ const t = Ht(Oe.current);
44
+ return { x: e % t * Le(tt.current), z: Math.floor(e / t) * Le(nt.current) };
45
+ }
46
+ function Qt(e, t) {
47
+ const r = Oe.current, a = Ht(r), l = Math.max(0, Math.min(a - 1, Math.round(e / Le(tt.current)))), d = Math.max(0, Math.round(t / Le(nt.current)));
48
+ return Math.max(0, Math.min(r - 1, d * a + l));
49
+ }
50
+ const [Be, Xn] = x(0), [Yn, jt] = x(!1), [Kn, en] = x(!1), [tn, Jn] = x(0), [st, D] = x(null), [Qn, er] = x("feature"), [he, Nt] = x(null), [nn, _t] = x(0), [At, St] = x(0), [ke, tr] = x(!1), [nr, zt] = x([]), [G, _e] = x("prepare"), [Rt, Lt] = x(!1), Te = g(null), [Ie, Ot] = x(["#6aa0dc", "#e08a2b"]), Ae = g(["#6aa0dc", "#e08a2b"]), [rn, it] = x(""), [rr, ar] = x(!1), [an, or] = x(!1), [ge, lr] = x("off"), [on, ln] = x(5), [sn, cn] = x({ enf: 0, blk: 0 }), [dn, xe] = x(""), [pn, Fe] = x(null);
51
+ We(() => {
52
+ const e = J.current;
53
+ if (!e) return;
54
+ const t = document.createElement("canvas");
55
+ if (!(t.getContext("webgl2") || t.getContext("webgl"))) {
56
+ Dn(!1), ie("์ด ํ™˜๊ฒฝ์—์„œ WebGL ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค (ํ—ค๋“œ๋ฆฌ์Šค/GPU ๋ฏธ์ง€์›).");
57
+ return;
58
+ }
59
+ let r = e.clientWidth || 800, a = e.clientHeight || 480;
60
+ const l = new f.WebGLRenderer({ antialias: !0 });
61
+ l.setPixelRatio(Math.min(window.devicePixelRatio, 2)), l.setSize(r, a), l.setClearColor(1448478, 1), l.domElement.setAttribute("data-webgl", l.getContext() ? "ok" : "fail"), e.appendChild(l.domElement);
62
+ const d = new f.Scene(), s = new f.PerspectiveCamera(50, r / a, 1, 3e3);
63
+ s.position.set(210, 180, 260), d.add(new f.HemisphereLight(16777215, 2764598, 1));
64
+ const b = new f.DirectionalLight(16777215, 1.1);
65
+ b.position.set(120, 220, 160), d.add(b);
66
+ const u = new f.Group();
67
+ d.add(u);
68
+ const P = new f.Group();
69
+ d.add(P);
70
+ const m = new Xr(s, l.domElement);
71
+ m.target.set(0, 22, 0), m.enableDamping = !1, m.update(), m.rotateSpeed = 1.6, m.panSpeed = 1.6;
72
+ const h = new Yr(s, l.domElement);
73
+ h.setMode("translate"), h.setSize(0.8);
74
+ const I = new f.Box3(), T = (o) => {
75
+ if (!o) return;
76
+ o.updateMatrixWorld(!0), I.setFromObject(o);
77
+ const i = I.min.y;
78
+ Number.isFinite(i) && Math.abs(i) > 1e-4 && (o.position.y -= i, o.updateMatrixWorld(!0));
79
+ };
80
+ h.addEventListener("dragging-changed", (o) => {
81
+ var i, p;
82
+ m.enabled = !o.value, o.value || T(h.object), (p = (i = N.current).invalidate) == null || p.call(i);
83
+ }), d.add(h), N.current = { scene: d, camera: s, renderer: l, orbit: m, transform: h, objectsGroup: u, toolpathGroup: P, plateBeds: [] }, typeof window < "u" && (window.__vpThree = N.current, window.__vpApi = () => c.current);
84
+ let Y = !0;
85
+ const M = () => {
86
+ Y = !0;
87
+ };
88
+ N.current.invalidate = M, m.addEventListener("change", M), h.addEventListener("change", M), l.domElement.addEventListener("pointermove", M);
89
+ const j = new f.Raycaster(), Z = new f.Vector2();
90
+ let V = null, A = null, Gr = 0;
91
+ const Ut = () => w.current.map((o) => o.mesh), ve = () => {
92
+ for (const o of Ut()) o.material.emissive.setHex(o === A ? 44610 : o === V ? 2055220 : 0);
93
+ }, we = () => w.current.length ? `์˜ค๋ธŒ์ ํŠธ ${w.current.length}๊ฐœ ยท ์„ ํƒ: ${A ? A.userData.name : "โ€”"} | M/R/S ยท ์ขŒ๋“œ๋ž˜๊ทธ ํšŒ์ „ ยท ? ๋‹จ์ถ•ํ‚ค` : `ํ˜ธ๋ฒ„: ${V ? V.userData.name : "โ€”"} ยท ์„ ํƒ: ${A ? A.userData.name : "โ€”"} | ์ขŒ๋“œ๋ž˜๊ทธ ํšŒ์ „ ยท ? ๋‹จ์ถ•ํ‚ค`, Ge = (o) => {
94
+ const i = l.domElement.getBoundingClientRect();
95
+ Z.x = (o.clientX - i.left) / i.width * 2 - 1, Z.y = -((o.clientY - i.top) / i.height) * 2 + 1;
96
+ }, mt = () => {
97
+ j.setFromCamera(Z, s);
98
+ const o = j.intersectObjects(Ut(), !1);
99
+ return o.length ? o[0].object : null;
100
+ }, Hr = () => {
101
+ j.setFromCamera(Z, s);
102
+ const o = j.intersectObjects(Ut(), !1);
103
+ return o.length ? o[0] : null;
104
+ }, jn = (o) => {
105
+ var H;
106
+ const i = wt.current;
107
+ if (!i) return;
108
+ Ge(o);
109
+ const p = Hr();
110
+ if (!p || p.faceIndex == null) return;
111
+ const E = (B) => [B.x - i.cx, -B.z - i.cy, B.y - i.minz], C = E(p.point), k = E(s.position);
112
+ (H = z.current) == null || H.postMessage({
113
+ cmd: "paint",
114
+ facet: p.faceIndex,
115
+ hx: C[0],
116
+ hy: C[1],
117
+ hz: C[2],
118
+ cx: k[0],
119
+ cy: k[1],
120
+ cz: k[2],
121
+ radius: Ke.current,
122
+ enforcer: q.current === "enforcer"
123
+ });
124
+ }, Nn = () => {
125
+ const o = l.domElement;
126
+ o.style.cursor = me.current === "preview" ? "" : q.current !== "off" ? "crosshair" : V ? "pointer" : "";
127
+ }, _n = (o) => {
128
+ if (me.current === "preview") return;
129
+ if (q.current !== "off") {
130
+ Qe.current && jn(o);
131
+ return;
132
+ }
133
+ if (h.dragging || h.axis) return;
134
+ Ge(o);
135
+ const i = mt();
136
+ i !== V && (V = i, ve(), Nn(), ie(we()));
137
+ }, An = (o) => {
138
+ if (o.button !== 0 || me.current === "preview") return;
139
+ if (q.current !== "off") {
140
+ Qe.current = !0, m.enabled = !1, jn(o);
141
+ return;
142
+ }
143
+ if (h.dragging || h.axis) return;
144
+ Ge(o);
145
+ const i = mt();
146
+ i ? (A = i, h.attach(i)) : (A = null, h.detach()), ve(), ie(we());
147
+ }, ft = () => {
148
+ Qe.current && (Qe.current = !1, m.enabled = !0);
149
+ }, Sn = (o) => {
150
+ o.button !== 0 || me.current === "preview" || q.current !== "off" || (Ge(o), mt() ? Dt() : (A = null, h.detach(), ve(), ie(we())));
151
+ }, zn = (o) => {
152
+ if (q.current === "off" || me.current === "preview") return;
153
+ o.preventDefault(), o.stopPropagation();
154
+ const i = Math.min(15, Math.max(1, Ke.current + (o.deltaY < 0 ? 0.5 : -0.5)));
155
+ Ke.current = i, ln(i);
156
+ };
157
+ let bt = null;
158
+ const Rn = (o) => {
159
+ o.button === 2 && (bt = { x: o.clientX, y: o.clientY });
160
+ }, Ln = (o) => {
161
+ if (o.preventDefault(), me.current === "preview" || q.current !== "off" || bt && Math.hypot(o.clientX - bt.x, o.clientY - bt.y) > 4) return;
162
+ Ge(o);
163
+ const i = mt();
164
+ i ? (A = i, h.attach(i)) : (A = null, h.detach()), ve(), ie(we());
165
+ const p = l.domElement.getBoundingClientRect();
166
+ D({ x: o.clientX - p.left, y: o.clientY - p.top, onObject: !!i });
167
+ };
168
+ l.domElement.addEventListener("pointermove", _n), l.domElement.addEventListener("pointerdown", An), l.domElement.addEventListener("pointerdown", Rn), l.domElement.addEventListener("contextmenu", Ln), l.domElement.addEventListener("dblclick", Sn), l.domElement.addEventListener("wheel", zn, { passive: !1, capture: !0 }), window.addEventListener("pointerup", ft), window.addEventListener("pointercancel", ft);
169
+ const qr = (o) => {
170
+ h.setMode(o), Gn(o);
171
+ }, Dt = () => {
172
+ const o = w.current, i = new f.Box3();
173
+ o.length ? o.forEach((k) => i.expandByObject(k.mesh)) : i.setFromCenterAndSize(new f.Vector3(0, 25, 0), new f.Vector3(100, 50, 100));
174
+ const p = i.getCenter(new f.Vector3()), E = i.getSize(new f.Vector3()), C = Math.max(E.x, E.y, E.z, 20) * 1.9 + 40;
175
+ m.target.copy(p), s.position.set(p.x + C * 0.7, p.y + C * 0.55 + E.y * 0.3, p.z + C), s.updateProjectionMatrix(), m.update();
176
+ }, On = (o, i, p = null, E = null, C = null) => {
177
+ const k = new f.BufferGeometry();
178
+ k.setAttribute("position", new f.Float32BufferAttribute(i, 3)), k.computeVertexNormals(), k.computeBoundingBox();
179
+ const H = Ae.current[0] || "#6aa0dc", B = new f.Mesh(k, new f.MeshStandardMaterial({ color: new f.Color(H), roughness: 0.6, metalness: 0.05, side: f.DoubleSide }));
180
+ if (p && B.rotation.copy(p), E && B.scale.copy(E), C)
181
+ B.position.copy(C);
182
+ else {
183
+ const de = (k.boundingBox.max.x - k.boundingBox.min.x) * (E ? Math.abs(E.x) : 1);
184
+ w.current.length === 0 && (Pe.current = 0);
185
+ const oe = Ct(se.current);
186
+ B.position.set(oe.x + Pe.current + de / 2, 0, oe.z), Pe.current += de + 8;
187
+ }
188
+ B.userData = { name: o }, u.add(B);
189
+ const ae = ++Gr;
190
+ return w.current.push({ id: ae, name: o, mesh: B, localPos: i, extruder: 1, visible: !0 }), u.visible = !0, ie(we()), Dt(), { id: ae, name: o };
191
+ };
192
+ c.current = {
193
+ setMode: qr,
194
+ refreshCursor: () => Nn(),
195
+ // ํŽ˜์ธํŠธ ๋ชจ๋“œ ์ „ํ™˜ ์‹œ ์ปค์„œ ํžŒํŠธ ๋™๊ธฐํ™”
196
+ detachTransform: () => {
197
+ A = null, h.detach(), ve();
198
+ },
199
+ // 20๋‹จ๊ณ„: ํŽ˜์ธํŒ… ์ง„์ž… ์‹œ ๊ธฐ์ฆˆ๋ชจ ํ•ด์ œ
200
+ addObject: (o, i) => On(o, Aa(i).localPos),
201
+ // ---- ๋‹จ์ถ•ํ‚ค ์ง€์› (๋ณต์ œ/๋„›์ง€/ํšŒ์ „/์คŒํˆฌ) ----
202
+ getSnapshot: (o) => {
203
+ const i = w.current.find((p) => p.id === o);
204
+ return i ? { name: i.name, localPos: i.localPos, rot: i.mesh.rotation.clone(), scale: i.mesh.scale.clone(), pos: i.mesh.position.clone() } : null;
205
+ },
206
+ // keepPos=true ๋ฉด ์Šค๋ƒ…์ƒท์˜ ์›๋ž˜ ์œ„์น˜๋ฅผ ์œ ์ง€(๋ถ„๋ฆฌ). false(๊ธฐ๋ณธ)๋ฉด ๋ฐฐ์น˜ ์ปค์„œ๋กœ ์˜†์— ๋†“๋Š”๋‹ค(๋ณต์ œ/๋ถ™์—ฌ๋„ฃ๊ธฐ).
207
+ spawnSnapshot: (o, i = !1) => o ? On(o.name, o.localPos, o.rot, o.scale, i && o.pos || null) : null,
208
+ nudgeSelected: (o, i) => {
209
+ A && (A.position.x += o, A.position.z += i);
210
+ },
211
+ rotateSelectedY: (o) => {
212
+ A && (A.rotation.y += o);
213
+ },
214
+ frame: () => Dt(),
215
+ // Z: ์ „์ฒด ์˜ค๋ธŒ์ ํŠธ๋กœ ์คŒ
216
+ frameBed: () => {
217
+ const o = Ct(se.current), i = Math.max(tt.current, nt.current) * 1.1 + 40;
218
+ m.target.set(o.x, 0, o.z), s.position.set(o.x + i * 0.55, i * 0.8, o.z + i), m.update();
219
+ },
220
+ removeObject: (o) => {
221
+ const i = w.current, p = i.findIndex((C) => C.id === o);
222
+ if (p < 0) return;
223
+ const E = i[p];
224
+ A === E.mesh && (A = null, h.detach()), V === E.mesh && (V = null), u.remove(E.mesh), E.mesh.geometry.dispose(), E.mesh.material.dispose(), i.splice(p, 1), i.length === 0 && (Pe.current = 0), ve(), ie(we());
225
+ },
226
+ // MM: ์ต์ŠคํŠธ๋ฃจ๋” ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์‚ผ๊ฐํ˜• ์ •๋ ฌ ๋ณ‘ํ•ฉ โ†’ ๊ทธ๋ฃน0(ext1) ๋’ค ๊ทธ๋ฃน1(ext2), split ๋ฐ˜ํ™˜.
227
+ platePos: (o) => Ct(o),
228
+ // ํ”Œ๋ ˆ์ดํŠธ i ์˜ three (x,z) ์˜คํ”„์…‹
229
+ plateOfObject: (o) => {
230
+ o.mesh.updateMatrixWorld(!0);
231
+ const i = new f.Vector3().setFromMatrixPosition(o.mesh.matrixWorld);
232
+ return Qt(i.x, i.z);
233
+ },
234
+ // plateIdx!=null ์ด๋ฉด ๊ทธ ํ”Œ๋ ˆ์ดํŠธ ์†Œ์† ์˜ค๋ธŒ์ ํŠธ๋งŒ + ์ขŒํ‘œ๋ฅผ ํ”Œ๋ ˆ์ดํŠธ ๋กœ์ปฌ(three-x -= PX)๋กœ ๋ณ€ํ™˜(28๋‹จ๊ณ„ ๊ณ„์•ฝ ์œ ์ง€).
235
+ buildMergedSTL: (o = null) => {
236
+ let i = w.current.filter((v) => v.visible !== !1);
237
+ if (o != null && (i = i.filter((v) => {
238
+ v.mesh.updateMatrixWorld(!0);
239
+ const F = new f.Vector3().setFromMatrixPosition(v.mesh.matrixWorld);
240
+ return Qt(F.x, F.z) === o;
241
+ })), !i.length) return null;
242
+ const p = [...i].sort((v, F) => (v.extruder || 1) - (F.extruder || 1)), E = new Set(p.map((v) => v.extruder || 1)), C = new f.Vector3(), k = [];
243
+ let H = 0, B = 0;
244
+ for (const v of p) {
245
+ (v.extruder || 1) >= 2 && B === 0 && (B = H), v.mesh.updateMatrixWorld(!0);
246
+ const F = v.mesh.matrixWorld, He = v.localPos;
247
+ for (let qe = 0; qe < He.length; qe += 3)
248
+ C.set(He[qe], He[qe + 1], He[qe + 2]).applyMatrix4(F), k.push(C.x, -C.z, C.y);
249
+ H += He.length / 9;
250
+ }
251
+ let ae = 1e18, de = 1e18, oe = -1e18, Ee = -1e18;
252
+ for (let v = 0; v < k.length; v += 3)
253
+ k[v] < ae && (ae = k[v]), k[v] > oe && (oe = k[v]), k[v + 1] < de && (de = k[v + 1]), k[v + 1] > Ee && (Ee = k[v + 1]);
254
+ const ze = (ae + oe) / 2, Re = (de + Ee) / 2;
255
+ for (let v = 0; v < k.length; v += 3)
256
+ k[v] -= ze, k[v + 1] -= Re;
257
+ const ht = ze, O = -Re, S = new ArrayBuffer(84 + H * 50), pe = new DataView(S);
258
+ pe.setUint32(80, H, !0);
259
+ let K = 84, Me = 0;
260
+ for (let v = 0; v < H; v++) {
261
+ K += 12;
262
+ for (let F = 0; F < 3; F++)
263
+ pe.setFloat32(K, k[Me++], !0), pe.setFloat32(K + 4, k[Me++], !0), pe.setFloat32(K + 8, k[Me++], !0), K += 12;
264
+ pe.setUint16(K, 0, !0), K += 2;
265
+ }
266
+ return { buf: S, split: B, extruders: E.size, offX: ht, offZ: O };
267
+ },
268
+ setObjectExtruder: (o, i) => {
269
+ const p = w.current.find((E) => E.id === o);
270
+ if (p) {
271
+ p.extruder = i;
272
+ const E = Ae.current[i - 1];
273
+ E && p.mesh.material.color.set(E);
274
+ }
275
+ },
276
+ setObjectVisible: (o, i) => {
277
+ const p = w.current.find((E) => E.id === o);
278
+ p && (p.visible = i, p.mesh.visible = i);
279
+ },
280
+ // 27๋‹จ๊ณ„: ์ถœ๋ ฅ ํ† ๊ธ€(๋ˆˆ์•Œ)
281
+ recolorObjects: () => {
282
+ for (const o of w.current) {
283
+ const i = Ae.current[(o.extruder || 1) - 1];
284
+ i && o.mesh.material.color.set(i);
285
+ }
286
+ },
287
+ // ํ•„๋ผ๋ฉ˜ํŠธ ์ƒ‰ ๋ณ€๊ฒฝ ๋ฐ˜์˜
288
+ selectedObjectId: () => {
289
+ var o;
290
+ return A ? ((o = w.current.find((i) => i.mesh === A)) == null ? void 0 : o.id) ?? null : null;
291
+ },
292
+ // 27๋‹จ๊ณ„: ๋ทฐํฌํŠธ ํˆด๋ฐ” "์„ ํƒ ์‚ญ์ œ"
293
+ selectObject: (o) => {
294
+ const i = w.current.find((p) => p.id === o);
295
+ i && (A = i.mesh, h.attach(i.mesh), ve(), ie(we()));
296
+ },
297
+ // 28๋‹จ๊ณ„ P1: ๋ฐ”๋‹ฅ ์•ˆ์ฐฉ โ€” ๋กœ์ปฌ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๋Š” bakeLocal ์ด minZโ†’0(๋กœ๋“œ ์‹œ 1ํšŒ). ๊ธฐ์ฆˆ๋ชจ Z์ด๋™ ํ›„ ์žฌ์•ˆ์ฐฉ.
298
+ // (์›๋ณธ ensure_on_bed ์˜ ์‹ฑํ‚น ํ—ˆ์šฉ[allow_negative_z]์€ ๋ฒ”์œ„ ์™ธ โ€” ์šฐ๋ฆฌ๋Š” -min_z ์•ˆ์ฐฉ๋งŒ.)
299
+ placeOnBed: () => {
300
+ var o;
301
+ for (const i of w.current) i.mesh.position.y = 0;
302
+ A && ((o = h.update) == null || o.call(h));
303
+ },
304
+ onSliced: () => {
305
+ u.visible = !1, h.detach(), A = null, ve();
306
+ },
307
+ showObjects: () => {
308
+ u.visible = !0;
309
+ },
310
+ // 29๋‹จ๊ณ„-2: N ํ”Œ๋ ˆ์ดํŠธ ๋ Œ๋” โ€” ๊ฐ ํ”Œ๋ ˆ์ดํŠธ = ๊ทธ๋ฆฌ๋“œ+ํ…Œ๋‘๋ฆฌ, PX_i ์˜คํ”„์…‹, ์„ ํƒ ํ”Œ๋ ˆ์ดํŠธ ํ…Œ๋‘๋ฆฌ ํ•˜์ด๋ผ์ดํŠธ.
311
+ setPlates: (o, i, p, E) => {
312
+ const C = N.current;
313
+ tt.current = i, nt.current = p, Oe.current = o, se.current = E;
314
+ for (const O of C.plateBeds || []) for (const S of [O.gridThin, O.gridBold, O.border])
315
+ C.scene.remove(S), S.geometry.dispose(), S.material.dispose();
316
+ C.plateBeds = [];
317
+ const k = Ht(o), H = Le(i), B = Le(p), ae = Math.min(i, p), de = ae >= 6e3 ? 100 : ae >= 1200 ? 50 : ae >= 600 ? 20 : 10, oe = [], Ee = [], ze = -i / 2, Re = -p / 2;
318
+ for (let O = 0, S = ze; S <= i / 2 + 1e-6; S = ze + ++O * de) (O % 5 ? oe : Ee).push(S, 0, Re, S, 0, p / 2);
319
+ for (let O = 0, S = Re; S <= p / 2 + 1e-6; S = Re + ++O * de) (O % 5 ? oe : Ee).push(ze, 0, S, i / 2, 0, S);
320
+ const ht = (O) => {
321
+ const S = new f.BufferGeometry();
322
+ return S.setAttribute("position", new f.Float32BufferAttribute(O, 3)), S;
323
+ };
324
+ for (let O = 0; O < o; O++) {
325
+ const S = O % k * H, pe = Math.floor(O / k) * B, K = new f.LineSegments(ht(oe), new f.LineBasicMaterial({ color: 2304561 })), Me = new f.LineSegments(ht(Ee), new f.LineBasicMaterial({ color: 3752781 }));
326
+ K.position.set(S, 0, pe), Me.position.set(S, 0, pe), C.scene.add(K), C.scene.add(Me);
327
+ const v = O === E, F = new f.LineSegments(new f.EdgesGeometry(new f.PlaneGeometry(i, p)), new f.LineBasicMaterial({ color: v ? 44610 : 4871520, linewidth: v ? 2 : 1 }));
328
+ F.rotation.x = -Math.PI / 2, F.position.set(S, 0, pe), C.scene.add(F), C.plateBeds.push({ gridThin: K, gridBold: Me, border: F });
329
+ }
330
+ },
331
+ setBed: (o, i) => {
332
+ var p;
333
+ (p = c.current) == null || p.setPlates(Oe.current, o, i, se.current);
334
+ }
335
+ // ํ•˜์œ„ํ˜ธํ™˜
336
+ };
337
+ const Pn = (o) => {
338
+ var i;
339
+ (i = Xe.current) == null || i.call(Xe, o), M();
340
+ };
341
+ window.addEventListener("keydown", Pn);
342
+ const Zn = new ResizeObserver(() => {
343
+ r = e.clientWidth || r, a = e.clientHeight || a, s.aspect = r / a, s.updateProjectionMatrix(), l.setSize(r, a), M();
344
+ });
345
+ Zn.observe(e), ie(we());
346
+ let Bn = 0, Tn = 0;
347
+ const In = (o = 0) => {
348
+ Bn = requestAnimationFrame(In), m.update(), (Y || o - Tn > 500) && (Y = !1, Tn = o, l.render(d, s));
349
+ };
350
+ return In(), () => {
351
+ cancelAnimationFrame(Bn), Zn.disconnect(), window.removeEventListener("keydown", Pn), l.domElement.removeEventListener("pointermove", _n), l.domElement.removeEventListener("pointerdown", An), l.domElement.removeEventListener("pointerdown", Rn), l.domElement.removeEventListener("contextmenu", Ln), l.domElement.removeEventListener("dblclick", Sn), l.domElement.removeEventListener("wheel", zn, { capture: !0 }), window.removeEventListener("pointerup", ft), window.removeEventListener("pointercancel", ft), c.current = null, h.detach(), h.dispose(), m.dispose(), d.traverse((o) => {
352
+ o.geometry && o.geometry.dispose(), o.material && o.material.dispose();
353
+ }), l.dispose(), l.domElement.parentNode && l.domElement.parentNode.removeChild(l.domElement);
354
+ };
355
+ }, []), We(() => () => {
356
+ z.current && (z.current.terminate(), z.current = null);
357
+ }, []), We(() => {
358
+ try {
359
+ Ue().postMessage({ cmd: "warmup" });
360
+ } catch {
361
+ }
362
+ }, []);
363
+ const X = Gt(L);
364
+ We(() => {
365
+ var e;
366
+ (e = c.current) == null || e.setPlates(ne, X.bed_width, X.bed_depth, Be);
367
+ }, [X.bed_width, X.bed_depth, ne, Be]), We(() => {
368
+ var r;
369
+ me.current = G;
370
+ const e = N.current;
371
+ if (!e.toolpathGroup) return;
372
+ const t = G === "preview";
373
+ e.toolpathGroup.visible = t, e.objectsGroup && (e.objectsGroup.visible = !t && w.current.length > 0), t && ((r = c.current) == null || r.detachTransform(), q.current !== "off" && re("off"));
374
+ }, [G]);
375
+ function ct(e) {
376
+ var r;
377
+ const t = y.current[e];
378
+ t && (t.group.remove(t.ctl.mesh), t.group.remove(t.ctl.travLines), t.ctl.dispose(), (r = N.current.toolpathGroup) == null || r.remove(t.group), delete y.current[e], U.current === t.ctl && (U.current = null, le.current = null));
379
+ }
380
+ function sr() {
381
+ for (const e of Object.keys(y.current)) ct(Number(e));
382
+ U.current = null, le.current = null;
383
+ }
384
+ function Pt(e, t) {
385
+ const { toolpathGroup: r } = N.current;
386
+ if (!r || (ct(e), !t || !t.length)) return null;
387
+ const a = ta(t, qt.current), l = na(f, a), d = et.current[e] || { offX: 0, offZ: 0 }, s = new f.Group();
388
+ s.rotation.x = -Math.PI / 2, s.position.set(d.offX || 0, 0, d.offZ || 0), s.add(l.mesh), s.add(l.travLines), r.add(s), l.setTravelVisible(xt.current), l.setLayerRange(0, Math.max(0, t.length - 1));
389
+ const b = Vn(a, vt.current, un());
390
+ l.setColors(b.color);
391
+ const u = { group: s, ctl: l, seg: a, layers: t };
392
+ return y.current[e] = u, u;
393
+ }
394
+ function ir() {
395
+ for (const [e, t] of Object.entries(te.current)) {
396
+ const r = Number(e);
397
+ if (!t || t.error || !t.layers || !t.layers.length) continue;
398
+ const a = y.current[r];
399
+ (!a || a.layers !== t.layers) && Pt(r, t.layers);
400
+ }
401
+ }
402
+ function un() {
403
+ const e = (r, a) => {
404
+ const l = gt(L, r), d = parseFloat(l);
405
+ return Number.isFinite(d) ? d : a;
406
+ }, t = e("outer_wall_speed", 60);
407
+ return {
408
+ speedByType: {
409
+ 1: t,
410
+ 2: e("sparse_infill_speed", 40),
411
+ 3: e("internal_solid_infill_speed", 45),
412
+ 4: t,
413
+ 5: e("support_speed", 35),
414
+ 6: e("support_speed", 35),
415
+ 7: e("gap_infill_speed", 30),
416
+ 8: t,
417
+ 9: e("bridge_speed", 25),
418
+ 10: e("ironing_speed", 20),
419
+ 11: t
420
+ },
421
+ firstLayerSpeed: e("initial_layer_speed", 30),
422
+ closeFanLayers: e("close_fan_the_first_x_layers", 1),
423
+ fanNormal: e("fan_max_speed", 100),
424
+ tempNormal: e("nozzle_temperature", 210),
425
+ tempFirst: e("nozzle_temperature_initial_layer", e("nozzle_temperature", 210))
426
+ };
427
+ }
428
+ function Zt() {
429
+ const e = un();
430
+ for (const t of Object.values(y.current)) {
431
+ const r = Vn(t.seg, vt.current, e);
432
+ t.ctl.setColors(r.color), t.ctl === U.current && Nt({ min: r.min, max: r.max, label: r.label, unit: r.unit, cont: r.cont });
433
+ }
434
+ }
435
+ function cr() {
436
+ const e = se.current, t = Q.current || [];
437
+ if (!t.length) {
438
+ ct(e), Ne(0), U.current = null, le.current = null;
439
+ return;
440
+ }
441
+ const r = Pt(e, t);
442
+ if (!r) {
443
+ Ne(0);
444
+ return;
445
+ }
446
+ U.current = r.ctl, le.current = r.seg, r.ctl.setLayerRange(ue.current, ee.current), Zt(), Ne(r.seg.nSeg), zt(Fn(r.seg.typeLengths));
447
+ }
448
+ function dr() {
449
+ var e;
450
+ (e = U.current) == null || e.setLayerRange(ue.current, ee.current);
451
+ }
452
+ const dt = g(null), Ve = g(0), $e = () => {
453
+ Ve.current && (clearInterval(Ve.current), Ve.current = 0);
454
+ }, pr = (e, t) => {
455
+ const r = t > 2 ? (t - 2) / 2 : 0;
456
+ return r ? e <= r ? 0.15 * (e / r) : e === r + 1 ? 0.2 : e === r + 2 ? 0.6 : 0.6 + 0.4 * ((e - r - 2) / r) : t ? e / t : 0;
457
+ }, ur = (e) => {
458
+ const t = dt.current;
459
+ !t || Ve.current || (Ve.current = setInterval(() => {
460
+ const r = t.arr[0];
461
+ Ze(0.2 + 0.4 * Math.min(0.95, r / (3.5 * e)));
462
+ }, 150));
463
+ };
464
+ function Ue() {
465
+ if (!z.current) {
466
+ const e = Kr();
467
+ e.onmessage = (r) => {
468
+ var d, s, b, u, P;
469
+ const a = r.data, l = ye.current;
470
+ if (a.type === "progress") {
471
+ const m = a.total > 2 ? (a.total - 2) / 2 : 0;
472
+ m && a.done === m + 1 && ur(m), m && a.done >= m + 2 && $e(), Ze(pr(a.done, a.total)), (d = l == null ? void 0 : l.note) == null || d.call(l, a.done, a.total), (s = l == null ? void 0 : l.kick) == null || s.call(l);
473
+ } else if (a.type === "supsab")
474
+ try {
475
+ dt.current = { arr: new Uint32Array(a.buf, a.ptr, 1) };
476
+ } catch {
477
+ }
478
+ else if (a.type === "layer") {
479
+ (b = l == null ? void 0 : l.kick) == null || b.call(l);
480
+ const m = yt.current;
481
+ m && (m.layers.push({ z: a.z, paths: a.paths, widths: a.widths }), a.gcode && m.gcode.push(a.gcode));
482
+ } else a.type === "done" ? ($e(), l ? (ye.current = null, (u = l.stop) == null || u.call(l), l.resolve(mn(a.result))) : (mr(mn(a.result)), fe(!1))) : a.type === "error" ? ($e(), l ? (ye.current = null, (P = l.stop) == null || P.call(l), l.reject(new Error(a.error))) : (_("์Šฌ๋ผ์ด์Šค ์‹คํŒจ: " + a.error), fe(!1))) : a.type === "prepared" || (a.type === "painted" ? (cn({ enf: a.enf, blk: a.blk }), e.postMessage({ cmd: "overlay" })) : a.type === "overlay" && xr(a.enf, a.blk));
483
+ };
484
+ const t = (r) => {
485
+ var l;
486
+ $e(), dt.current = null;
487
+ const a = ye.current;
488
+ if (a) {
489
+ ye.current = null, (l = a.stop) == null || l.call(a);
490
+ try {
491
+ e.terminate();
492
+ } catch {
493
+ }
494
+ z.current = null, a.reject(new Error(r));
495
+ } else
496
+ _(r), fe(!1);
497
+ };
498
+ e.onerror = (r) => t("Worker ์ข…๋ฃŒ(๋ฉ”๋ชจ๋ฆฌ ์ดˆ๊ณผ ์ถ”์ •): " + (r.message || "worker error")), e.onmessageerror = () => t("Worker ๋ฉ”์‹œ์ง€ ์˜ค๋ฅ˜(๊ตฌ์กฐํ™” ๋ณต์ œ ์‹คํŒจ)"), z.current = e, typeof window < "u" && (window.__vpWorker = e);
499
+ }
500
+ return z.current;
501
+ }
502
+ function mn(e) {
503
+ if (e && e.stats && e.stats.streamed) {
504
+ const t = yt.current || { layers: [], gcode: [] };
505
+ return { stats: e.stats, layers: t.layers, gcode: t.gcode.join("") };
506
+ }
507
+ return e;
508
+ }
509
+ function mr(e) {
510
+ var r;
511
+ if (e.error) {
512
+ _(String(e.error));
513
+ return;
514
+ }
515
+ Q.current = e.layers;
516
+ const t = e.layers.length;
517
+ ue.current = 0, ee.current = t - 1, _t(0), St(t - 1), cr(), (r = c.current) == null || r.onSliced(), _e("preview"), at({ layers: e.stats.layers, segments: e.stats.path_segments, filament: e.stats.filament_mm, timeSec: e.stats.time_estimate }), ot(!!e.stats.over_bed), lt(t), it((a) => (a && URL.revokeObjectURL(a), URL.createObjectURL(new Blob([e.gcode], { type: "text/plain" }))));
518
+ }
519
+ async function fn(e) {
520
+ var l, d;
521
+ const t = Array.from(e || []).filter((s) => aa.includes(oa(s.name))), r = Array.from(e || []).length - t.length;
522
+ if (!t.length) {
523
+ r && _("์ง€์› ํฌ๋งท: STL/OBJ/3MF/AMF/PLY");
524
+ return;
525
+ }
526
+ _(""), Yt(""), Ze(0), Q.current = null, le.current = null, te.current = {}, et.current = {}, sr(), pt(), at(null), ot(!1), lt(0), Ne(0), Nt(null), xe(""), Fe(null), it((s) => (s && URL.revokeObjectURL(s), "")), _e("prepare"), (l = c.current) == null || l.showObjects();
527
+ let a = 0;
528
+ for (const s of t)
529
+ try {
530
+ const b = performance.now(), u = await s.arrayBuffer(), P = performance.now(), m = await la(s.name, u), h = performance.now();
531
+ for (const I of m)
532
+ (d = c.current) == null || d.addObject(I.name, I.modelPos), a += I.modelPos.length / 9;
533
+ console.info(`[vp-prof] load ${s.name}: read ${(P - b).toFixed(0)}ms, parse ${(h - P).toFixed(0)}ms, scene ${(performance.now() - h).toFixed(0)}ms`);
534
+ } catch (b) {
535
+ _(`๋กœ๋“œ ์‹คํŒจ ${s.name}: ${b && b.message || b}`);
536
+ }
537
+ rt(w.current.map((s) => ({ id: s.id, name: s.name, extruder: s.extruder, visible: s.visible !== !1 }))), a > 1e5 && Yt(`์‚ผ๊ฐํ˜• ${Math.round(a).toLocaleString()}๊ฐœ โ€” ์Šฌ๋ผ์ด์Šค๊ฐ€ ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค`);
538
+ }
539
+ function fr(e) {
540
+ fn(e.target.files), e.target.value = "";
541
+ }
542
+ function Bt(e) {
543
+ var t;
544
+ (t = c.current) == null || t.removeObject(e), rt(w.current.map((r) => ({ id: r.id, name: r.name, extruder: r.extruder, visible: r.visible !== !1 })));
545
+ }
546
+ function br(e) {
547
+ var t;
548
+ e.preventDefault(), Lt(!1), fn((t = e.dataTransfer) == null ? void 0 : t.files);
549
+ }
550
+ function hr(e) {
551
+ e.preventDefault(), e.dataTransfer && (e.dataTransfer.dropEffect = "copy"), Rt || Lt(!0);
552
+ }
553
+ function gr(e) {
554
+ e.currentTarget.contains(e.relatedTarget) || Lt(!1);
555
+ }
556
+ function xr(e, t) {
557
+ var s, b;
558
+ const r = N.current;
559
+ if (!r.objectsGroup) return;
560
+ const a = wt.current || { cx: 0, cy: 0, minz: 0 }, l = Je.current;
561
+ if (l)
562
+ for (const u of ["enf", "blk"]) l[u] && (r.objectsGroup.remove(l[u]), l[u].geometry.dispose(), l[u].material.dispose());
563
+ const d = (u, P) => {
564
+ if (!u || u.length < 9) return null;
565
+ const m = new Float32Array(u.length);
566
+ for (let T = 0; T < u.length; T += 3) {
567
+ const Y = u[T], M = u[T + 1], j = u[T + 2];
568
+ m[T] = Y + a.cx, m[T + 1] = j + a.minz, m[T + 2] = -(M + a.cy);
569
+ }
570
+ const h = new f.BufferGeometry();
571
+ h.setAttribute("position", new f.Float32BufferAttribute(m, 3)), h.computeVertexNormals();
572
+ const I = new f.Mesh(h, new f.MeshBasicMaterial({ color: P, transparent: !0, opacity: 0.55, side: f.DoubleSide, depthTest: !1 }));
573
+ return I.renderOrder = 999, r.objectsGroup.add(I), I;
574
+ };
575
+ Je.current = { enf: d(e, 2845951), blk: d(t, 14826299) }, (b = (s = N.current).invalidate) == null || b.call(s);
576
+ }
577
+ function vr() {
578
+ const e = N.current, t = Je.current;
579
+ if (t && e.objectsGroup)
580
+ for (const r of ["enf", "blk"]) t[r] && (e.objectsGroup.remove(t[r]), t[r].geometry.dispose(), t[r].material.dispose());
581
+ Je.current = null;
582
+ }
583
+ function re(e) {
584
+ var t, r, a;
585
+ if (e !== "off" && w.current.length === 0) {
586
+ _("๋จผ์ € STL ์„ ์—…๋กœ๋“œํ•˜์„ธ์š”");
587
+ return;
588
+ }
589
+ if (e !== "off") {
590
+ const l = (t = c.current) == null ? void 0 : t.buildMergedSTL(se.current);
591
+ if (!l) return;
592
+ wt.current = { cx: l.offX, cy: -l.offZ, minz: 0 }, (r = c.current) == null || r.detachTransform(), Ue().postMessage({ cmd: "prepare", stl: l.buf });
593
+ }
594
+ q.current = e, lr(e), (a = c.current) == null || a.refreshCursor();
595
+ }
596
+ function wr() {
597
+ Ue().postMessage({ cmd: "clear" }), vr(), cn({ enf: 0, blk: 0 });
598
+ }
599
+ const yr = 6e4, kr = 3e5;
600
+ function bn(e, t) {
601
+ return new Promise((r, a) => {
602
+ if (typeof window < "u" && window.__vpFail && window.__vpFail(window.__vpSliceN = (window.__vpSliceN || 0) + 1)) {
603
+ a(new Error("forced failure (test hook)"));
604
+ return;
605
+ }
606
+ const l = typeof window < "u" && window.__vpStallNext ? (window.__vpStallNext = !1, !0) : !1, d = typeof window < "u" && window.__vpWatchdogOnce ? ((M) => (window.__vpWatchdogOnce = 0, M))(window.__vpWatchdogOnce) : yr;
607
+ yt.current = { layers: [], gcode: [] };
608
+ let s = 0, b = 0, u = 0;
609
+ const P = performance.now();
610
+ let m = "";
611
+ const h = (M, j) => {
612
+ b = M, u = j;
613
+ const Z = j > 2 ? (j - 2) / 2 : 0, V = Z ? M < Z ? "PASS1โ€ฆ" : M === Z ? "PASS1-done" : M === Z + 1 ? "surf-done" : M === Z + 2 ? "support-done" : M === j ? "emit-done" : "emitโ€ฆ" : "";
614
+ V && V !== m && (console.info(`[vp-prof] ${V} +${((performance.now() - P) / 1e3).toFixed(1)}s`), m = V);
615
+ }, I = () => {
616
+ const M = u > 2 ? (u - 2) / 2 : 0;
617
+ return M && b >= M && b < M + 2 ? kr : d;
618
+ }, T = () => {
619
+ s && (clearTimeout(s), s = 0);
620
+ }, Y = () => {
621
+ T();
622
+ const M = I();
623
+ s = setTimeout(() => {
624
+ var j;
625
+ ye.current = null, $e(), dt.current = null;
626
+ try {
627
+ (j = z.current) == null || j.terminate();
628
+ } catch {
629
+ }
630
+ z.current = null, a(new Error(`watchdog: ${M}ms ๋ฌด์ง„ํ–‰ โ€” ๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ•์œผ๋กœ ํŒ๋‹จ`));
631
+ }, M);
632
+ };
633
+ ye.current = { resolve: r, reject: a, kick: Y, stop: T, note: h }, Y(), Ue().postMessage({ stl: e, params: t, stall: l });
634
+ });
635
+ }
636
+ function Er() {
637
+ var e;
638
+ try {
639
+ (e = z.current) == null || e.terminate();
640
+ } catch {
641
+ }
642
+ z.current = null, Ue();
643
+ }
644
+ async function hn(e, t) {
645
+ try {
646
+ const r = await bn(e, JSON.stringify(t));
647
+ return { r, economy: !!(r.stats && r.stats.economy) };
648
+ } catch {
649
+ return Er(), { r: await bn(e, JSON.stringify({ ...t, economy: !0 })), economy: !0, recovered: !0 };
650
+ }
651
+ }
652
+ function gn(e) {
653
+ const t = Gt(L);
654
+ return e.extruders >= 2 && e.split > 0 && (t.extruder_count = e.extruders, t.mm_group_split = e.split, t.wipe_tower_real = an), kt.current && (t.sparse_infill_pattern = "rectilinear", t.infill_density = Math.min(t.infill_density ?? 0.15, 0.08), t.economy = !0), typeof window < "u" && window.__vpForceTree && (t.enable_support = !0, t.support_style = "tree", t.support_threshold_angle = 40), t;
655
+ }
656
+ function Tt(e) {
657
+ var s;
658
+ ir();
659
+ const t = U.current;
660
+ t && t.setLayerRange(0, 1e9);
661
+ const r = te.current[e];
662
+ if (!r || r.error || !r.layers || !r.layers.length) {
663
+ Q.current = null, U.current = null, le.current = null, at(null), ot(!1), lt(0), Ne(0), Nt(null), zt([]), it((b) => (b && URL.revokeObjectURL(b), ""));
664
+ return;
665
+ }
666
+ Q.current = r.layers;
667
+ const a = r.layers.length;
668
+ ue.current = 0, ee.current = a - 1, _t(0), St(a - 1);
669
+ const l = y.current[e], d = l && l.layers === r.layers ? l : Pt(e, r.layers);
670
+ d && (U.current = d.ctl, le.current = d.seg, d.ctl.setLayerRange(0, a - 1), Zt(), Ne(d.seg.nSeg), zt(Fn(d.seg.typeLengths))), (s = c.current) == null || s.onSliced(), _e("preview"), at({ layers: r.stats.layers, segments: r.stats.path_segments, filament: r.stats.filament_mm, timeSec: r.stats.time_estimate }), ot(!!r.stats.over_bed), lt(a), it((b) => (b && URL.revokeObjectURL(b), URL.createObjectURL(new Blob([r.gcode], { type: "text/plain" }))));
671
+ }
672
+ function Mr(e, t) {
673
+ const r = URL.createObjectURL(new Blob([e], { type: "text/plain" })), a = document.createElement("a");
674
+ a.href = r, a.download = t, a.style.display = "none", document.body.appendChild(a), a.click(), setTimeout(() => {
675
+ a.remove(), URL.revokeObjectURL(r);
676
+ }, 4e3);
677
+ }
678
+ const Cr = (e) => new Promise((t) => setTimeout(t, e));
679
+ function pt() {
680
+ Jn(Object.values(te.current).filter((e) => e && !e.error && e.gcode).length);
681
+ }
682
+ async function jr() {
683
+ jt(!1);
684
+ const e = Object.entries(te.current).filter(([, t]) => t && !t.error && t.gcode).sort((t, r) => Number(t[0]) - Number(r[0]));
685
+ if (!e.length) {
686
+ _("๋‚ด๋ณด๋‚ผ ์Šฌ๋ผ์ด์Šค ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค โ€” ๋จผ์ € ์Šฌ๋ผ์ด์Šคํ•˜์„ธ์š”");
687
+ return;
688
+ }
689
+ for (const [t, r] of e)
690
+ Mr(r.gcode, `plate_${Number(t) + 1}.gcode`), await Cr(350);
691
+ xe(`${e.length}๊ฐœ ํ”Œ๋ ˆ์ดํŠธ G-code ๋ฅผ ๋‚ด๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค`);
692
+ }
693
+ async function De(e = "current") {
694
+ var r, a;
695
+ jt(!1), _(""), xe(""), Fe(null);
696
+ const t = se.current;
697
+ if (qt.current = Gt(L).line_width, e === "all") {
698
+ fe(!0), Ze(0);
699
+ let l = 0, d = !1;
700
+ const s = [];
701
+ for (let b = 0; b < Oe.current; b++) {
702
+ const u = (r = c.current) == null ? void 0 : r.buildMergedSTL(b);
703
+ if (u) {
704
+ et.current[b] = { offX: u.offX, offZ: u.offZ };
705
+ try {
706
+ const { r: P, economy: m } = await hn(u.buf, gn(u));
707
+ te.current[b] = P, pt(), l++, m && (d = !0);
708
+ } catch {
709
+ s.push(b + 1);
710
+ }
711
+ }
712
+ }
713
+ if (fe(!1), !l) {
714
+ Fe({ scope: "all" }), _("๋ชจ๋“  ํ”Œ๋ ˆ์ดํŠธ ์Šฌ๋ผ์ด์Šค ์‹คํŒจ(์ ˆ์•ฝ ๋ชจ๋“œ ํฌํ•จ) โ€” ๊ฐ„์†Œํ™” ์žฌ์‹œ๋„๋ฅผ ์‹œ๋„ํ•˜์„ธ์š”");
715
+ return;
716
+ }
717
+ s.length && _(`ํ”Œ๋ ˆ์ดํŠธ ${s.join(", ")} ์‹คํŒจ โ€” ์™„์ฃผํ•œ ${l}๊ฐœ ๊ฒฐ๊ณผ๋Š” ์œ ์ง€๋จ(ํƒญ์—์„œ ์กฐํšŒยท๋‚ด๋ณด๋‚ด๊ธฐ)`), d && xe("๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• โ€” ์ผ๋ถ€ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์ ˆ์•ฝ ๋ชจ๋“œ๋กœ ์™„์ฃผ(ํ”„๋ฆฌ๋ทฐ ์—†์Œ, G-code ์ •์ƒ)"), Tt(te.current[t] ? t : Object.keys(te.current).map(Number)[0]);
718
+ } else {
719
+ const l = performance.now(), d = (a = c.current) == null ? void 0 : a.buildMergedSTL(t);
720
+ if (!d) {
721
+ _(`ํ”Œ๋ ˆ์ดํŠธ ${t + 1} ์— ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค`);
722
+ return;
723
+ }
724
+ console.info(`[vp-prof] buildMergedSTL ${(performance.now() - l).toFixed(0)}ms (${(d.buf.byteLength / 1048576).toFixed(1)}MB)`), et.current[t] = { offX: d.offX, offZ: d.offZ }, fe(!0), Ze(0);
725
+ try {
726
+ const { r: s, economy: b } = await hn(d.buf, gn(d));
727
+ s != null && s.stats && console.info(`[vp-prof] kernel stages p1=${(s.stats.t_pass1_ms / 1e3).toFixed(1)}s surf=${(s.stats.t_surface_ms / 1e3).toFixed(1)}s sup=${(s.stats.t_support_ms / 1e3).toFixed(1)}s emit=${(s.stats.t_emit_ms / 1e3).toFixed(1)}s`), te.current[t] = s, pt(), fe(!1), Tt(t), b && xe("๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• โ€” ์ ˆ์•ฝ ๋ชจ๋“œ๋กœ ์™„์ฃผ(ํ”„๋ฆฌ๋ทฐ ์—†์Œ, G-code ๋Š” ๋‹ค์šด๋กœ๋“œ ๊ฐ€๋Šฅ)");
728
+ } catch (s) {
729
+ fe(!1), Fe({ scope: "current" }), _("์Šฌ๋ผ์ด์Šค ์‹คํŒจ(์ ˆ์•ฝ ๋ชจ๋“œ๋„ ์‹คํŒจ): " + s.message);
730
+ }
731
+ }
732
+ }
733
+ async function Nr() {
734
+ const e = pn;
735
+ if (Fe(null), !!e) {
736
+ kt.current = !0;
737
+ try {
738
+ await De(e.scope);
739
+ } finally {
740
+ kt.current = !1;
741
+ }
742
+ }
743
+ }
744
+ function _r() {
745
+ Jt((e) => Math.min(Un, e + 1));
746
+ }
747
+ function Ar() {
748
+ Jt((e) => {
749
+ if (e <= 1) return e;
750
+ const t = e - 1;
751
+ return delete te.current[t], ct(t), pt(), se.current >= t && xn(t - 1), t;
752
+ });
753
+ }
754
+ function xn(e) {
755
+ se.current = e, Xn(e), Pe.current = 0, G === "preview" && Tt(e);
756
+ }
757
+ function vn(e, t) {
758
+ if (!(e > 0) || !(t > 0)) return;
759
+ const r = gt(L, "printable_area"), a = Array.isArray(r) && r.length >= 3, l = a ? Math.min(...r.map((s) => s[0])) : 0, d = a ? Math.min(...r.map((s) => s[1])) : 0;
760
+ $((s) => ({ ...s, printable_area: [[l, d], [l + e, d], [l + e, d + t], [l, d + t]] }));
761
+ }
762
+ function Sr(e, t) {
763
+ var r;
764
+ (r = c.current) == null || r.setObjectExtruder(e, t), rt(w.current.map((a) => ({ id: a.id, name: a.name, extruder: a.extruder, visible: a.visible !== !1 })));
765
+ }
766
+ function ce(e, t) {
767
+ const r = Math.max(0, je - 1);
768
+ if (e = Math.max(0, Math.min(r, e)), t = Math.max(0, Math.min(r, t)), e > t) {
769
+ const a = e;
770
+ e = t, t = a;
771
+ }
772
+ ue.current = e, ee.current = t, _t(e), St(t), dr();
773
+ }
774
+ function zr(e) {
775
+ const t = parseInt(e.target.value, 10);
776
+ ke ? ce(t, t) : ce(t, ee.current);
777
+ }
778
+ function Rr(e) {
779
+ const t = parseInt(e.target.value, 10);
780
+ ce(ke ? t : ue.current, t);
781
+ }
782
+ function wn() {
783
+ const e = !ke;
784
+ tr(e), e && ce(ee.current, ee.current);
785
+ }
786
+ function Lr(e) {
787
+ const t = e.target.value;
788
+ er(t), vt.current = t, Zt();
789
+ }
790
+ function yn(e) {
791
+ const t = e.target.checked;
792
+ ar(t), xt.current = t;
793
+ for (const r of Object.values(y.current)) r.ctl.setTravelVisible(t);
794
+ }
795
+ function Or(e) {
796
+ const t = e.target.checked;
797
+ $((r) => ({ ...r, enable_support: t }));
798
+ }
799
+ const Pr = !!gt(L, "enable_support");
800
+ function Se() {
801
+ rt(w.current.map((e) => ({ id: e.id, name: e.name, extruder: e.extruder, visible: e.visible !== !1 })));
802
+ }
803
+ function Zr(e, t) {
804
+ Ot((r) => {
805
+ var l;
806
+ const a = [...r];
807
+ return a[e] = t, Ae.current = a, (l = c.current) == null || l.recolorObjects(), a;
808
+ });
809
+ }
810
+ function Br() {
811
+ Ot((e) => {
812
+ if (e.length >= 4) return e;
813
+ const t = ["#e0473b", "#3bb0e0", "#7ad14a"], r = [...e, t[e.length - 1] || "#888888"];
814
+ return Ae.current = r, r;
815
+ });
816
+ }
817
+ function Tr() {
818
+ Ot((e) => {
819
+ var r;
820
+ if (e.length <= 1) return e;
821
+ const t = e.slice(0, -1);
822
+ return Ae.current = t, w.current.forEach((a) => {
823
+ var l;
824
+ (a.extruder || 1) > t.length && ((l = c.current) == null || l.setObjectExtruder(a.id, t.length));
825
+ }), (r = c.current) == null || r.recolorObjects(), Se(), t;
826
+ });
827
+ }
828
+ function Ir(e) {
829
+ var r;
830
+ const t = w.current.find((a) => a.id === e);
831
+ (r = c.current) == null || r.setObjectVisible(e, (t == null ? void 0 : t.visible) === !1), Se();
832
+ }
833
+ function Fr() {
834
+ re(ge === "off" ? "enforcer" : "off");
835
+ }
836
+ const Vr = [
837
+ { id: "add", icon: ca, label: "์ถ”๊ฐ€", tip: "๋ชจ๋ธ ํŒŒ์ผ์„ ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ์— ์ถ”๊ฐ€ (๊ธฐ์กด ์˜ค๋ธŒ์ ํŠธ ์œ ์ง€)", run: () => {
838
+ var e;
839
+ return (e = Te.current) == null ? void 0 : e.click();
840
+ } },
841
+ { id: "delete", icon: ma, label: "์‚ญ์ œ", tip: "์„ ํƒํ•œ ์˜ค๋ธŒ์ ํŠธ ์‚ญ์ œ (Del)", run: ut },
842
+ { id: "delete-all", icon: fa, label: "์ „์ฒด ์‚ญ์ œ", tip: "ํ”Œ๋ ˆ์ดํŠธ์˜ ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ ์‚ญ์ œ", run: $r, disabled: () => Ce.length === 0 },
843
+ { sep: !0 },
844
+ { id: "duplicate", icon: ba, label: "๋ณต์ œ", tip: "์„ ํƒ ์˜ค๋ธŒ์ ํŠธ ๋ณต์ œ (Ctrl+K)", run: It },
845
+ { id: "split", icon: $n, label: "๋ถ„๋ฆฌ", tip: "๊ฐ์ฒด๋กœ ๋ถ„๋ฆฌ โ€” ์„œ๋กœ ๋–จ์–ด์ง„ ๋ถ€๋ถ„(์—ฐ๊ฒฐ ์„ฑ๋ถ„)๋งˆ๋‹ค ๋…๋ฆฝ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋‚˜๋ˆ”. ํŒŒํŠธ๋กœ ๋ถ„๋ฆฌ๋Š” ๋ฏธ๊ตฌํ˜„(ํŒŒํŠธ ๊ฐœ๋… ๋ถ€์žฌ)", run: Vt },
846
+ { id: "onbed", icon: wa, label: "๋ฐ”๋‹ฅ์— ๋†“๊ธฐ", tip: "๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฒ ๋“œ ๋ฐ”๋‹ฅ(Z=0)์— ๋ถ™์ž„ โ€” ๊ธฐ์ฆˆ๋ชจ๋กœ ๋„์šด ๋’ค ์žฌ์•ˆ์ฐฉ์šฉ", run: () => {
847
+ var e;
848
+ return (e = c.current) == null ? void 0 : e.placeOnBed();
849
+ } },
850
+ { sep: !0 },
851
+ { id: "arrange", icon: da, label: "๋ฐฐ์น˜", tip: "์ž๋™ ๋ฐฐ์น˜ โ€” ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฒ ๋“œ์— ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์ •๋ ฌ. ๋ฏธ๊ตฌํ˜„(libslic3r Arrange ์ด์‹ ํ•„์š”)" },
852
+ { id: "orient", icon: ka, label: "๋ฐฉํ–ฅ", tip: "์ž๋™ ๋ฐฉํ–ฅ โ€” ์„œํฌํŠธ๊ฐ€ ๋œ ํ•„์š”ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „. ๋ฏธ๊ตฌํ˜„(libslic3r Orient ์ด์‹ ํ•„์š”)" },
853
+ { sep: !0 },
854
+ { id: "cut", icon: ua, label: "์ปท", tip: "์ปท โ€” ํ‰๋ฉด์œผ๋กœ ๋ชจ๋ธ์„ ์ž˜๋ผ ๋‘ ์กฐ๊ฐ์œผ๋กœ ๋ถ„๋ฆฌ. ๋ฏธ๊ตฌํ˜„(์ ˆ๋‹จ๋ฉด ์žฌ๋ด‰ํ•ฉ ํ•„์š”)" },
855
+ { id: "boolean", icon: pa, label: "๋ถˆ๋ฆฌ์–ธ", tip: "๋ฉ”์‹œ ๋ถˆ๋ฆฌ์–ธ โ€” ๋‘ ์˜ค๋ธŒ์ ํŠธ์˜ ํ•ฉ/์ฐจ/๊ต์ง‘ํ•ฉ. ๋ฏธ๊ตฌํ˜„(CGAL ๋ถˆ๋ฆฌ์–ธ ์ด์‹ ํ•„์š”)" },
856
+ { id: "negative", icon: va, label: "์Œ๊ฐ ํŒŒํŠธ", tip: "์Œ๊ฐยท๋ชจ๋””ํŒŒ์ด์–ด ํŒŒํŠธ ์ถ”๊ฐ€ โ€” ํ•œ ์˜ค๋ธŒ์ ํŠธ ์•ˆ์— ์„ฑ์งˆ์ด ๋‹ค๋ฅธ ํŒŒํŠธ๋ฅผ ๋„ฃ์Œ. ๋ฏธ๊ตฌํ˜„(ํŒŒํŠธ ๊ฐœ๋… ๋ถ€์žฌ)" },
857
+ { sep: !0 },
858
+ { id: "seam", icon: ja, label: "์‹ฌ ํŽ˜์ธํŒ…", tip: "์‹ฌ ํŽ˜์ธํŒ… โ€” ๋ ˆ์ด์–ด ์ด์Œ๋งค ์œ„์น˜๋ฅผ ๋ธŒ๋Ÿฌ์‹œ๋กœ ์ง€์ •. ๋ฏธ๊ตฌํ˜„(์ปค๋„ ์‹ฌ ๋ฐฐ์„  ํ•„์š”)" },
859
+ { id: "mmu", icon: ga, label: "์ปฌ๋Ÿฌ ํŽ˜์ธํŒ…", tip: "์ปฌ๋Ÿฌ ํŽ˜์ธํŒ… โ€” ๋ฉ€ํ‹ฐ๋จธํ‹ฐ๋ฆฌ์–ผ ์ƒ‰์„ ๋ฉด ๋‹จ์œ„๋กœ ์ง€์ •. ๋ฏธ๊ตฌํ˜„(MMU ํŽ˜์ธํŠธ ์ฝ”๋ฑ ๋ฐฐ์„  ํ•„์š”)" },
860
+ { id: "text", icon: Na, label: "ํ…์ŠคํŠธ", tip: "ํ…์ŠคํŠธยทSVG ๊ฐ์ธ โ€” ๋ชจ๋ธ ํ‘œ๋ฉด์— ๋ฌธ์ž/๋„ํ˜•์„ ์ƒˆ๊น€. ๋ฏธ๊ตฌํ˜„(ํฐํŠธ ๋ž˜์Šคํ„ฐํ™” ํ•„์š”)" },
861
+ { id: "measure", icon: ha, label: "์ธก์ •", tip: "์ธก์ • โ€” ๋‘ ์ง€์ /๋ฉด ์‚ฌ์ด ๊ฑฐ๋ฆฌยท๊ฐ๋„ ์ธก์ •. ๋ฏธ๊ตฌํ˜„" },
862
+ { id: "varlayer", icon: _a, label: "๊ฐ€๋ณ€ ๋ ˆ์ด์–ด", tip: "๊ฐ€๋ณ€ ๋ ˆ์ด์–ด ๋†’์ด โ€” ๊ตฌ๊ฐ„๋ณ„๋กœ ๋ ˆ์ด์–ด ๋†’์ด๋ฅผ ๋‹ค๋ฅด๊ฒŒ. ๋ฏธ๊ตฌํ˜„(์ปค๋„ ๊ฐ€๋ณ€ z ๋ฏธ์ง€์›)" }
863
+ ];
864
+ function It() {
865
+ var r, a, l;
866
+ const e = (r = c.current) == null ? void 0 : r.selectedObjectId();
867
+ if (!e) {
868
+ _("๋จผ์ € ๋ณต์ œํ•  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”");
869
+ return;
870
+ }
871
+ const t = (a = c.current) == null ? void 0 : a.getSnapshot(e);
872
+ t && ((l = c.current) == null || l.spawnSnapshot(t), Se(), _(""));
873
+ }
874
+ function Ft() {
875
+ var t, r;
876
+ const e = (t = c.current) == null ? void 0 : t.selectedObjectId();
877
+ if (!e) {
878
+ _("๋จผ์ € ๋ณต์‚ฌํ•  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”");
879
+ return;
880
+ }
881
+ Ye.current = (r = c.current) == null ? void 0 : r.getSnapshot(e), _(""), xe("์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค (Ctrl+V ๋กœ ๋ถ™์—ฌ๋„ฃ๊ธฐ)");
882
+ }
883
+ function kn() {
884
+ var e;
885
+ Ye.current && ((e = c.current) == null || e.spawnSnapshot(Ye.current), Se());
886
+ }
887
+ function ut() {
888
+ var t;
889
+ const e = (t = c.current) == null ? void 0 : t.selectedObjectId();
890
+ if (!e) {
891
+ _("๋จผ์ € ์‚ญ์ œํ•  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”");
892
+ return;
893
+ }
894
+ Bt(e), _("");
895
+ }
896
+ function $r() {
897
+ var t;
898
+ const e = w.current.map((r) => r.id);
899
+ if (e.length) {
900
+ for (const r of e) (t = c.current) == null || t.removeObject(r);
901
+ Se(), xe(`${e.length}๊ฐœ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ชจ๋‘ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค`);
902
+ }
903
+ }
904
+ function Vt() {
905
+ var l, d;
906
+ const e = (l = c.current) == null ? void 0 : l.selectedObjectId();
907
+ if (!e) {
908
+ _("๋จผ์ € ๋ถ„๋ฆฌํ•  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์„ ํƒํ•˜์„ธ์š”");
909
+ return;
910
+ }
911
+ const t = (d = c.current) == null ? void 0 : d.getSnapshot(e);
912
+ if (!t) return;
913
+ let r;
914
+ try {
915
+ r = ra(t.localPos);
916
+ } catch (s) {
917
+ _("๋ถ„๋ฆฌ ์‹คํŒจ: " + ((s == null ? void 0 : s.message) || s));
918
+ return;
919
+ }
920
+ if (!r || r.length < 2) {
921
+ _("๋ถ„๋ฆฌํ•  ๋…๋ฆฝ ๋ถ€๋ถ„์ด ์—†์Šต๋‹ˆ๋‹ค โ€” ํ•˜๋‚˜๋กœ ์—ฐ๊ฒฐ๋œ ๋ฉ”์‹œ์ž…๋‹ˆ๋‹ค");
922
+ return;
923
+ }
924
+ const a = String(t.name || "object").replace(/\.[^.]+$/, "");
925
+ Bt(e), r.forEach((s, b) => {
926
+ var u;
927
+ return (u = c.current) == null ? void 0 : u.spawnSnapshot(
928
+ { name: `${a}_${b + 1}`, localPos: s, rot: t.rot, scale: t.scale, pos: t.pos },
929
+ !0
930
+ );
931
+ }), Se(), _(""), xe(`${r.length}๊ฐœ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค`);
932
+ }
933
+ function $t(e) {
934
+ var t;
935
+ q.current !== "off" && re("off"), (t = c.current) == null || t.setMode(e);
936
+ }
937
+ Xe.current = (e) => {
938
+ var b, u, P, m, h, I, T, Y, M;
939
+ const t = e.composedPath ? e.composedPath()[0] : e.target;
940
+ if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.tagName === "SELECT" || t.isContentEditable)) return;
941
+ const r = e.key, a = typeof r == "string" ? r.toLowerCase() : "", l = e.ctrlKey || e.metaKey, d = me.current === "preview", s = () => {
942
+ e.preventDefault(), e.stopPropagation();
943
+ };
944
+ if (l) {
945
+ a === "r" ? (s(), Mt || De("current")) : a === "c" ? (s(), Ft()) : a === "v" ? (s(), kn()) : a === "x" ? (s(), Ft(), ut()) : (a === "k" || a === "d") && (s(), It());
946
+ return;
947
+ }
948
+ if (d) {
949
+ const j = e.shiftKey ? 10 : 1;
950
+ if (r === "ArrowUp") {
951
+ s();
952
+ const Z = ee.current + j;
953
+ ce(ke ? Z : ue.current, Z);
954
+ } else if (r === "ArrowDown") {
955
+ s();
956
+ const Z = ee.current - j;
957
+ ce(ke ? Z : ue.current, Z);
958
+ } else a === "l" ? (s(), wn()) : a === "t" ? (s(), yn({ target: { checked: !xt.current } })) : a === "z" ? (s(), (b = c.current) == null || b.frame()) : a === "b" ? (s(), (u = c.current) == null || u.frameBed()) : r === "Escape" && (s(), _e("prepare"));
959
+ return;
960
+ }
961
+ if (a === "m" || a === "g")
962
+ s(), $t("translate");
963
+ else if (a === "r")
964
+ s(), $t("rotate");
965
+ else if (a === "s")
966
+ s(), $t("scale");
967
+ else if (a === "z")
968
+ s(), (P = c.current) == null || P.frame();
969
+ else if (a === "b")
970
+ s(), (m = c.current) == null || m.frameBed();
971
+ else if (r === "Delete" || r === "Backspace")
972
+ s(), ut();
973
+ else if (r === "Escape")
974
+ s(), q.current !== "off" && re("off"), (h = c.current) == null || h.detachTransform();
975
+ else if (r === "PageUp")
976
+ s(), (I = c.current) == null || I.rotateSelectedY(Math.PI / 4);
977
+ else if (r === "PageDown")
978
+ s(), (T = c.current) == null || T.rotateSelectedY(-Math.PI / 4);
979
+ else if ((Y = r.startsWith) != null && Y.call(r, "Arrow")) {
980
+ s();
981
+ const j = e.shiftKey ? 1 : 10;
982
+ (M = c.current) == null || M.nudgeSelected(
983
+ r === "ArrowLeft" ? -j : r === "ArrowRight" ? j : 0,
984
+ r === "ArrowUp" ? -j : r === "ArrowDown" ? j : 0
985
+ );
986
+ } else r === "?" && (s(), en((j) => !j));
987
+ };
988
+ const Ur = X.nozzle_diameter || gt(L, "nozzle_diameter") || "0.4";
989
+ (Cn = (Mn = N.current).invalidate) == null || Cn.call(Mn);
990
+ const En = je > 0 && /* @__PURE__ */ n.createElement("div", { className: "slice-layer", "data-testid": "preview-controls" }, /* @__PURE__ */ n.createElement("label", { className: "view-type-row" }, "๋ทฐ ํƒ€์ž…", /* @__PURE__ */ n.createElement("select", { value: Qn, onChange: Lr, "data-testid": "view-type-select", title: "ํˆดํŒจ์Šค ์ƒ‰์„ ๋ฌด์—‡์œผ๋กœ ์น ํ• ์ง€ โ€” ํ”ผ์ฒ˜ ์ข…๋ฅ˜ยท์†๋„ยท๋ ˆ์ด์–ด ๋†’์ดยทํญยทํŒฌยท์˜จ๋„" }, Qr.map((e) => /* @__PURE__ */ n.createElement("option", { key: e.key, value: e.key }, e.label)))), /* @__PURE__ */ n.createElement("label", null, "๋ ˆ์ด์–ด ", /* @__PURE__ */ n.createElement("b", { "data-testid": "layer-range" }, ke ? At + 1 : `${nn + 1}..${At + 1}`), " / ", je, /* @__PURE__ */ n.createElement("span", { className: "muted" }, " (", Wn.toLocaleString(), " ์„ธ๊ทธ๋จผํŠธ)")), /* @__PURE__ */ n.createElement("div", { className: "dual-slider" }, /* @__PURE__ */ n.createElement("input", { type: "range", min: "0", max: Math.max(0, je - 1), value: nn, onChange: zr, "data-testid": "layer-lo", title: "ํ‘œ์‹œํ•  ์ตœํ•˜๋‹จ ๋ ˆ์ด์–ด (โ†“/โ†‘ ๋กœ๋„ ์กฐ์ ˆ)" }), /* @__PURE__ */ n.createElement("input", { type: "range", min: "0", max: Math.max(0, je - 1), value: At, onChange: Rr, "data-testid": "layer-hi", title: "ํ‘œ์‹œํ•  ์ตœ์ƒ๋‹จ ๋ ˆ์ด์–ด (โ†“/โ†‘, Shift ๋กœ 10๋‹จ๊ณ„)" })), /* @__PURE__ */ n.createElement("div", { className: "layer-ctl" }, /* @__PURE__ */ n.createElement("button", { className: ke ? "on" : "", onClick: wn, "data-testid": "single-layer-btn", title: "์„ ํƒํ•œ ํ•œ ์ธต๋งŒ ๋ณด๊ธฐ (L)" }, "๋‹จ์ผ ๋ ˆ์ด์–ด"), /* @__PURE__ */ n.createElement("label", { className: "slice-travel" }, /* @__PURE__ */ n.createElement("input", { type: "checkbox", checked: rr, onChange: yn, "data-testid": "travel-toggle", title: "์••์ถœ ์—†์ด ์ด๋™ํ•˜๋Š” ๊ฒฝ๋กœ๋ฅผ ํšŒ์ƒ‰ ์„ ์œผ๋กœ ํ‘œ์‹œ (T)" }), " ํŠธ๋ž˜๋ธ”")), he && he.cont ? /* @__PURE__ */ n.createElement("div", { className: "grad-legend", "data-testid": "view-legend" }, /* @__PURE__ */ n.createElement("div", { className: "grad-title" }, he.label, " ", /* @__PURE__ */ n.createElement("span", { className: "muted" }, he.unit)), /* @__PURE__ */ n.createElement("div", { className: "grad-bar", "data-testid": "gradient-bar", style: { background: `linear-gradient(to right, ${ea.map((e) => `rgb(${Math.round(e[0] * 255)},${Math.round(e[1] * 255)},${Math.round(e[2] * 255)})`).join(",")})` } }), /* @__PURE__ */ n.createElement("div", { className: "grad-minmax" }, /* @__PURE__ */ n.createElement("span", { "data-testid": "grad-min" }, he.min.toFixed(he.unit === "mm" ? 2 : 0)), /* @__PURE__ */ n.createElement("span", { "data-testid": "grad-max" }, he.max.toFixed(he.unit === "mm" ? 2 : 0)))) : /* @__PURE__ */ n.createElement("div", { className: "role-legend", "data-testid": "view-legend" }, nr.map((e) => /* @__PURE__ */ n.createElement("span", { key: e.type, className: "role-item" }, /* @__PURE__ */ n.createElement("i", { style: { background: `rgb(${Math.round(e.color[0] * 255)},${Math.round(e.color[1] * 255)},${Math.round(e.color[2] * 255)})` } }), e.label, " ", /* @__PURE__ */ n.createElement("b", null, e.pct.toFixed(0), "%"))))), Dr = be && /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement("div", null, /* @__PURE__ */ n.createElement("b", null, be.layers), " ๋ ˆ์ด์–ด ยท ", /* @__PURE__ */ n.createElement("b", null, be.segments), " ์„ธ๊ทธ๋จผํŠธ"), /* @__PURE__ */ n.createElement("div", null, "ํ•„๋ผ๋ฉ˜ํŠธ ", /* @__PURE__ */ n.createElement("b", null, be.filament.toFixed(1)), " mm"), typeof be.timeSec == "number" && be.timeSec > 0 && (() => {
991
+ const e = Math.round(be.timeSec), t = `${Math.floor(e / 3600)}h ${String(Math.floor(e % 3600 / 60)).padStart(2, "0")}m ${String(e % 60).padStart(2, "0")}s`;
992
+ return /* @__PURE__ */ n.createElement("div", { "data-testid": "print-time" }, "โฑ ์˜ˆ์ƒ ์ถœ๋ ฅ ", /* @__PURE__ */ n.createElement("b", null, t));
993
+ })(), qn && /* @__PURE__ */ n.createElement("div", { className: "slice-warn", "data-testid": "over-bed" }, "โš  ๋ชจ๋ธ์ด ๋ฒ ๋“œ๋ฅผ ๋ฒ—์–ด๋‚จ"));
994
+ return /* @__PURE__ */ n.createElement(sa, { css: ia }, /* @__PURE__ */ n.createElement("div", { className: "app-shell" }, /* @__PURE__ */ n.createElement("input", { ref: Te, type: "file", accept: ".stl,.obj,.3mf,.amf,.ply", multiple: !0, onChange: fr, title: "STLยทOBJยท3MFยทAMFยทPLY (์—ฌ๋Ÿฌ ๊ฐœ ์„ ํƒ ๊ฐ€๋Šฅ)", "data-testid": "stl-input", style: { display: "none" } }), /* @__PURE__ */ n.createElement("header", { className: "topbar" }, /* @__PURE__ */ n.createElement("div", { className: "tb-left" }, /* @__PURE__ */ n.createElement("span", { className: "tb-logo" }, /* @__PURE__ */ n.createElement("b", null, "Three"), "Slicer ", /* @__PURE__ */ n.createElement("span", { className: "tb-re" }, "RE")), /* @__PURE__ */ n.createElement("button", { className: "tb-btn", onClick: () => {
995
+ var e;
996
+ return (e = Te.current) == null ? void 0 : e.click();
997
+ }, title: "๋ชจ๋ธ ํŒŒ์ผ ์—ด๊ธฐ โ€” ๊ธฐ์กด ์˜ค๋ธŒ์ ํŠธ๋Š” ๋ชจ๋‘ ์ง€์›Œ์ง", "data-testid": "open-file" }, /* @__PURE__ */ n.createElement("img", { src: ya, alt: "" }), /* @__PURE__ */ n.createElement("span", null, "์—ด๊ธฐ"))), W && /* @__PURE__ */ n.createElement("div", { className: "tb-tabs", role: "tablist", "aria-label": "์บ”๋ฒ„์Šค ๋ชจ๋“œ" }, /* @__PURE__ */ n.createElement("button", { role: "tab", className: G === "prepare" ? "on" : "", onClick: () => _e("prepare"), "data-testid": "mode-prepare", title: "๋ชจ๋ธ ๋ฐฐ์น˜ยท๋ณ€ํ˜•ยท์„œํฌํŠธ ํŽ˜์ธํŒ…" }, "Prepare"), /* @__PURE__ */ n.createElement("button", { role: "tab", className: G === "preview" ? "on" : "", onClick: () => _e("preview"), disabled: je === 0, "data-testid": "mode-preview", title: "์Šฌ๋ผ์ด์Šค๋œ ํˆดํŒจ์Šค ๋ฏธ๋ฆฌ๋ณด๊ธฐ (์Šฌ๋ผ์ด์Šค ํ›„ ํ™œ์„ฑํ™”)" }, "Preview")), /* @__PURE__ */ n.createElement("div", { className: "tb-right" }, /* @__PURE__ */ n.createElement("button", { className: "tb-icon", disabled: !0, title: "์‹คํ–‰ ์ทจ์†Œ โ€” ๋ฏธ๊ตฌํ˜„(์ž‘์—… ์ด๋ ฅ ์Šคํƒ ํ•„์š”)" }, "โ†ถ"), /* @__PURE__ */ n.createElement("button", { className: "tb-icon", disabled: !0, title: "๋‹ค์‹œ ์‹คํ–‰ โ€” ๋ฏธ๊ตฌํ˜„(์ž‘์—… ์ด๋ ฅ ์Šคํƒ ํ•„์š”)" }, "โ†ท"))), /* @__PURE__ */ n.createElement("div", { className: "app-body" }, W && G === "prepare" && /* @__PURE__ */ n.createElement("nav", { className: "left-rail", role: "toolbar", "aria-label": "๊ธฐ์ฆˆ๋ชจ ๋„๊ตฌ" }, /* @__PURE__ */ n.createElement("button", { className: Et === "translate" && ge === "off" ? "on" : "", onClick: () => {
998
+ var e;
999
+ re("off"), (e = c.current) == null || e.setMode("translate");
1000
+ }, title: "์˜ค๋ธŒ์ ํŠธ ์ด๋™ โ€” ๊ธฐ์ฆˆ๋ชจ ์ถ•์„ ๋Œ๊ฑฐ๋‚˜ ๋ฐฉํ–ฅํ‚ค๋กœ 10mm(Shift 1mm) ์ด๋™ (M/G)", "data-testid": "gizmo-move" }, /* @__PURE__ */ n.createElement("img", { src: xa, alt: "์ด๋™" })), /* @__PURE__ */ n.createElement("button", { className: Et === "rotate" && ge === "off" ? "on" : "", onClick: () => {
1001
+ var e;
1002
+ re("off"), (e = c.current) == null || e.setMode("rotate");
1003
+ }, title: "์˜ค๋ธŒ์ ํŠธ ํšŒ์ „ โ€” PageUp/PageDown ์œผ๋กœ 45ยฐ ๋‹จ์œ„ ํšŒ์ „ (R)", "data-testid": "gizmo-rotate" }, /* @__PURE__ */ n.createElement("img", { src: Ma, alt: "ํšŒ์ „" })), /* @__PURE__ */ n.createElement("button", { className: Et === "scale" && ge === "off" ? "on" : "", onClick: () => {
1004
+ var e;
1005
+ re("off"), (e = c.current) == null || e.setMode("scale");
1006
+ }, title: "์˜ค๋ธŒ์ ํŠธ ํฌ๊ธฐ ์กฐ์ ˆ (S)", "data-testid": "gizmo-scale" }, /* @__PURE__ */ n.createElement("img", { src: Ca, alt: "์Šค์ผ€์ผ" })), /* @__PURE__ */ n.createElement("div", { className: "rail-sep" }), /* @__PURE__ */ n.createElement("button", { className: ge !== "off" ? "on" : "", onClick: Fr, title: "๋ธŒ๋Ÿฌ์‹œ๋กœ ๋ฉด์„ ์น ํ•ด ์„œํฌํŠธ๋ฅผ ๊ฐ•์ œํ•˜๊ฑฐ๋‚˜ ์ฐจ๋‹จ โ€” ํœ ๋กœ ๋ธŒ๋Ÿฌ์‹œ ํฌ๊ธฐ ์กฐ์ ˆ", "data-testid": "gizmo-paint" }, /* @__PURE__ */ n.createElement("img", { src: Ea, alt: "์„œํฌํŠธ ํŽ˜์ธํŒ…" }))), /* @__PURE__ */ n.createElement("div", { className: "viewport-col" }, /* @__PURE__ */ n.createElement(
1007
+ "div",
1008
+ {
1009
+ className: (W ? "vp-canvas" : "vp-canvas fail") + (Rt ? " drag-over" : ""),
1010
+ ref: J,
1011
+ onDrop: br,
1012
+ onDragOver: hr,
1013
+ onDragLeave: gr,
1014
+ "data-testid": "drop-zone"
1015
+ },
1016
+ !W && /* @__PURE__ */ n.createElement("div", { className: "vp-fallback" }, "โš  ", Wt),
1017
+ W && Ce.length === 0 && G !== "preview" && /* @__PURE__ */ n.createElement("div", { className: "empty-hint", "data-testid": "empty-hint" }, /* @__PURE__ */ n.createElement("div", { className: "eh-icon" }, "๐Ÿ“ฆ"), /* @__PURE__ */ n.createElement("div", { className: "eh-title" }, "ํŒŒ์ผ์„ ๋“œ๋ž˜๊ทธํ•˜๊ฑฐ๋‚˜ ์„ ํƒํ•˜์„ธ์š”"), /* @__PURE__ */ n.createElement("div", { className: "eh-sub" }, "STL ยท OBJ ยท 3MF ยท AMF ยท PLY"), /* @__PURE__ */ n.createElement("button", { className: "eh-btn", onClick: () => {
1018
+ var e;
1019
+ return (e = Te.current) == null ? void 0 : e.click();
1020
+ }, "data-testid": "empty-pick", title: "STLยทOBJยท3MFยทAMFยทPLY ํŒŒ์ผ ์„ ํƒ (์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€๋Šฅ)" }, "ํŒŒ์ผ ์„ ํƒ")),
1021
+ Rt && /* @__PURE__ */ n.createElement("div", { className: "drop-overlay", "data-testid": "drop-overlay" }, "์—ฌ๊ธฐ์— ๋†“๊ธฐ (STL/OBJ/3MF/AMF/PLY)"),
1022
+ st && /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement("div", { className: "ctx-scrim", onPointerDown: () => D(null), onContextMenu: (e) => {
1023
+ e.preventDefault(), D(null);
1024
+ } }), /* @__PURE__ */ n.createElement("div", { className: "ctx-menu", style: { left: st.x, top: st.y }, "data-testid": "ctx-menu" }, st.onObject ? /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement("button", { onClick: () => {
1025
+ D(null), It();
1026
+ }, "data-testid": "ctx-duplicate", title: "์„ ํƒ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๊ฐ™์€ ํฌ๊ธฐยทํšŒ์ „์œผ๋กœ ๋ณต์ œํ•ด ์˜†์— ๋ฐฐ์น˜" }, "๋ณต์ œ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "Ctrl+K")), /* @__PURE__ */ n.createElement("button", { onClick: () => {
1027
+ D(null), Ft();
1028
+ }, "data-testid": "ctx-copy", title: "์„ ํƒ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฒ„ํผ์— ๋ณต์‚ฌ (๋ถ™์—ฌ๋„ฃ๊ธฐ๋กœ ์ถ”๊ฐ€)" }, "๋ณต์‚ฌ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "Ctrl+C")), /* @__PURE__ */ n.createElement("button", { onClick: () => {
1029
+ D(null), Vt();
1030
+ }, "data-testid": "ctx-split", title: "๊ฐ์ฒด๋กœ ๋ถ„๋ฆฌ โ€” ์„œ๋กœ ๋–จ์–ด์ง„ ๋ถ€๋ถ„(์—ฐ๊ฒฐ ์„ฑ๋ถ„)๋งˆ๋‹ค ๋…๋ฆฝ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋‚˜๋ˆ”. ํŒŒํŠธ๋กœ ๋ถ„๋ฆฌ๋Š” ๋ฏธ๊ตฌํ˜„(ํŒŒํŠธ ๊ฐœ๋… ๋ถ€์žฌ)" }, "๋ถ„๋ฆฌ"), /* @__PURE__ */ n.createElement("button", { onClick: () => {
1031
+ var e;
1032
+ D(null), (e = c.current) == null || e.placeOnBed();
1033
+ }, "data-testid": "ctx-seat", title: "๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฒ ๋“œ ๋ฐ”๋‹ฅ(Z=0)์— ๋ถ™์ž„" }, "๋ฐ”๋‹ฅ์— ๋†“๊ธฐ"), /* @__PURE__ */ n.createElement("hr", null), /* @__PURE__ */ n.createElement("button", { className: "danger", onClick: () => {
1034
+ D(null), ut();
1035
+ }, "data-testid": "ctx-delete", title: "์„ ํƒ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์”ฌ์—์„œ ์ œ๊ฑฐ" }, "์‚ญ์ œ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "Del"))) : /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement("button", { onClick: () => {
1036
+ var e;
1037
+ D(null), (e = Te.current) == null || e.click();
1038
+ }, "data-testid": "ctx-open", title: "๋ชจ๋ธ ํŒŒ์ผ์„ ์—ด์–ด ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ์— ์ถ”๊ฐ€" }, "๋ชจ๋ธ ์—ด๊ธฐโ€ฆ"), /* @__PURE__ */ n.createElement("button", { disabled: !Ye.current, onClick: () => {
1039
+ D(null), kn();
1040
+ }, "data-testid": "ctx-paste", title: "๋ณต์‚ฌํ•ด ๋‘” ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ์— ์ถ”๊ฐ€" }, "๋ถ™์—ฌ๋„ฃ๊ธฐ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "Ctrl+V")), /* @__PURE__ */ n.createElement("hr", null), /* @__PURE__ */ n.createElement("button", { onClick: () => {
1041
+ var e;
1042
+ D(null), (e = c.current) == null || e.frame();
1043
+ }, "data-testid": "ctx-zoom-all", title: "๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋ณด์ด๋„๋ก ์นด๋ฉ”๋ผ ๋งž์ถค" }, "์ „์ฒด ๋ณด๊ธฐ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "Z")), /* @__PURE__ */ n.createElement("button", { onClick: () => {
1044
+ var e;
1045
+ D(null), (e = c.current) == null || e.frameBed();
1046
+ }, "data-testid": "ctx-zoom-bed", title: "์„ ํƒํ•œ ํ”Œ๋ ˆ์ดํŠธ ์ „์ฒด๊ฐ€ ๋ณด์ด๋„๋ก ์นด๋ฉ”๋ผ ๋งž์ถค" }, "๋ฒ ๋“œ ๋ณด๊ธฐ ", /* @__PURE__ */ n.createElement("span", { className: "ctx-key" }, "B"))))),
1047
+ Kn && /* @__PURE__ */ n.createElement("div", { className: "help-overlay", "data-testid": "help-overlay", onClick: () => en(!1) }, /* @__PURE__ */ n.createElement("div", { className: "help-card", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ n.createElement("h3", null, "๋‹จ์ถ•ํ‚ค ", /* @__PURE__ */ n.createElement("span", { className: "muted" }, "(? ๋กœ ๋‹ซ๊ธฐ)")), /* @__PURE__ */ n.createElement("div", { className: "help-cols" }, /* @__PURE__ */ n.createElement("section", null, /* @__PURE__ */ n.createElement("h4", null, "Prepare"), /* @__PURE__ */ n.createElement("dl", null, /* @__PURE__ */ n.createElement("dt", null, "M / G"), /* @__PURE__ */ n.createElement("dd", null, "์ด๋™"), /* @__PURE__ */ n.createElement("dt", null, "R"), /* @__PURE__ */ n.createElement("dd", null, "ํšŒ์ „"), /* @__PURE__ */ n.createElement("dt", null, "S"), /* @__PURE__ */ n.createElement("dd", null, "์Šค์ผ€์ผ"), /* @__PURE__ */ n.createElement("dt", null, "๋ฐฉํ–ฅํ‚ค"), /* @__PURE__ */ n.createElement("dd", null, "10mm ์ด๋™ (Shift 1mm)"), /* @__PURE__ */ n.createElement("dt", null, "PageUp/Down"), /* @__PURE__ */ n.createElement("dd", null, "45ยฐ ํšŒ์ „"), /* @__PURE__ */ n.createElement("dt", null, "Del"), /* @__PURE__ */ n.createElement("dd", null, "์„ ํƒ ์‚ญ์ œ"), /* @__PURE__ */ n.createElement("dt", null, "Esc"), /* @__PURE__ */ n.createElement("dd", null, "์„ ํƒ/ํŽ˜์ธํŠธ ํ•ด์ œ"))), /* @__PURE__ */ n.createElement("section", null, /* @__PURE__ */ n.createElement("h4", null, "Preview"), /* @__PURE__ */ n.createElement("dl", null, /* @__PURE__ */ n.createElement("dt", null, "โ†‘ / โ†“"), /* @__PURE__ */ n.createElement("dd", null, "๋ ˆ์ด์–ด (Shift 10๋‹จ๊ณ„)"), /* @__PURE__ */ n.createElement("dt", null, "L"), /* @__PURE__ */ n.createElement("dd", null, "๋‹จ์ผ ๋ ˆ์ด์–ด"), /* @__PURE__ */ n.createElement("dt", null, "T"), /* @__PURE__ */ n.createElement("dd", null, "ํŠธ๋ž˜๋ธ”"), /* @__PURE__ */ n.createElement("dt", null, "Esc"), /* @__PURE__ */ n.createElement("dd", null, "Prepare ๋กœ"))), /* @__PURE__ */ n.createElement("section", null, /* @__PURE__ */ n.createElement("h4", null, "๊ณตํ†ต"), /* @__PURE__ */ n.createElement("dl", null, /* @__PURE__ */ n.createElement("dt", null, "Ctrl+R"), /* @__PURE__ */ n.createElement("dd", null, "์Šฌ๋ผ์ด์Šค"), /* @__PURE__ */ n.createElement("dt", null, "Ctrl+K / โŒ˜D"), /* @__PURE__ */ n.createElement("dd", null, "๋ณต์ œ"), /* @__PURE__ */ n.createElement("dt", null, "Ctrl+C/V/X"), /* @__PURE__ */ n.createElement("dd", null, "๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐ/์ž˜๋ผ๋‚ด๊ธฐ"), /* @__PURE__ */ n.createElement("dt", null, "Z / B"), /* @__PURE__ */ n.createElement("dd", null, "์ „์ฒด / ๋ฒ ๋“œ๋กœ ์คŒ"))))))
1048
+ ), W && G === "prepare" && /* @__PURE__ */ n.createElement("div", { className: "vp-top-toolbar", role: "toolbar", "aria-label": "์˜ค๋ธŒ์ ํŠธ ๋„๊ตฌ" }, Vr.map((e, t) => {
1049
+ var r;
1050
+ return e.sep ? /* @__PURE__ */ n.createElement("span", { key: "sep" + t, className: "vtt-sep" }) : /* @__PURE__ */ n.createElement(
1051
+ "button",
1052
+ {
1053
+ key: e.id,
1054
+ onClick: e.run,
1055
+ disabled: ((r = e.disabled) == null ? void 0 : r.call(e)) ?? !e.run,
1056
+ title: e.tip,
1057
+ "data-testid": `tool-${e.id}`
1058
+ },
1059
+ /* @__PURE__ */ n.createElement("img", { src: e.icon, alt: e.label })
1060
+ );
1061
+ })), W && G === "prepare" && ge !== "off" && /* @__PURE__ */ n.createElement("div", { className: "brush-panel", "data-testid": "paint-tools" }, /* @__PURE__ */ n.createElement("div", { className: "bp-title" }, "์„œํฌํŠธ ํŽ˜์ธํŒ…"), /* @__PURE__ */ n.createElement("div", { className: "bp-modes" }, /* @__PURE__ */ n.createElement("button", { className: ge === "enforcer" ? "on enf" : "enf", onClick: () => re("enforcer"), title: "์น ํ•œ ๋ฉด ์•„๋ž˜์— ์„œํฌํŠธ๋ฅผ ๊ฐ•์ œ๋กœ ์ƒ์„ฑ", "data-testid": "paint-enforcer" }, "enforcer"), /* @__PURE__ */ n.createElement("button", { className: ge === "blocker" ? "on blk" : "blk", onClick: () => re("blocker"), title: "์น ํ•œ ๋ฉด ์•„๋ž˜์— ์„œํฌํŠธ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๊ฒŒ ์ฐจ๋‹จ", "data-testid": "paint-blocker" }, "blocker"), /* @__PURE__ */ n.createElement("button", { onClick: wr, "data-testid": "paint-clear", title: "์น ํ•œ ๊ฐ•์ œ/์ฐจ๋‹จ ์˜์—ญ์„ ๋ชจ๋‘ ์ง€์›€" }, "์ง€์šฐ๊ธฐ"), /* @__PURE__ */ n.createElement("button", { onClick: () => re("off"), "data-testid": "paint-off", title: "ํŽ˜์ธํŒ… ๋ชจ๋“œ ์ข…๋ฃŒ (Esc)" }, "๋‹ซ๊ธฐ")), /* @__PURE__ */ n.createElement("label", { className: "bp-radius" }, "๋ธŒ๋Ÿฌ์‹œ ๋ฐ˜๊ฒฝ ", on, "mm", /* @__PURE__ */ n.createElement(
1062
+ "input",
1063
+ {
1064
+ type: "range",
1065
+ min: "1",
1066
+ max: "15",
1067
+ step: "0.5",
1068
+ value: on,
1069
+ onChange: (e) => {
1070
+ const t = parseFloat(e.target.value);
1071
+ ln(t), Ke.current = t;
1072
+ },
1073
+ "data-testid": "brush-radius"
1074
+ }
1075
+ )), /* @__PURE__ */ n.createElement("div", { className: "muted bp-counts", "data-testid": "paint-counts" }, "enforcer ", sn.enf, " ยท blocker ", sn.blk, " ยท ๋ชจ๋ธ ์œ„ ๋“œ๋ž˜๊ทธ๋กœ ํŽ˜์ธํŠธ")), W && G === "preview" && be && /* @__PURE__ */ n.createElement("div", { className: "stats-card", "data-testid": "slice-stats" }, Dr), W && /* @__PURE__ */ n.createElement("div", { className: "plate-bar", "data-testid": "plate-bar", role: "tablist", "aria-label": "ํ”Œ๋ ˆ์ดํŠธ" }, Array.from({ length: ne }, (e, t) => /* @__PURE__ */ n.createElement("button", { key: t, role: "tab", className: "plate-tab" + (t === Be ? " on" : ""), onClick: () => xn(t), title: `ํ”Œ๋ ˆ์ดํŠธ ${t + 1} ์„ ํƒ โ€” Preview ์—์„  ์ด ํ”Œ๋ ˆ์ดํŠธ ๊ฒฐ๊ณผ๋กœ ์ „ํ™˜`, "data-testid": `plate-${t}`, title: `ํ”Œ๋ ˆ์ดํŠธ ${t + 1}` }, t + 1)), /* @__PURE__ */ n.createElement("button", { className: "plate-add", onClick: _r, disabled: ne >= Un, title: "๋นˆ ํ”Œ๋ ˆ์ดํŠธ ์ถ”๊ฐ€ (์ตœ๋Œ€ 9๊ฐœ) โ€” ํ”Œ๋ ˆ์ดํŠธ๋ณ„๋กœ ๋”ฐ๋กœ ์Šฌ๋ผ์ด์Šคยท๋‚ด๋ณด๋‚ด๊ธฐ", "data-testid": "plate-add" }, "+"), ne > 1 && /* @__PURE__ */ n.createElement("button", { className: "plate-del", onClick: Ar, title: "๋งˆ์ง€๋ง‰ ํ”Œ๋ ˆ์ดํŠธ์™€ ๊ทธ ์Šฌ๋ผ์ด์Šค ๊ฒฐ๊ณผ ์‚ญ์ œ", "data-testid": "plate-del" }, "โˆ’")), W && /* @__PURE__ */ n.createElement("div", { className: "vp-status", "data-testid": "vp-status" }, Wt)), W && /* @__PURE__ */ n.createElement("aside", { className: "sidebar" }, /* @__PURE__ */ n.createElement("div", { className: "sidebar-scroll" }, /* @__PURE__ */ n.createElement("section", { className: "side-card" }, /* @__PURE__ */ n.createElement("div", { className: "sc-head" }, "๐Ÿ–จ ํ”„๋ฆฐํ„ฐ"), /* @__PURE__ */ n.createElement("div", { className: "sc-info" }, /* @__PURE__ */ n.createElement("span", null, "๋ฒ ๋“œ"), /* @__PURE__ */ n.createElement("span", { className: "sc-bed", title: "ํ”Œ๋ ˆ์ดํŠธ ํฌ๊ธฐ โ€” Enter ๋˜๋Š” ํฌ์ปค์Šค ์•„์›ƒ์œผ๋กœ ์ ์šฉ. ์›ํ˜•/์ปค์Šคํ…€ ํ˜•์ƒ์€ printable_area ์˜ต์…˜์—์„œ" }, /* @__PURE__ */ n.createElement(
1076
+ "input",
1077
+ {
1078
+ type: "number",
1079
+ min: "1",
1080
+ key: `w${Math.round(X.bed_width)}`,
1081
+ defaultValue: Math.round(X.bed_width),
1082
+ onBlur: (e) => vn(+e.target.value, X.bed_depth),
1083
+ onKeyDown: (e) => {
1084
+ e.key === "Enter" && e.target.blur();
1085
+ },
1086
+ "data-testid": "bed-w-card"
1087
+ }
1088
+ ), "ร—", /* @__PURE__ */ n.createElement(
1089
+ "input",
1090
+ {
1091
+ type: "number",
1092
+ min: "1",
1093
+ key: `d${Math.round(X.bed_depth)}`,
1094
+ defaultValue: Math.round(X.bed_depth),
1095
+ onBlur: (e) => vn(X.bed_width, +e.target.value),
1096
+ onKeyDown: (e) => {
1097
+ e.key === "Enter" && e.target.blur();
1098
+ },
1099
+ "data-testid": "bed-d-card"
1100
+ }
1101
+ ), "mm")), /* @__PURE__ */ n.createElement("div", { className: "sc-info" }, /* @__PURE__ */ n.createElement("span", null, "๋…ธ์ฆ ร˜"), /* @__PURE__ */ n.createElement("b", null, Ur, " mm"))), /* @__PURE__ */ n.createElement("section", { className: "side-card", "data-testid": "filament-section" }, /* @__PURE__ */ n.createElement("div", { className: "sc-head" }, "๐Ÿงต ํ•„๋ผ๋ฉ˜ํŠธ ", /* @__PURE__ */ n.createElement("span", { className: "sc-count" }, Ie.length), /* @__PURE__ */ n.createElement("span", { className: "sc-head-btns" }, /* @__PURE__ */ n.createElement("button", { onClick: Br, disabled: Ie.length >= 4, title: "ํ•„๋ผ๋ฉ˜ํŠธ(์ต์ŠคํŠธ๋ฃจ๋”) ์ถ”๊ฐ€ โ€” ์ตœ๋Œ€ 4๊ฐœ, ์˜ค๋ธŒ์ ํŠธ๋ณ„๋กœ ์ง€์ • ๊ฐ€๋Šฅ", "data-testid": "filament-add" }, "+"), /* @__PURE__ */ n.createElement("button", { onClick: Tr, disabled: Ie.length <= 1, title: "๋งˆ์ง€๋ง‰ ํ•„๋ผ๋ฉ˜ํŠธ ์ œ๊ฑฐ โ€” ์ด๋ฅผ ์“ฐ๋˜ ์˜ค๋ธŒ์ ํŠธ๋Š” ๋‚จ์€ ๋ฒˆํ˜ธ๋กœ ์žฌ๋ฐฐ์ •", "data-testid": "filament-del" }, "โˆ’"))), Ie.map((e, t) => /* @__PURE__ */ n.createElement("div", { className: "filament-row", key: t }, /* @__PURE__ */ n.createElement("input", { type: "color", value: e, onChange: (r) => Zr(t, r.target.value), title: `T${t + 1} ํ•„๋ผ๋ฉ˜ํŠธ ์ƒ‰`, "data-testid": `filament-color-${t}` }), /* @__PURE__ */ n.createElement("span", { className: "fil-t" }, "T", t + 1), /* @__PURE__ */ n.createElement("span", { className: "fil-swatch", style: { background: e } }), /* @__PURE__ */ n.createElement("span", { className: "fil-hex muted" }, e)))), Ce.length > 0 && /* @__PURE__ */ n.createElement("section", { className: "side-card", "data-testid": "object-section" }, /* @__PURE__ */ n.createElement("div", { className: "sc-head" }, "๐Ÿ“ฆ ์˜ค๋ธŒ์ ํŠธ ", /* @__PURE__ */ n.createElement("span", { className: "sc-count" }, Ce.length)), /* @__PURE__ */ n.createElement("ul", { className: "obj-list2", "data-testid": "obj-list" }, Ce.map((e) => /* @__PURE__ */ n.createElement("li", { key: e.id, className: e.visible === !1 ? "obj-hidden" : "" }, /* @__PURE__ */ n.createElement("button", { className: "obj-eye", onClick: () => Ir(e.id), title: "์ด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ถœ๋ ฅ ๋Œ€์ƒ์—์„œ ์ œ์™ธ/ํฌํ•จ โ€” ์ œ์™ธํ•ด๋„ ์”ฌ์—๋Š” ๋‚จ์Œ", "data-testid": `eye-${e.id}` }, e.visible === !1 ? "๐Ÿšซ" : "๐Ÿ‘"), /* @__PURE__ */ n.createElement("span", { className: "obj-name", title: e.name }, e.name), /* @__PURE__ */ n.createElement("select", { className: "obj-ext", value: e.extruder ?? 1, onChange: (t) => Sr(e.id, +t.target.value), title: "์ด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ถœ๋ ฅํ•  ํ•„๋ผ๋ฉ˜ํŠธ(์ต์ŠคํŠธ๋ฃจ๋”) ๋ฒˆํ˜ธ", "data-testid": `ext-${e.id}` }, Ie.map((t, r) => /* @__PURE__ */ n.createElement("option", { key: r, value: r + 1 }, "T", r + 1))), /* @__PURE__ */ n.createElement("button", { className: "obj-split", onClick: () => {
1102
+ var t;
1103
+ (t = c.current) == null || t.selectObject(e.id), Vt();
1104
+ }, title: "๊ฐ์ฒด๋กœ ๋ถ„๋ฆฌ โ€” ์„œ๋กœ ๋–จ์–ด์ง„ ๋ถ€๋ถ„(์—ฐ๊ฒฐ ์„ฑ๋ถ„)๋งˆ๋‹ค ๋…๋ฆฝ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋‚˜๋ˆ”. ํŒŒํŠธ๋กœ ๋ถ„๋ฆฌ๋Š” ๋ฏธ๊ตฌํ˜„(ํŒŒํŠธ ๊ฐœ๋… ๋ถ€์žฌ)", "data-testid": `split-${e.id}` }, /* @__PURE__ */ n.createElement("img", { src: $n, alt: "๋ถ„๋ฆฌ" })), /* @__PURE__ */ n.createElement("button", { className: "obj-del", onClick: () => Bt(e.id), title: "์ด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์”ฌ์—์„œ ์ œ๊ฑฐ" }, "โœ•")))), /* @__PURE__ */ n.createElement("label", { className: "slice-support" }, /* @__PURE__ */ n.createElement("input", { type: "checkbox", checked: Pr, onChange: Or, title: "์˜ค๋ฒ„ํ–‰ ์•„๋ž˜์— ์ง€์ง€ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑ (์„ค์ • ํŒจ๋„์˜ enable_support ์™€ ๋™์ผ)", "data-testid": "support-toggle" }), " ์„œํฌํŠธ ์ƒ์„ฑ"), /* @__PURE__ */ n.createElement("label", { className: "slice-support" }, /* @__PURE__ */ n.createElement("input", { type: "checkbox", checked: an, onChange: (e) => or(e.target.checked), title: "๋ฉ€ํ‹ฐ๋จธํ‹ฐ๋ฆฌ์–ผ ํˆด์ฒด์ธ์ง€ ์‹œ ์›๋ณธ WipeTower ๋กœ ํผ์ง€๋Ÿ‰์„ ๊ณ„์‚ฐ (๋„๋ฉด ๋‹จ์ˆœ ์‚ฌ๊ฐ ๋ง)", "data-testid": "wipe-tower-real-toggle" }), " ์‹ค ์™€์ดํ”„ํƒ€์›Œ ", /* @__PURE__ */ n.createElement("span", { className: "muted" }, "(MM)"))), Xt && /* @__PURE__ */ n.createElement("div", { className: "slice-warn side-warn" }, "โš  ", Xt), dn && /* @__PURE__ */ n.createElement("div", { className: "slice-warn side-warn", "data-testid": "slice-notice" }, "โ„น ", dn), Kt && /* @__PURE__ */ n.createElement("div", { className: "slice-err side-warn", "data-testid": "slice-err" }, Kt), pn && /* @__PURE__ */ n.createElement("button", { className: "slice-btn", "data-testid": "downgrade-retry", onClick: Nr, title: "์ธํ•„์„ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ๋ฐ€๋„๋ฅผ ๋‚ฎ์ถฐ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€๋‹ด์„ ์ค„์ธ ๋’ค ์žฌ์‹œ๋„" }, "๊ฐ„์†Œํ™” ์žฌ์‹œ๋„(์ธํ•„ ๋‹จ์ˆœํ™”ยท์ ˆ์•ฝ ๋ชจ๋“œ)"), G === "preview" && En && /* @__PURE__ */ n.createElement("section", { className: "side-card" }, /* @__PURE__ */ n.createElement("div", { className: "sc-head" }, "๐ŸŽš ๋ฏธ๋ฆฌ๋ณด๊ธฐ"), En), /* @__PURE__ */ n.createElement("section", { className: "side-card process-card", "data-testid": "process-section" }, /* @__PURE__ */ n.createElement("div", { className: "sc-head" }, "โš™ ํ”„๋กœ์„ธ์Šค"), R)), /* @__PURE__ */ n.createElement("div", { className: "side-bottom" }, /* @__PURE__ */ n.createElement("div", { className: "slice-dd" }, /* @__PURE__ */ n.createElement("button", { className: "slice-btn", title: ne > 1 ? "์Šฌ๋ผ์ด์Šค ๋Œ€์ƒ ์„ ํƒ (Ctrl+R = ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ)" : "ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์Šฌ๋ผ์ด์Šค (Ctrl+R)", onClick: () => ne > 1 ? jt((e) => !e) : De("current"), disabled: Ce.length === 0 || Mt, "data-testid": "slice-btn" }, Mt ? `์Šฌ๋ผ์ด์‹ฑโ€ฆ ${Math.round(Hn * 100)}%` : ne > 1 ? "์Šฌ๋ผ์ด์Šค โ–พ" : "์Šฌ๋ผ์ด์Šค"), Yn && ne > 1 && /* @__PURE__ */ n.createElement("div", { className: "slice-menu", "data-testid": "slice-menu" }, /* @__PURE__ */ n.createElement("button", { onClick: () => De("current"), "data-testid": "slice-current", title: "์„ ํƒํ•œ ํ”Œ๋ ˆ์ดํŠธ๋งŒ ์Šฌ๋ผ์ด์Šค (Ctrl+R)" }, "ํ˜„์žฌ ํ”Œ๋ ˆ์ดํŠธ (P", Be + 1, ")"), /* @__PURE__ */ n.createElement("button", { onClick: () => De("all"), "data-testid": "slice-all", title: "๋ชจ๋“  ํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์ฐจ๋ก€๋กœ ์Šฌ๋ผ์ด์Šค โ€” ๊ฒฐ๊ณผ๋Š” ํƒญ ์ „ํ™˜์œผ๋กœ ์กฐํšŒ" }, "์ „์ฒด ํ”Œ๋ ˆ์ดํŠธ (", ne, ")"), tn > 0 && /* @__PURE__ */ n.createElement("button", { onClick: jr, "data-testid": "export-all", title: "์Šฌ๋ผ์ด์Šค๋œ ๋ชจ๋“  ํ”Œ๋ ˆ์ดํŠธ์˜ G-code๋ฅผ ๊ฐ๊ฐ ํŒŒ์ผ๋กœ ์ €์žฅ" }, "์ „์ฒด G-code ๋‚ด๋ณด๋‚ด๊ธฐ (", tn, ")"))), rn ? /* @__PURE__ */ n.createElement("a", { className: "export-btn", href: rn, download: `plate_${Be + 1}.gcode`, title: "ํ˜„์žฌ ๋ณด๊ณ  ์žˆ๋Š” ํ”Œ๋ ˆ์ดํŠธ์˜ G-code ํŒŒ์ผ ์ €์žฅ", "data-testid": "gcode-dl" }, "G-code ๋‚ด๋ณด๋‚ด๊ธฐ") : /* @__PURE__ */ n.createElement("button", { className: "export-btn", disabled: !0, title: "G-code ๋‚ด๋ณด๋‚ด๊ธฐ โ€” ์Šฌ๋ผ์ด์Šค ํ›„ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค" }, "G-code ๋‚ด๋ณด๋‚ด๊ธฐ"))))));
1105
+ }
1106
+ export {
1107
+ Ia as default
1108
+ };