gaesup-world 1.0.0 → 1.0.2
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.
- package/README.md +267 -263
- package/dist/GrassDriver-0VzddMiy.cjs +725 -0
- package/dist/GrassDriver-CgXNOTL2.js +9871 -0
- package/dist/PhysicsEntity-BpoArh5L.cjs +1 -0
- package/dist/PhysicsEntity-Cy3K_czk.js +3845 -0
- package/dist/api-B58jaq5T.cjs +1 -0
- package/dist/api-BRV101Zn.js +40 -0
- package/dist/assetStore-2bI2BPCn.js +232 -0
- package/dist/assetStore-BuE4mh1C.cjs +1 -0
- package/dist/assets.cjs +1 -0
- package/dist/assets.d.ts +1 -0
- package/dist/assets.js +14 -0
- package/dist/blueprints-editor.cjs +1 -1
- package/dist/blueprints-editor.js +14 -12
- package/dist/blueprints.cjs +1 -1
- package/dist/blueprints.js +2 -2
- package/dist/core/animation/hooks/useAnimationBridge.d.ts +1 -1
- package/dist/core/assets/api.d.ts +12 -0
- package/dist/core/assets/building.d.ts +5 -0
- package/dist/core/assets/components/AssetPreviewCanvas/index.d.ts +7 -0
- package/dist/core/assets/data/seedAssets.d.ts +2 -0
- package/dist/core/assets/index.d.ts +7 -0
- package/dist/core/assets/stores/assetStore.d.ts +20 -0
- package/dist/core/assets/types.d.ts +30 -0
- package/dist/core/building/catalog/index.d.ts +1 -0
- package/dist/core/building/catalog/objects.d.ts +12 -0
- package/dist/core/building/components/BlockSystem/index.d.ts +1 -1
- package/dist/core/building/components/BlockSystem/types.d.ts +1 -0
- package/dist/core/building/components/BuildingUI/index.d.ts +1 -0
- package/dist/core/building/components/TileSystem/index.d.ts +1 -1
- package/dist/core/building/components/TileSystem/types.d.ts +1 -0
- package/dist/core/building/components/WallSystem/index.d.ts +3 -1
- package/dist/core/building/components/WallSystem/types.d.ts +2 -0
- package/dist/core/building/components/mesh/fire/index.d.ts +1 -0
- package/dist/core/building/components/mesh/grass/assets.d.ts +11 -0
- package/dist/core/building/components/mesh/model/index.d.ts +11 -0
- package/dist/core/building/components/mesh/sand.d.ts +5 -1
- package/dist/core/building/components/mesh/snowfield.d.ts +5 -1
- package/dist/core/building/core/MaterialManager.d.ts +1 -0
- package/dist/core/building/hooks/useBuildingEditor.d.ts +4 -1
- package/dist/core/building/index.d.ts +1 -0
- package/dist/core/building/plugin.d.ts +2 -0
- package/dist/core/building/render/core.d.ts +1 -0
- package/dist/core/building/render/culling.d.ts +2 -1
- package/dist/core/building/render/draw.d.ts +1 -1
- package/dist/core/building/stores/buildingStore.d.ts +23 -1
- package/dist/core/building/stores/persistence.d.ts +19 -0
- package/dist/core/building/types/index.d.ts +23 -1
- package/dist/core/camera/bridge/BaseCameraSystem.d.ts +1 -0
- package/dist/core/camera/bridge/types.d.ts +9 -0
- package/dist/core/camera/controllers/BaseController.d.ts +1 -0
- package/dist/core/camera/controllers/FirstPersonController.d.ts +1 -0
- package/dist/core/camera/controllers/TopDownController.d.ts +5 -0
- package/dist/core/camera/core/CameraSystem.d.ts +2 -2
- package/dist/core/camera/core/constants.d.ts +4 -0
- package/dist/core/camera/core/types.d.ts +9 -0
- package/dist/core/camera/index.d.ts +1 -0
- package/dist/core/camera/plugin.d.ts +48 -0
- package/dist/core/camera/utils/camera.d.ts +4 -3
- package/dist/core/character/index.d.ts +2 -0
- package/dist/core/character/resolveParts.d.ts +11 -0
- package/dist/core/character/stores/characterStore.d.ts +3 -2
- package/dist/core/character/types.d.ts +8 -2
- package/dist/core/content/exporter.d.ts +17 -0
- package/dist/core/content/index.d.ts +4 -0
- package/dist/core/content/loader.d.ts +9 -0
- package/dist/core/content/types.d.ts +57 -0
- package/dist/core/editor/components/Editor/types.d.ts +2 -0
- package/dist/core/editor/components/EditorLayout/types.d.ts +12 -0
- package/dist/core/editor/components/panels/BuildingPanel/index.d.ts +3 -0
- package/dist/core/editor/components/panels/CharacterAssetPanel/index.d.ts +3 -0
- package/dist/core/editor/components/panels/GameplayEventPanel/index.d.ts +12 -0
- package/dist/core/editor/components/panels/StudioPanel/index.d.ts +7 -0
- package/dist/core/editor/components/panels/index.d.ts +3 -0
- package/dist/core/editor/index.d.ts +3 -1
- package/dist/core/editor/shell.d.ts +31 -0
- package/dist/core/gameplay/events/data/seedEvents.d.ts +2 -0
- package/dist/core/gameplay/events/engine.d.ts +17 -0
- package/dist/core/gameplay/events/index.d.ts +5 -0
- package/dist/core/gameplay/events/registry.d.ts +11 -0
- package/dist/core/gameplay/events/types.d.ts +138 -0
- package/dist/core/gameplay/index.d.ts +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/interactions/core/adapter.d.ts +9 -0
- package/dist/core/interactions/core/index.d.ts +1 -0
- package/dist/core/motions/core/system/PhysicsSystem.d.ts +1 -0
- package/dist/core/motions/entities/types.d.ts +2 -0
- package/dist/core/motions/hooks/usePhysicsBridge.d.ts +2 -0
- package/dist/core/motions/index.d.ts +1 -0
- package/dist/core/motions/plugin.d.ts +50 -0
- package/dist/core/networks/adapter/MockNetworkAdapter.d.ts +10 -0
- package/dist/core/networks/adapter/index.d.ts +3 -0
- package/dist/core/networks/adapter/types.d.ts +51 -0
- package/dist/core/networks/index.d.ts +1 -0
- package/dist/core/ops/index.d.ts +2 -0
- package/dist/core/ops/rbac.d.ts +4 -0
- package/dist/core/ops/types.d.ts +44 -0
- package/dist/core/platform/index.d.ts +2 -0
- package/dist/core/platform/snapshot.d.ts +35 -0
- package/dist/core/plugins/ExtensionRegistry.d.ts +1 -0
- package/dist/core/plugins/PluginRegistry.d.ts +1 -0
- package/dist/core/plugins/types.d.ts +4 -0
- package/dist/core/runtime/createGaesupRuntime.d.ts +2 -0
- package/dist/core/runtime/index.d.ts +2 -0
- package/dist/core/runtime/types.d.ts +24 -0
- package/dist/core/save/core/SaveSystem.d.ts +4 -2
- package/dist/core/save/types.d.ts +8 -0
- package/dist/core/world/components/WorldContainer/types.d.ts +11 -2
- package/dist/core/world/stores/persistenceSlice.d.ts +11 -6
- package/dist/defaultConfig-BR_x-243.cjs +1 -0
- package/dist/defaultConfig-CJNbZAKY.js +2126 -0
- package/dist/editor.cjs +1 -0
- package/dist/editor.d.ts +5 -0
- package/dist/editor.js +208 -0
- package/dist/eventsStore-Cipkf938.cjs +1 -0
- package/dist/eventsStore-DqmXNVEb.js +244 -0
- package/dist/gaesupStore-BKIA2dFc.js +1345 -0
- package/dist/gaesupStore-BoN_06sX.cjs +1 -0
- package/dist/gltf/props/LICENSE.txt +70 -0
- package/dist/index-B9921cuX.cjs +1 -0
- package/dist/index-BOmJcTCV.cjs +1 -0
- package/dist/index-BUONBdvH.cjs +1 -0
- package/dist/index-BjrBeKEM.js +705 -0
- package/dist/index-BlKxYuUK.js +328 -0
- package/dist/index-BmOFYbvk.js +69 -0
- package/dist/index-BnACo_cG.js +385 -0
- package/dist/index-BsAUS0-8.js +547 -0
- package/dist/index-C-ViQFGa.js +100 -0
- package/dist/index-CwttQ-l-.cjs +1 -0
- package/dist/index-DCa_lUwq.cjs +1 -0
- package/dist/index-SFK6DuIo.cjs +1 -0
- package/dist/index.cjs +2 -726
- package/dist/index.css +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +4183 -15725
- package/dist/network.cjs +1 -0
- package/dist/network.d.ts +1 -0
- package/dist/network.js +2067 -0
- package/dist/postprocessing.cjs +1 -1
- package/dist/postprocessing.js +24 -23
- package/dist/rbac-Bjx9pTbU.js +42 -0
- package/dist/rbac-N7h7zNl3.cjs +1 -0
- package/dist/{registerComponents-CYCKQxA1.js → registerComponents-BfIcN9qa.js} +2 -2
- package/dist/{registerComponents-DBQpZm-r.cjs → registerComponents-D3FUm9GA.cjs} +1 -1
- package/dist/runtime.cjs +1 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +1350 -0
- package/dist/seedEvents-Dmms48tb.cjs +1 -0
- package/dist/seedEvents-v6aCLQE7.js +723 -0
- package/dist/server-contracts.cjs +1 -0
- package/dist/server-contracts.d.ts +5 -0
- package/dist/server-contracts.js +28 -0
- package/dist/sfe-CRsG1dTW.js +10 -0
- package/dist/sfe-CpgzdMyB.cjs +1 -0
- package/dist/snapshot-DRqZrbCu.cjs +1 -0
- package/dist/snapshot-OExk53wq.js +75 -0
- package/dist/timeStore-BRw0mdde.js +96 -0
- package/dist/timeStore-CDN035t4.cjs +1 -0
- package/dist/types-Ck0ueY4N.js +40 -0
- package/dist/types-DgS5FYTs.cjs +1 -0
- package/dist/useSpawnFromBlueprint-1gMiylSa.cjs +1 -0
- package/dist/useSpawnFromBlueprint-fzl4TuHG.js +366 -0
- package/dist/weatherStore-1unmwIen.cjs +1 -0
- package/dist/weatherStore-CzG5N441.js +49 -0
- package/package.json +226 -175
- package/public/gltf/props/LICENSE.txt +70 -0
- package/public/gltf/props/bed.glb +0 -0
- package/public/gltf/props/chair.glb +0 -0
- package/public/gltf/props/crafting.glb +0 -0
- package/public/gltf/props/door.glb +0 -0
- package/public/gltf/props/fence.glb +0 -0
- package/public/gltf/props/lamp.glb +0 -0
- package/public/gltf/props/mailbox.glb +0 -0
- package/public/gltf/props/shop-stall.glb +0 -0
- package/public/gltf/props/storage.glb +0 -0
- package/public/gltf/props/table.glb +0 -0
- package/public/gltf/props/window.glb +0 -0
- package/dist/index-B-02XaUy.js +0 -3436
- package/dist/index-CZLbaLYT.cjs +0 -1
- package/dist/useSpawnFromBlueprint-Cxb3C2ch.js +0 -1665
- package/dist/useSpawnFromBlueprint-D5j-98Q8.cjs +0 -1
- package/dist/weatherStore-C2_1d8hn.cjs +0 -1
- package/dist/weatherStore-ZW3thKj6.js +0 -142
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
"use strict";const t=require("react/jsx-runtime"),u=require("react"),Be=require("reactflow");;/* empty css */const At=require("./seedEvents-Dmms48tb.cjs"),Ye=require("./assetStore-BuE4mh1C.cjs"),st=require("./index-CwttQ-l-.cjs"),re=require("./gaesupStore-BoN_06sX.cjs"),S=require("./PhysicsEntity-BpoArh5L.cjs"),pt=require("./index-DCa_lUwq.cjs"),rt=require("zustand"),dn=require("zustand/react/shallow"),Ge=require("@react-three/drei"),ae=require("@react-three/fiber"),Yo=require("three"),Ot=require("./sfe-CpgzdMyB.cjs"),ot=require("@react-three/rapier"),gs=require("three-stdlib");require("reflect-metadata");const oi=require("./weatherStore-1unmwIen.cjs"),bs=require("simplex-noise"),Xo=require("./authStore-CrDnYNnL.cjs"),qo=require("immer"),Ko=require("zustand/middleware/immer");function Jo(e){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const i=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(s,n,i.get?i:{enumerable:!0,get:()=>e[n]})}}return s.default=e,Object.freeze(s)}const b=Jo(Yo);function je({label:e,min:s,max:n,step:i,value:o,suffix:r,onChange:a}){return t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,fontSize:11,color:"#fff"},children:[t.jsx("span",{style:{width:60,flexShrink:0,color:"rgba(255,255,255,0.7)"},children:e}),t.jsx("input",{type:"range",min:s,max:n,step:i,value:o,onChange:l=>a(Number(l.target.value)),style:{flex:1,accentColor:"#0078d4"}}),t.jsxs("span",{style:{width:44,textAlign:"right",fontFamily:"monospace",fontSize:11},children:[typeof i=="number"&&i<1?o.toFixed(2):o,r??""]})]})}function Dn({label:e,checked:s,onChange:n}){return t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,fontSize:11,color:"#fff"},children:[t.jsx("input",{type:"checkbox",checked:s,onChange:i=>n(i.target.checked),style:{accentColor:"#0078d4"}}),t.jsx("span",{children:e})]})}function jt({title:e,children:s}){return t.jsxs("div",{style:{background:"rgba(0,0,0,0.2)",borderRadius:6,padding:"8px 10px",border:"1px solid rgba(255,255,255,0.08)",display:"flex",flexDirection:"column",gap:6},children:[t.jsx("div",{style:{fontSize:10,fontWeight:600,color:"rgba(255,255,255,0.5)",textTransform:"uppercase",letterSpacing:.5},children:e}),s]})}function Qo(){const e=re.useGaesupStore(a=>a.cameraOption),s=re.useGaesupStore(a=>a.setCameraOption),n=re.useGaesupStore(a=>a.mode),i=u.useCallback((a,l)=>{s({[a]:l})},[s]),o=u.useCallback((a,l)=>{s({smoothing:{...e.smoothing,[a]:l}})},[s,e.smoothing]),r=a=>e[a]??0;return t.jsxs("div",{style:{padding:10,display:"flex",flexDirection:"column",gap:10},children:[t.jsxs("div",{style:{fontSize:11,color:"rgba(255,255,255,0.5)",marginBottom:-4},children:["Mode: ",n.control??"thirdPerson"]}),t.jsxs(jt,{title:"Distance",children:[t.jsx(je,{label:"X",min:-50,max:50,step:1,value:r("xDistance"),onChange:a=>i("xDistance",a)}),t.jsx(je,{label:"Y",min:0,max:50,step:1,value:r("yDistance"),onChange:a=>i("yDistance",a)}),t.jsx(je,{label:"Z",min:-50,max:50,step:1,value:r("zDistance"),onChange:a=>i("zDistance",a)})]}),t.jsxs(jt,{title:"FOV / Smoothing",children:[t.jsx(je,{label:"FOV",min:30,max:120,step:5,value:e.fov??75,suffix:"deg",onChange:a=>i("fov",a)}),t.jsx(je,{label:"Pos",min:.01,max:1,step:.01,value:e.smoothing?.position??.1,onChange:a=>o("position",a)}),t.jsx(je,{label:"Rot",min:.01,max:1,step:.01,value:e.smoothing?.rotation??.1,onChange:a=>o("rotation",a)}),t.jsx(je,{label:"FOV Sm",min:.01,max:1,step:.01,value:e.smoothing?.fov??.2,onChange:a=>o("fov",a)})]}),t.jsxs(jt,{title:"Zoom",children:[t.jsx(Dn,{label:"Enable Zoom",checked:e.enableZoom??!1,onChange:a=>i("enableZoom",a)}),t.jsx(je,{label:"Speed",min:1e-4,max:.01,step:1e-4,value:e.zoomSpeed??.001,onChange:a=>i("zoomSpeed",a)}),t.jsx(je,{label:"Min",min:.1,max:2,step:.1,value:e.minZoom??.5,onChange:a=>i("minZoom",a)}),t.jsx(je,{label:"Max",min:1,max:5,step:.1,value:e.maxZoom??2,onChange:a=>i("maxZoom",a)})]}),t.jsxs(jt,{title:"Options",children:[t.jsx(Dn,{label:"Collision",checked:e.enableCollision??!1,onChange:a=>i("enableCollision",a)}),t.jsx(Dn,{label:"Focus Mode",checked:e.enableFocus??!1,onChange:a=>i("enableFocus",a)}),t.jsx(je,{label:"Focus Dist",min:1,max:50,step:1,value:e.focusDistance??15,onChange:a=>i("focusDistance",a)}),t.jsx(je,{label:"Max Dist",min:5,max:100,step:1,value:e.maxDistance??50,onChange:a=>i("maxDistance",a)})]}),t.jsxs(jt,{title:"Bounds",children:[t.jsx(je,{label:"Min Y",min:-10,max:50,step:1,value:e.bounds?.minY??2,onChange:a=>s({bounds:{...e.bounds,minY:a}})}),t.jsx(je,{label:"Max Y",min:5,max:100,step:1,value:e.bounds?.maxY??50,onChange:a=>s({bounds:{...e.bounds,maxY:a}})})]})]})}const er=[{value:"thirdPerson",label:"Third Person"},{value:"firstPerson",label:"First Person"},{value:"chase",label:"Chase"},{value:"topDown",label:"Top Down"},{value:"isometric",label:"Isometric"},{value:"sideScroll",label:"Side-Scroller"},{value:"fixed",label:"Fixed"}];function tr(){const{mode:e,setMode:s}=re.useGaesupStore(dn.useShallow(i=>({mode:i.mode,setMode:i.setMode}))),n=e?.control||"thirdPerson";return t.jsx("div",{className:"cc-panel",children:t.jsx("div",{className:"cc-list",children:er.map(i=>t.jsx("button",{className:`cc-button ${n===i.value?"active":""}`,onClick:()=>s({control:i.value}),children:i.label},i.value))})})}const nr=[{key:"mode",label:"Mode",enabled:!0,format:"text"},{key:"position",label:"Position",enabled:!0,format:"vector3",precision:2},{key:"distance",label:"Distance",enabled:!0,format:"vector3",precision:2},{key:"fov",label:"FOV",enabled:!0,format:"angle",precision:1},{key:"velocity",label:"Velocity",enabled:!1,format:"vector3",precision:2},{key:"rotation",label:"Rotation",enabled:!1,format:"vector3",precision:2},{key:"zoom",label:"Zoom",enabled:!1,format:"number",precision:2},{key:"activeController",label:"Controller",enabled:!0,format:"text"}];function Fn(e){if(typeof e!="object"||e===null)return!1;const s=e;return typeof s.x=="number"&&typeof s.y=="number"&&typeof s.z=="number"}function ri(){const e={frameCount:0,averageFrameTime:0,lastUpdateTime:Date.now(),mode:"unknown",activeController:"unknown",distance:null,fov:0,position:null,targetPosition:null,velocity:null,rotation:null},[s,n]=u.useState(e),i=re.useGaesupStore(p=>p.mode),o=re.useGaesupStore(p=>p.cameraOption),{activeState:r}=S.useStateSystem(),a=u.useRef(e),l=u.useCallback((p,m)=>p===m?!1:Fn(p)?Fn(m)?p.x!==m.x||p.y!==m.y||p.z!==m.z:!0:typeof p!="object"||p===null?!0:JSON.stringify(p)!==JSON.stringify(m),[]),c=u.useCallback(p=>Fn(p)?{x:p.x,y:p.y,z:p.z}:null,[]),d=u.useCallback(()=>{const p=o?.xDistance!==void 0&&o?.yDistance!==void 0&&o?.zDistance!==void 0?{x:o.xDistance,y:o.yDistance,z:o.zDistance}:null,m={...a.current,mode:i?.control??"unknown",activeController:o?.mode??i?.control??"unknown",distance:p,fov:o?.fov??0,position:c(r?.position),targetPosition:c(o?.target),velocity:c(r?.velocity),rotation:c(r?.euler),lastUpdateTime:Date.now(),...o?.zoom!==void 0?{zoom:o.zoom}:{}};Object.keys(m).some(y=>l(m[y],a.current[y]))&&(a.current=m,n(m))},[i,o,r,l,c]);u.useEffect(()=>{d();const p=setInterval(d,100);return()=>{clearInterval(p)}},[d]);const g=u.useCallback((p,m=2)=>p==null?"N/A":typeof p=="object"&&p.x!==void 0?`X:${p.x.toFixed(m)} Y:${p.y.toFixed(m)} Z:${p.z.toFixed(m)}`:typeof p=="number"?p.toFixed(m):p.toString(),[]);return t.jsx("div",{className:"cd-panel",children:t.jsx("div",{className:"cd-grid",children:nr.map(p=>t.jsxs("div",{className:"cd-item",children:[t.jsx("span",{className:"cd-label",children:p.label}),t.jsx("span",{className:"cd-value",children:g(s[p.key])})]},p.key))})})}const sr=[{id:"classic",name:"Classic",description:"A traditional third-person view.",icon:"camera",config:{mode:"thirdPerson",distance:{x:0,y:8,z:10},fov:75,smoothing:{position:.1,rotation:.1,fov:.1}}},{id:"cinematic",name:"Cinematic",description:"Smooth, movie-like camera work.",icon:"camera",config:{mode:"chase",distance:{x:2,y:7,z:8},fov:60,smoothing:{position:.05,rotation:.05,fov:.05}}},{id:"action",name:"Action",description:"Responsive camera for fast gameplay.",icon:"camera",config:{mode:"thirdPerson",distance:{x:0,y:6,z:6},fov:85,smoothing:{position:.2,rotation:.2,fov:.2}}},{id:"strategy",name:"Strategy",description:"Top-down view for an overview.",icon:"camera",config:{mode:"topDown",distance:{x:0,y:20,z:0},fov:45,smoothing:{position:.1,rotation:.1,fov:.1}}},{id:"retro",name:"Retro",description:"Classic side-scroller style.",icon:"camera",config:{mode:"sideScroll",distance:{x:15,y:0,z:0},fov:75,smoothing:{position:.15,rotation:.15,fov:.15}}}];function ir(e,s){return!e||!s?!1:e.x===s.x&&e.y===s.y&&e.z===s.z}function or(e){const s=e?.xDistance,n=e?.yDistance,i=e?.zDistance;if(!(s===void 0||n===void 0||i===void 0))return{x:s,y:n,z:i}}function ai(){const[e]=u.useState(sr),s=re.useGaesupStore(c=>c.setMode),n=re.useGaesupStore(c=>c.setCameraOption),i=re.useGaesupStore(c=>c.mode),o=re.useGaesupStore(c=>c.cameraOption),[r,a]=u.useState(null),l=u.useCallback(c=>{s({control:c.config.mode}),n({xDistance:c.config.distance.x,yDistance:c.config.distance.y,zDistance:c.config.distance.z,fov:c.config.fov,smoothing:c.config.smoothing||{position:.1,rotation:.1,fov:.1}})},[s,n,o]);return u.useEffect(()=>{const c=e.find(d=>d.config.mode===i?.control&&ir(d.config.distance,or(o)));a(c?c.id:null)},[i,o,e]),t.jsx("div",{className:"cp-panel",children:t.jsx("div",{className:"cp-grid",children:e.map(c=>t.jsxs("button",{className:`cp-item ${r===c.id?"active":""}`,onClick:()=>l(c),children:[t.jsx("div",{className:"cp-name",children:c.name}),t.jsx("div",{className:"cp-description",children:c.description})]},c.id))})})}function li(){const[e,s]=u.useState("Settings"),n=()=>{switch(e){case"Settings":return t.jsx(Qo,{});case"Controller":return t.jsx(tr,{});case"Presets":return t.jsx(ai,{});case"Debug":return t.jsx(ri,{});default:return null}};return t.jsxs("div",{className:"tabbed-panel",children:[t.jsxs("div",{className:"panel-tabs",children:[t.jsx("button",{className:`panel-tab ${e==="Settings"?"active":""}`,onClick:()=>s("Settings"),children:"Settings"}),t.jsx("button",{className:`panel-tab ${e==="Controller"?"active":""}`,onClick:()=>s("Controller"),children:"Controller"}),t.jsx("button",{className:`panel-tab ${e==="Presets"?"active":""}`,onClick:()=>s("Presets"),children:"Presets"}),t.jsx("button",{className:`panel-tab ${e==="Debug"?"active":""}`,onClick:()=>s("Debug"),children:"Debug"})]}),t.jsx("div",{className:"panel-tab-content",children:n()})]})}const rr=[{value:"idle",label:"Idle"},{value:"walk",label:"Walk"},{value:"run",label:"Run"},{value:"jump",label:"Jump"},{value:"fall",label:"Fall"},{value:"dance",label:"Dance"},{value:"wave",label:"Wave"}];function ar(){const{playAnimation:e,currentType:s,currentAnimation:n}=S.useAnimationBridge(),i=o=>{e(s,o)};return t.jsx("div",{className:"ac-panel",children:t.jsx("div",{className:"ac-grid",children:rr.map(o=>t.jsx("button",{className:`ac-button ${o.value===n?"active":""}`,onClick:()=>i(o.value),title:o.label,children:o.label},o.value))})})}const lr=[{key:"currentAnimation",label:"현재 애니메이션",format:"text",enabled:!0},{key:"animationType",label:"애니메이션 타입",format:"text",enabled:!0},{key:"isPlaying",label:"재생 상태",format:"text",enabled:!0},{key:"weight",label:"가중치",format:"number",enabled:!0},{key:"speed",label:"속도",format:"number",enabled:!0},{key:"blendDuration",label:"블렌드 시간",format:"number",enabled:!1},{key:"activeActions",label:"활성 액션",format:"number",enabled:!0},{key:"availableAnimations",label:"사용 가능 애니메이션",format:"array",enabled:!1},{key:"frameCount",label:"프레임 카운트",format:"number",enabled:!1},{key:"averageFrameTime",label:"평균 프레임 시간",format:"number",enabled:!1}];function ci(){const{bridge:e,currentType:s}=S.useAnimationBridge(),[n,i]=u.useState({frameCount:0,averageFrameTime:0,lastUpdateTime:Date.now(),currentAnimation:"idle",animationType:"character",availableAnimations:[],isPlaying:!1,weight:1,speed:1,blendDuration:.3,activeActions:0});u.useEffect(()=>{if(!e)return;const a=()=>{const c=e.snapshot(s);if(!c)return;const d=e.getMetrics(s);i(g=>({...g,currentAnimation:c.currentAnimation,animationType:s,availableAnimations:c.availableAnimations,isPlaying:c.isPlaying,weight:c.weight,speed:c.speed,activeActions:c.metrics.activeAnimations,frameCount:d?.totalActions||0,averageFrameTime:d?.mixerTime||0,lastUpdateTime:Date.now()}))};return a(),e.subscribe((c,d)=>{d===s&&a()})},[e,s]);const o=(a,l,c=2)=>{if(a==null)return"N/A";switch(l){case"array":return Array.isArray(a)?`${a.length} animations`:String(a);case"boolean":return a?"Yes":"No";case"number":return typeof a=="number"?a.toFixed(c):String(a);default:return String(a)}},r=a=>{if(a in n)return n[a]};return t.jsx("div",{className:"ad-panel",children:t.jsx("div",{className:"ad-content",children:lr.filter(a=>a.enabled).map(a=>t.jsxs("div",{className:"ad-item",children:[t.jsx("span",{className:"ad-label",children:a.label}),t.jsx("span",{className:"ad-value",children:o(r(a.key),a.format)})]},a.key))})})}const cr=()=>t.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:t.jsx("path",{d:"M8 5v14l11-7z"})}),ur=()=>t.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:t.jsx("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"})}),dr=()=>t.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:t.jsx("path",{d:"M6 6h2v12H6zm3.5 6l8.5 6V6z"})}),pr=()=>t.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"currentColor",children:t.jsx("path",{d:"M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"})});function mr(){const{bridge:e,playAnimation:s,stopAnimation:n,currentType:i,currentAnimation:o}=S.useAnimationBridge(),[r,a]=u.useState(!1),[l,c]=u.useState([]),[d,g]=u.useState(30);u.useEffect(()=>{if(!e)return;const m=()=>{const y=e.snapshot(i);y&&(a(y.isPlaying),c(y.availableAnimations))};return m(),e.subscribe((y,M)=>{M===i&&m()})},[e,i]);const p=()=>{r?n(i):s(i,o)};return t.jsxs("div",{className:"ap-panel",children:[t.jsxs("div",{className:"ap-controls",children:[t.jsx("select",{className:"ap-select",value:o,onChange:m=>s(i,m.target.value),children:l.map(m=>t.jsx("option",{value:m,children:m},m))}),t.jsxs("div",{className:"ap-buttons",children:[t.jsx("button",{className:"ap-btn","aria-label":"previous animation",children:t.jsx(dr,{})}),t.jsx("button",{className:"ap-btn-primary",onClick:p,"aria-label":r?"pause":"play",children:r?t.jsx(ur,{}):t.jsx(cr,{})}),t.jsx("button",{className:"ap-btn","aria-label":"next animation",children:t.jsx(pr,{})})]})]}),t.jsxs("div",{className:"ap-timeline",children:[t.jsx("span",{className:"ap-time",children:"0:00"}),t.jsx("input",{type:"range",className:"ap-slider",min:"0",max:"100",value:d,onChange:m=>g(Number(m.target.value))}),t.jsx("span",{className:"ap-time",children:"1:30"})]})]})}function ui(){const[e,s]=u.useState("Player"),n=()=>{switch(e){case"Player":return t.jsx("div",{className:"panel-content-wrapper",children:t.jsx(mr,{})});case"Controller":return t.jsx("div",{className:"panel-content-wrapper",children:t.jsx(ar,{})});case"Debug":return t.jsx("div",{className:"panel-content-wrapper",children:t.jsx(ci,{})});default:return null}};return t.jsxs("div",{className:"tabbed-panel",children:[t.jsxs("div",{className:"panel-tabs",children:[t.jsx("button",{className:`panel-tab ${e==="Player"?"active":""}`,onClick:()=>s("Player"),children:"Player"}),t.jsx("button",{className:`panel-tab ${e==="Controller"?"active":""}`,onClick:()=>s("Controller"),children:"Controller"}),t.jsx("button",{className:`panel-tab ${e==="Debug"?"active":""}`,onClick:()=>s("Debug"),children:"Debug"})]}),t.jsx("div",{className:"panel-tab-content",children:n()})]})}const Ls=[{id:"slow",name:"Slow",maxSpeed:5,acceleration:8},{id:"normal",name:"Normal",maxSpeed:10,acceleration:15},{id:"fast",name:"Fast",maxSpeed:20,acceleration:25},{id:"sprint",name:"Sprint",maxSpeed:35,acceleration:40}],Gs=[{id:"eco",name:"Eco",maxSpeed:15,acceleration:10},{id:"comfort",name:"Comfort",maxSpeed:25,acceleration:20},{id:"sport",name:"Sport",maxSpeed:40,acceleration:35},{id:"turbo",name:"Turbo",maxSpeed:60,acceleration:50}];function fr(e,s){const n=e??"bottom-left",i={position:"fixed",zIndex:s??1e4};return n.includes("top")&&(i.top=12),n.includes("bottom")&&(i.bottom=12),n.includes("left")&&(i.left=12),n.includes("right")&&(i.right=12),i}function di(e){const s=fr(e.position,e.zIndex),n=re.useGaesupStore(m=>m.mode),i=re.useGaesupStore(m=>m.setMode),o=re.useGaesupStore(m=>m.setPhysics),r=n?.type==="vehicle"?"vehicle":"character",a=r==="vehicle"?Gs:Ls,[l,c]=u.useState(r==="vehicle"?"comfort":"normal"),d=u.useCallback((m,f)=>{const M=(m==="vehicle"?Gs:Ls).find(_=>_.id===f);if(M){if(m==="vehicle"){o({maxSpeed:M.maxSpeed,accelRatio:M.acceleration});return}o({walkSpeed:Math.max(1,M.maxSpeed*.5),runSpeed:M.maxSpeed,accelRatio:M.acceleration})}},[o]),g=u.useCallback(m=>{c(m),d(r,m),e.onPresetChange?.(m)},[d,r,e]),p=u.useCallback(m=>{const f=m.target.value;i({type:f});const y=f==="vehicle"?"comfort":"normal";c(y),d(f,y),e.onPresetChange?.(y)},[d,i,e]);return t.jsxs("div",{className:`mc-panel ${e.compact?"compact":""}`,style:s,children:[t.jsxs("div",{className:"mc-setting-row",children:[t.jsx("label",{htmlFor:"motion-type-select",className:"mc-label",children:"Motion Type"}),t.jsxs("select",{id:"motion-type-select",className:"mc-select",value:r,onChange:p,children:[t.jsx("option",{value:"character",children:"Character"}),t.jsx("option",{value:"vehicle",children:"Vehicle"})]})]}),t.jsxs("div",{className:"mc-setting-row",children:[t.jsx("label",{className:"mc-label",children:"Presets"}),t.jsx("div",{className:"mc-presets-grid",children:a.map(m=>t.jsx("button",{className:`mc-preset-btn ${m.id===l?"active":""}`,onClick:()=>g(m.id),title:`Max Speed: ${m.maxSpeed}, Accel: ${m.acceleration}`,children:m.name},m.id))})]})]})}const zs=[{key:"motionType",label:"Motion Type",type:"text"},{key:"position",label:"Position",type:"vector3"},{key:"velocity",label:"Velocity",type:"vector3"},{key:"speed",label:"Speed",type:"number"},{key:"direction",label:"Direction",type:"vector3"},{key:"isGrounded",label:"Grounded",type:"text"},{key:"isMoving",label:"Moving",type:"text"},{key:"acceleration",label:"Acceleration",type:"number"},{key:"jumpForce",label:"Jump Force",type:"number"},{key:"maxSpeed",label:"Max Speed",type:"number"},{key:"totalDistance",label:"Total Distance",type:"number"},{key:"gameState",label:"Game State",type:"text"}];function hr(e,s){const n=e??"top-right",i={position:"fixed",zIndex:s??1e4};return n.includes("top")&&(i.top=12),n.includes("bottom")&&(i.bottom=12),n.includes("left")&&(i.left=12),n.includes("right")&&(i.right=12),i}function pi(e){const s=e.embedded?{}:hr(e.position,e.zIndex),n=re.useGaesupStore(g=>g.mode),i=re.useGaesupStore(g=>g.physics),{activeState:o,gameStates:r}=S.useStateSystem(),a=e.precision??2,l=e.customFields?[...zs,...e.customFields]:zs,c=(g,p,m=2)=>{if(p==null)return"N/A";switch(g.type){case"vector3":if(Array.isArray(p)&&p.length===3){const[f,y,M]=p;return`X:${f.toFixed(m)} Y:${y.toFixed(m)} Z:${M.toFixed(m)}`}if(typeof p=="object"&&p!==null&&"x"in p&&"y"in p&&"z"in p){const f=p;return`X:${f.x.toFixed(m)} Y:${f.y.toFixed(m)} Z:${f.z.toFixed(m)}`}return String(p);case"number":return typeof p=="number"?p.toFixed(m):String(p);default:return String(p)}},d=g=>{if(g.value!==void 0)return g.value;switch(g.key){case"motionType":return n?.type??"character";case"position":return o?.position?{x:o.position.x,y:o.position.y,z:o.position.z}:{x:0,y:0,z:0};case"velocity":return o?.velocity?{x:o.velocity.x,y:o.velocity.y,z:o.velocity.z}:{x:0,y:0,z:0};case"speed":return o?.velocity?o.velocity.length():0;case"direction":return o?.direction?{x:o.direction.x,y:o.direction.y,z:o.direction.z}:{x:0,y:0,z:0};case"isGrounded":return r?.isOnTheGround?"Yes":"No";case"isMoving":return r?.isMoving?"Yes":"No";case"acceleration":return i?.accelRatio??0;case"jumpForce":return i?.jumpSpeed??0;case"maxSpeed":return n?.type==="character"?i?.runSpeed??0:i?.maxSpeed??0;case"totalDistance":return 0;case"gameState":return r?.isRiding?"riding":r?.isOnTheGround?"ground":"air";default:return null}};return t.jsx("div",{className:`md-panel ${e.compact?"compact":""} ${e.theme?`theme-${e.theme}`:""}`,style:s,children:t.jsx("div",{className:"md-content",children:l.map(g=>t.jsxs("div",{className:"md-item",children:[t.jsx("span",{className:"md-label",children:g.label}),t.jsx("span",{className:"md-value",children:c(g,d(g),a)})]},g.key))})})}function mi(){const[e,s]=u.useState("Controller"),n=()=>{switch(e){case"Controller":return t.jsx("div",{className:"panel-content-wrapper",children:t.jsx(di,{})});case"Debug":return t.jsx("div",{className:"panel-content-wrapper",children:t.jsx(pi,{embedded:!0})});default:return null}};return t.jsxs("div",{className:"tabbed-panel",children:[t.jsxs("div",{className:"panel-tabs",children:[t.jsx("button",{className:`panel-tab ${e==="Controller"?"active":""}`,onClick:()=>s("Controller"),children:"Controller"}),t.jsx("button",{className:`panel-tab ${e==="Debug"?"active":""}`,onClick:()=>s("Debug"),children:"Debug"})]}),t.jsx("div",{className:"panel-tab-content",children:n()})]})}const Yt=60,Xt=({data:e,color:s,max:n,warn:i})=>{const r=e.filter(c=>isFinite(c));if(r.length<2)return null;const a=Math.max(1,n),l=r.map((c,d)=>{const g=d/(r.length-1)*100,p=40-c/a*40;return`${d===0?"M":"L"}${g.toFixed(2)},${p.toFixed(2)}`}).join(" ");return t.jsx("div",{className:"perf-chart",children:t.jsxs("svg",{width:"100%",height:40,preserveAspectRatio:"none",viewBox:"0 0 100 40",children:[i!==void 0&&t.jsx("line",{x1:"0",y1:40-i/a*40,x2:"100",y2:40-i/a*40,stroke:"#facc15",strokeWidth:"0.5",strokeDasharray:"3,3",opacity:.5}),t.jsx("path",{d:l,fill:"none",stroke:s,strokeWidth:"2",strokeLinejoin:"round",strokeLinecap:"round"})]})})},Ln=({value:e,max:s,color:n,label:i})=>{const o=s>0?Math.min(100,e/s*100):0;return t.jsxs("div",{style:{marginBottom:4},children:[t.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:10,marginBottom:2},children:[t.jsx("span",{className:"perf-label",children:i}),t.jsx("span",{children:e.toFixed(1)})]}),t.jsx("div",{style:{height:4,background:"#1e293b",borderRadius:2,overflow:"hidden"},children:t.jsx("div",{style:{width:`${o}%`,height:"100%",background:n,borderRadius:2,transition:"width 0.3s"}})})]})};function fi(){const e=re.useGaesupStore(dn.useShallow(P=>P.performance)),[s,n]=u.useState({current:0,min:1/0,max:0,avg:0,p1Low:0,history:Array(Yt).fill(0)}),[i,o]=u.useState({used:0,limit:0,history:Array(Yt).fill(0)}),[r,a]=u.useState(0),[l,c]=u.useState(Array(Yt).fill(0)),[d,g]=u.useState(Array(Yt).fill(0)),p=u.useRef(0),m=u.useRef(0),f=u.useRef(0),y=u.useRef([]),M=u.useRef(0),_=u.useRef(null),j=u.useRef(0),A=u.useRef(0),w=u.useRef(0),x=u.useCallback(P=>{if(P.length<5)return 0;const G=[...P].filter(h=>h>0).sort((h,k)=>h-k),z=Math.max(1,Math.floor(G.length*.01));let L=0;for(let h=0;h<z;h++)L+=G[h]??0;return L/z},[]);u.useEffect(()=>{const P=window.performance.now();p.current=P,m.current=P,M.current=P;const G=z=>{const L=z-m.current;if(m.current=z,y.current.push(L),y.current.length>300&&y.current.shift(),j.current+=L,A.current++,A.current>=10){const h=j.current/A.current;a(h),g(k=>[...k.slice(1),h]),j.current=0,A.current=0}if(f.current++,z-p.current>=500){const h=f.current*1e3/(z-p.current),k=y.current.map(Z=>Z>0?1e3/Z:0),U=z-M.current>3e3;n(Z=>{const Y=[...Z.history.slice(1),h],$=U?Math.min(Z.min===1/0?h:Z.min,h):1/0,J=U?Math.max(Z.max,h):0,ee=U?Y.filter(Q=>Q>0):[],te=ee.length>0?ee.reduce((Q,se)=>Q+se,0)/ee.length:h,X=U?x(k):h;return{current:h,min:$,max:J,avg:te,p1Low:X,history:Y}});const W=window.performance.memory;W&&o(Z=>{const Y=Math.round(W.usedJSHeapSize/1048576),$=Math.round(W.jsHeapSizeLimit/1048576);return{used:Y,limit:$,history:[...Z.history.slice(1),Y]}}),p.current=z,f.current=0}_.current=requestAnimationFrame(G)};return _.current=requestAnimationFrame(G),()=>{_.current&&cancelAnimationFrame(_.current)}},[x]),u.useEffect(()=>{const P=e.render.calls;P!==w.current&&(w.current=P,c(G=>[...G.slice(1),P]))},[e.render.calls]);const T=P=>P>=55?"#4ade80":P>=30?"#facc15":"#f87171",C=P=>P<=16.7?"#4ade80":P<=33.3?"#facc15":"#f87171",B=P=>P<=100?"#4ade80":P<=300?"#facc15":"#f87171",I=(P,G)=>{const z=G>0?P/G*100:0;return z<60?"#4ade80":z<80?"#facc15":"#f87171"},F=e.render.triangles,R=e.render.calls,D=e.engine.geometries,E=e.engine.textures;return t.jsxs("div",{className:"perf-panel",children:[t.jsxs("div",{className:"perf-stat-group",children:[t.jsxs("div",{className:"perf-header",children:[t.jsx("h4",{className:"perf-title",children:"Frame Rate"}),t.jsxs("span",{className:"perf-current",style:{color:T(s.current)},children:[s.current.toFixed(0)," FPS"]})]}),t.jsxs("div",{className:"perf-details-grid",children:[t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Avg"}),s.avg.toFixed(1)]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Min"}),isFinite(s.min)?s.min.toFixed(1):"..."]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Max"}),s.max.toFixed(1)]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"1% Low"}),t.jsx("span",{style:{color:T(s.p1Low)},children:s.p1Low.toFixed(1)})]})]}),t.jsx(Xt,{data:s.history,color:T(s.current),max:90,warn:60})]}),t.jsxs("div",{className:"perf-stat-group",children:[t.jsxs("div",{className:"perf-header",children:[t.jsx("h4",{className:"perf-title",children:"Frame Time"}),t.jsxs("span",{className:"perf-current",style:{color:C(r)},children:[r.toFixed(2)," ms"]})]}),t.jsx(Ln,{value:r,max:33.3,color:C(r),label:"Budget (16.7ms)"}),t.jsx(Xt,{data:d,color:C(r),max:33.3,warn:16.7})]}),t.jsxs("div",{className:"perf-stat-group",children:[t.jsxs("div",{className:"perf-header",children:[t.jsx("h4",{className:"perf-title",children:"GPU Pipeline"}),t.jsxs("span",{className:"perf-current",style:{color:B(R)},children:[R," calls"]})]}),t.jsxs("div",{className:"perf-details-grid",children:[t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Triangles"}),F>=1e6?(F/1e6).toFixed(2)+"M":F>=1e3?(F/1e3).toFixed(1)+"K":F]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Draw Calls"}),t.jsx("span",{style:{color:B(R)},children:R})]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Tri/Call"}),R>0?Math.round(F/R):0]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Points"}),e.render.points]})]}),t.jsx(Xt,{data:l,color:B(R),max:Math.max(200,...l)})]}),t.jsxs("div",{className:"perf-stat-group",children:[t.jsx("div",{className:"perf-header",children:t.jsx("h4",{className:"perf-title",children:"Resources"})}),t.jsxs("div",{className:"perf-details-grid",children:[t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Geometries"}),D]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Textures"}),E]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Programs"}),e.engine.programs]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Lines"}),e.render.lines]})]}),t.jsx(Ln,{value:D,max:200,color:D>150?"#f87171":"#4ade80",label:"Geometry Budget"}),t.jsx(Ln,{value:E,max:100,color:E>80?"#f87171":"#4ade80",label:"Texture Budget"})]}),t.jsxs("div",{className:"perf-stat-group",children:[t.jsxs("div",{className:"perf-header",children:[t.jsx("h4",{className:"perf-title",children:"Memory"}),t.jsxs("span",{className:"perf-current",style:{color:I(i.used,i.limit)},children:[i.used," MB"]})]}),t.jsxs("div",{className:"perf-details-grid",children:[t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Limit"}),i.limit," MB"]}),t.jsxs("div",{children:[t.jsx("span",{className:"perf-label",children:"Usage"}),i.limit>0?(i.used/i.limit*100).toFixed(0):0,"%"]})]}),t.jsx(Xt,{data:i.history,color:I(i.used,i.limit),max:i.limit||1})]})]})}const hi=()=>{const e=re.useGaesupStore(o=>o.mode),s=re.useGaesupStore(o=>o.setMode),n=o=>{s({type:o,controller:"keyboard",control:o==="airplane"||o==="vehicle"?"chase":"thirdPerson"})},i=[{type:"character",label:"Character",description:"Walk around as character"},{type:"vehicle",label:"Vehicle",description:"Drive a ground vehicle"},{type:"airplane",label:"Airplane",description:"Fly an airplane"}];return t.jsxs("div",{className:"vehicle-panel",children:[t.jsx("div",{className:"vehicle-panel__modes",children:i.map(o=>t.jsxs("button",{className:`vehicle-panel__mode-button ${e.type===o.type?"vehicle-panel__mode-button--active":""}`,onClick:()=>n(o.type),children:[t.jsx("span",{className:"vehicle-panel__mode-label",children:o.label}),t.jsx("span",{className:"vehicle-panel__mode-description",children:o.description})]},o.type))}),t.jsxs("div",{className:"vehicle-panel__info",children:[t.jsxs("div",{className:"vehicle-panel__info-item",children:[t.jsx("span",{className:"vehicle-panel__info-label",children:"Current Mode:"}),t.jsx("span",{className:"vehicle-panel__info-value",children:e.type})]}),t.jsxs("div",{className:"vehicle-panel__info-item",children:[t.jsx("span",{className:"vehicle-panel__info-label",children:"Controls:"}),t.jsx("span",{className:"vehicle-panel__info-value",children:e.type==="airplane"?"WASD + Space/Shift":"WASD + Space"})]})]})]})},it=[{id:"door-basic",label:"Door",category:"structure",fallbackKind:"door",defaultScale:1,defaultColor:"#8b5a2b",modelUrl:"gltf/props/door.glb"},{id:"window-basic",label:"Window",category:"structure",fallbackKind:"window",defaultScale:1,defaultColor:"#9fd3ff",modelUrl:"gltf/props/window.glb"},{id:"fence-basic",label:"Fence",category:"structure",fallbackKind:"fence",defaultScale:1,defaultColor:"#8f6a3d",modelUrl:"gltf/props/fence.glb"},{id:"lamp-basic",label:"Lamp",category:"utility",fallbackKind:"lamp",defaultScale:1,defaultColor:"#ffd166",modelUrl:"gltf/props/lamp.glb"},{id:"chair-basic",label:"Chair",category:"furniture",fallbackKind:"chair",defaultScale:1,defaultColor:"#a6784f",modelUrl:"gltf/props/chair.glb"},{id:"table-basic",label:"Table",category:"furniture",fallbackKind:"table",defaultScale:1,defaultColor:"#9b6b43",modelUrl:"gltf/props/table.glb"},{id:"bed-basic",label:"Bed",category:"furniture",fallbackKind:"bed",defaultScale:1,defaultColor:"#7aa2ff",modelUrl:"gltf/props/bed.glb"},{id:"storage-basic",label:"Storage",category:"furniture",fallbackKind:"storage",defaultScale:1,defaultColor:"#7c5c3e",modelUrl:"gltf/props/storage.glb"},{id:"mailbox-basic",label:"Mailbox",category:"utility",fallbackKind:"mailbox",defaultScale:1,defaultColor:"#d04f45",modelUrl:"gltf/props/mailbox.glb"},{id:"crafting-basic",label:"Crafting Station",category:"utility",fallbackKind:"crafting",defaultScale:1,defaultColor:"#b68553",modelUrl:"gltf/props/crafting.glb"},{id:"shop-stall-basic",label:"Shop Stall",category:"shop",fallbackKind:"shop",defaultScale:1,defaultColor:"#d88f45",modelUrl:"gltf/props/shop-stall.glb"}];function Dt(e){return it.find(s=>s.id===e)}const gr=Object.entries(S.FLAG_STYLE_META),br=[{value:"#00ff88",label:"초록"},{value:"#00aaff",label:"파랑"},{value:"#f59e0b",label:"앰버"},{value:"#ffffff",label:"흰색"},{value:"#ffdd00",label:"노랑"}],xr=e=>e.kind==="material"||e.kind==="wall"||e.kind==="tile";function Gn(e){return`${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function Os(e,s,n){const{mapTextureUrl:i,textureUrl:o,materialParams:r,...a}=n??{};return{...a,id:e,color:s,material:"STANDARD",materialParams:{...r??{},color:s}}}const vr=()=>{const e=S.useBuildingStore(v=>v.editMode),s=S.useBuildingStore(v=>v.setEditMode),n=S.useBuildingStore(v=>v.selectedWallId),i=S.useBuildingStore(v=>v.selectedTileId),o=S.useBuildingStore(v=>v.selectedBlockId),r=S.useBuildingStore(v=>v.selectedWallGroupId),a=S.useBuildingStore(v=>v.currentTileMultiplier),l=S.useBuildingStore(v=>v.setTileMultiplier),c=S.useBuildingStore(v=>v.currentTileHeight),d=S.useBuildingStore(v=>v.setTileHeight),g=S.useBuildingStore(v=>v.currentTileShape),p=S.useBuildingStore(v=>v.setTileShape),m=S.useBuildingStore(v=>v.currentTileRotation),f=S.useBuildingStore(v=>v.setTileRotation),y=S.useBuildingStore(v=>v.currentTileMaterialId),M=S.useBuildingStore(v=>v.setCurrentTileMaterialId),_=S.useBuildingStore(v=>v.currentWallRotation),j=S.useBuildingStore(v=>v.setWallRotation),A=S.useBuildingStore(v=>v.selectedTileObjectType),w=S.useBuildingStore(v=>v.setSelectedTileObjectType),x=S.useBuildingStore(v=>v.currentTerrainColor),T=S.useBuildingStore(v=>v.currentTerrainAccentColor),C=S.useBuildingStore(v=>v.setTerrainColors),B=S.useBuildingStore(v=>v.selectedPlacedObjectType),I=S.useBuildingStore(v=>v.setSelectedPlacedObjectType),F=S.useBuildingStore(v=>v.selectedModelObjectId),R=S.useBuildingStore(v=>v.setSelectedModelObjectId),D=S.useBuildingStore(v=>v.currentModelUrl),E=S.useBuildingStore(v=>v.setModelUrl),P=S.useBuildingStore(v=>v.currentModelScale),G=S.useBuildingStore(v=>v.setModelScale),z=S.useBuildingStore(v=>v.currentModelColor),L=S.useBuildingStore(v=>v.setModelColor),h=S.useBuildingStore(v=>v.snapToGrid),k=S.useBuildingStore(v=>v.setSnapToGrid),U=S.useBuildingStore(v=>v.currentFlagWidth),W=S.useBuildingStore(v=>v.currentFlagHeight),Z=S.useBuildingStore(v=>v.currentFlagImageUrl),Y=S.useBuildingStore(v=>v.setFlagWidth),$=S.useBuildingStore(v=>v.setFlagHeight),J=S.useBuildingStore(v=>v.setFlagImageUrl),ee=S.useBuildingStore(v=>v.currentFlagStyle),te=S.useBuildingStore(v=>v.setFlagStyle),X=S.useBuildingStore(v=>v.currentFireIntensity),Q=S.useBuildingStore(v=>v.currentFireWidth),se=S.useBuildingStore(v=>v.currentFireHeight),q=S.useBuildingStore(v=>v.currentFireColor),ie=S.useBuildingStore(v=>v.setFireIntensity),ue=S.useBuildingStore(v=>v.setFireWidth),O=S.useBuildingStore(v=>v.setFireHeight),me=S.useBuildingStore(v=>v.setFireColor),fe=S.useBuildingStore(v=>v.currentObjectRotation),xe=S.useBuildingStore(v=>v.setObjectRotation),Me=S.useBuildingStore(v=>v.selectedTileGroupId),Ie=S.useBuildingStore(v=>v.tileGroups),le=S.useBuildingStore(v=>v.wallGroups),Qe=S.useBuildingStore(v=>v.blocks),Ae=S.useBuildingStore(v=>v.meshes),bt=S.useBuildingStore(v=>v.addMesh),Oe=S.useBuildingStore(v=>v.updateMesh),at=S.useBuildingStore(v=>v.updateWall),Ce=S.useBuildingStore(v=>v.updateTile),He=S.useBuildingStore(v=>v.setCurrentWallMaterialId),Te=S.useBuildingStore(v=>v.removeWall),lt=S.useBuildingStore(v=>v.removeTile),In=S.useBuildingStore(v=>v.removeBlock),An=S.useBuildingStore(v=>v.currentBillboardText),Bn=S.useBuildingStore(v=>v.currentBillboardImageUrl),En=S.useBuildingStore(v=>v.currentBillboardColor),kn=S.useBuildingStore(v=>v.setBillboardText),Wt=S.useBuildingStore(v=>v.setBillboardImageUrl),xt=S.useBuildingStore(v=>v.setBillboardColor),et=S.useBuildingStore(v=>v.currentObjectPrimaryColor),Ht=S.useBuildingStore(v=>v.currentObjectSecondaryColor),Rn=S.useBuildingStore(v=>v.setObjectPrimaryColor),$t=S.useBuildingStore(v=>v.setObjectSecondaryColor),N=S.useBuildingStore(v=>v.showSnow),H=S.useBuildingStore(v=>v.setShowSnow),de=Ye.useAssetStore(v=>v.ids),ve=Ye.useAssetStore(v=>v.records),vt=u.useMemo(()=>de.map(v=>ve[v]).filter(v=>!!v).filter(xr),[de,ve]),Zt=[{type:"none",label:"없음",description:"건축 편집을 끕니다"},{type:"wall",label:"벽",description:"벽 조각을 배치합니다"},{type:"tile",label:"타일",description:"바닥 타일을 배치합니다"},{type:"block",label:"박스",description:"복셀 박스를 쌓습니다"},{type:"object",label:"오브젝트",description:"타일 위에 장식을 배치합니다"},{type:"npc",label:"NPC",description:"NPC를 배치합니다"}],yt=[{type:"none",label:"없음"},{type:"grass",label:"잔디"},{type:"sand",label:"모래"},{type:"snowfield",label:"눈밭"}],ks=[{type:"none",label:"없음"},{type:"sakura",label:"벚꽃나무"},{type:"flag",label:"깃발"},{type:"fire",label:"불"},{type:"billboard",label:"간판"},{type:"model",label:"기본 기물"}],Rs=[{type:"box",label:"박스"},{type:"stairs",label:"계단"},{type:"round",label:"원형"},{type:"ramp",label:"경사"}],Ps=[{value:0,label:"0도"},{value:Math.PI/2,label:"90도"},{value:Math.PI,label:"180도"},{value:Math.PI*1.5,label:"270도"}],Re=n?Array.from(le.values()).find(v=>v.walls.some(pe=>pe.id===n)):le.get(r??""),be=i?Array.from(Ie.values()).find(v=>v.tiles.some(pe=>pe.id===i)):Ie.get(Me??""),Pn=i?be?.tiles.find(v=>v.id===i):void 0,Ds=o?Qe.find(v=>v.id===o):void 0,Lo=Zt.find(v=>v.type===e)?.label??e,Go=yt.find(v=>v.type===A)?.label??A,zo=ks.find(v=>v.type===B)?.label??B,Oo=Rs.find(v=>v.type===g)?.label??g,St=Dt(F)??it[0],Uo=()=>{!n||!Re||Te(Re.id,n)},Wo=()=>{!i||!be||lt(be.id,i)},Ho=()=>{o&&In(o)},Vt=(v,pe,he,Pe)=>{const De=pt.createScopedBuildingMeshId(pe,he,Pe.id),ct=v?Ae.get(v):void 0,Mt=pt.createScopedAssetMeshConfig(De,Pe,ct);return Ae.has(De)?Oe(De,Mt):bt(Mt),De},$o=v=>{if(!Re)return;const he=(n?Re.walls.find(De=>De.id===n):void 0)?.materialId??Re.frontMeshId;if(n){const De=Vt(he,n,"wall",v);at(Re.id,n,{materialId:De});return}const Pe=Vt(Re.frontMeshId,Gn("placement-wall"),"wall",v);He(Pe)},Zo=v=>{if(!be)return;if(i){const he=Vt(Pn?.materialId??be.floorMeshId,i,"tile",v);Ce(be.id,i,{materialId:he});return}const pe=Vt(be.floorMeshId,Gn("placement-tile"),"tile",v);M(pe)},Vo=v=>{if(!be)return;if(i){const De=Pn?.materialId??be.floorMeshId,ct=pt.createScopedBuildingMeshId(i,"tile-color",v),Mt=Os(ct,v,Ae.get(De));Ae.has(ct)?Oe(ct,Mt):bt(Mt),Ce(be.id,i,{materialId:ct});return}const pe=y??be.floorMeshId,he=pt.createScopedBuildingMeshId(Gn("placement-tile-color"),"tile",v),Pe=Os(he,v,Ae.get(pe));bt(Pe),M(he)},Fs=(v,pe=T)=>{if(C(v,pe),!i||!be)return;const he=be.tiles.find(Pe=>Pe.id===i);!he||!he.objectType||he.objectType==="none"||he.objectType==="water"||Ce(be.id,i,{objectConfig:{...he.objectConfig??{},terrainColor:v,terrainAccentColor:pe}})};return t.jsxs("div",{className:"building-panel",children:[t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"편집 모드"}),t.jsx("div",{className:"building-panel__modes",children:Zt.map(v=>t.jsxs("button",{className:`building-panel__mode-btn ${e===v.type?"building-panel__mode-btn--active":""}`,onClick:()=>s(v.type),children:[t.jsx("span",{className:"building-panel__mode-label",children:v.label}),t.jsx("span",{className:"building-panel__mode-desc",children:v.description})]},v.type))})]}),(e==="wall"||e==="none")&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"벽 회전 / 삭제"}),t.jsx("div",{className:"building-panel__segmented",children:Ps.map(v=>t.jsx("button",{className:`building-panel__segment-btn ${Math.abs(_-v.value)<1e-4?"building-panel__segment-btn--active":""}`,onClick:()=>j(v.value),children:v.label},v.value))}),t.jsxs("div",{className:"building-panel__delete-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"선택한 벽"}),t.jsx("span",{children:n?`ID: ${n}`:"벽 마커를 클릭해 선택하세요"})]}),t.jsx("button",{className:"building-panel__delete-button",disabled:!n||!Re,onClick:Uo,children:"선택 벽 삭제"})]})]}),(e==="wall"||e==="tile"||e==="none")&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"에셋 재질"}),t.jsxs("div",{className:"building-panel__asset-targets",children:[t.jsxs("span",{children:["벽: ",Re?.name??"선택 없음"]}),t.jsxs("span",{children:["타일: ",i?`선택 타일 ${i}`:"다음 생성 타일"]}),t.jsxs("span",{children:["현재 생성 재질: ",y??be?.floorMeshId??"기본값"]})]}),t.jsxs("div",{className:"building-panel__asset-list",children:[vt.map(v=>t.jsxs("div",{className:"building-panel__asset-card",children:[t.jsx(pt.AssetPreviewCanvas,{asset:v,size:54}),t.jsxs("div",{className:"building-panel__asset-info",children:[t.jsx("strong",{children:v.name}),t.jsx("span",{children:v.kind})]}),t.jsxs("div",{className:"building-panel__asset-actions",children:[t.jsx("button",{className:"building-panel__asset-action",disabled:!Re,onClick:()=>$o(v),children:"벽"}),t.jsx("button",{className:"building-panel__asset-action",disabled:!be,onClick:()=>Zo(v),children:"타일"})]})]},v.id)),vt.length===0&&t.jsx("div",{className:"building-panel__empty",children:"사용 가능한 빌딩 에셋이 없습니다."})]})]}),(e==="tile"||e==="none")&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"지형 덮개"}),t.jsx("div",{className:"building-panel__grid",children:yt.map(v=>t.jsx("button",{className:`building-panel__grid-btn ${A===v.type?"building-panel__grid-btn--active":""}`,onClick:()=>w(v.type),children:v.label},v.type))}),t.jsxs("div",{className:"building-panel__terrain-colors",children:[t.jsxs("label",{children:[t.jsx("span",{children:"기본색"}),t.jsx("input",{type:"color",value:x,onChange:v=>Fs(v.target.value)})]}),t.jsxs("label",{children:[t.jsx("span",{children:"강조색"}),t.jsx("input",{type:"color",value:T,onChange:v=>Fs(x,v.target.value)})]})]})]}),(e==="object"||e==="none")&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"배치 오브젝트"}),t.jsx("div",{className:"building-panel__grid",children:ks.map(v=>t.jsx("button",{className:`building-panel__grid-btn ${B===v.type?"building-panel__grid-btn--active":""}`,onClick:()=>{I(v.type),v.type==="model"&&St&&(G(St.defaultScale),L(St.defaultColor),E(St.modelUrl??""))},children:v.label},v.type))})]}),e==="object"&&B==="model"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"기본 기물 GLB"}),t.jsx("div",{className:"building-panel__grid",children:it.map(v=>t.jsx("button",{className:`building-panel__grid-btn ${F===v.id?"building-panel__grid-btn--active":""}`,onClick:()=>{R(v.id),G(v.defaultScale),L(v.defaultColor),E(v.modelUrl??"")},children:v.label},v.id))}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("label",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"GLB URL"}),t.jsx("input",{type:"text",value:D,onChange:v=>E(v.target.value),placeholder:"gltf/props/door.glb",className:"building-panel__text-input"})]}),t.jsxs("label",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"스케일"}),t.jsx("input",{type:"number",min:"0.1",max:"10",step:"0.1",value:P,onChange:v=>G(Number(v.target.value)||1),className:"building-panel__number-input"})]}),t.jsxs("label",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"색상"}),t.jsx("input",{type:"color",value:z,onChange:v=>L(v.target.value),style:{width:"36px",height:"24px",border:"none",cursor:"pointer",background:"none"}}),t.jsx("span",{className:"building-panel__info-value",style:{fontSize:"10px"},children:z})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"Fallback"}),t.jsx("span",{className:"building-panel__info-value",children:St?.fallbackKind??"generic"})]})]})]}),t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"타일 설정"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"크기"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>l(Math.max(1,a-1)),children:"-"}),t.jsx("span",{className:"building-panel__stepper-value",children:a}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>l(Math.min(4,a+1)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"격자 맞춤"}),t.jsx("button",{className:`building-panel__toggle ${h?"building-panel__toggle--on":""}`,onClick:()=>k(!h),children:h?"ON":"OFF"})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"높이"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>d(Math.max(0,c-1)),children:"-"}),t.jsx("span",{className:"building-panel__stepper-value",children:c}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>d(Math.min(6,c+1)),children:"+"})]})]})]}),t.jsx("div",{className:"building-panel__section-subtitle",children:"타일 형태"}),t.jsx("div",{className:"building-panel__grid",children:Rs.map(v=>t.jsx("button",{className:`building-panel__grid-btn ${g===v.type?"building-panel__grid-btn--active":""}`,onClick:()=>p(v.type),children:v.label},v.type))}),t.jsx("div",{className:"building-panel__section-subtitle",children:"타일 회전"}),t.jsx("div",{className:"building-panel__segmented",children:Ps.map(v=>t.jsx("button",{className:`building-panel__segment-btn ${Math.abs(m-v.value)<1e-4?"building-panel__segment-btn--active":""}`,onClick:()=>f(v.value),children:v.label},v.value))}),t.jsxs("div",{className:"building-panel__delete-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"선택한 타일"}),t.jsx("span",{children:i?`ID: ${i}`:"타일 하이라이트를 클릭해 선택하세요"})]}),t.jsx("button",{className:"building-panel__delete-button",disabled:!i||!be,onClick:Wo,children:"선택 타일 삭제"})]})]}),(e==="block"||e==="none")&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"박스 편집"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"박스 크기"}),t.jsxs("span",{className:"building-panel__info-value",children:[a," x ",a]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"쌓기 높이"}),t.jsx("span",{className:"building-panel__info-value",children:c})]})]}),t.jsxs("div",{className:"building-panel__delete-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"선택한 박스"}),t.jsx("span",{children:Ds?`ID: ${Ds.id}`:"박스 하이라이트를 클릭해 선택하세요"})]}),t.jsx("button",{className:"building-panel__delete-button",disabled:!o,onClick:Ho,children:"선택 박스 삭제"})]})]}),e==="tile"&&Me&&(()=>{const v=Ie.get(Me),pe=Pn?.materialId??y??v?.floorMeshId,he=pe?Ae.get(pe):void 0;return he?t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"타일 색상"}),t.jsx("div",{className:"building-panel__info",children:t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"색상"}),t.jsx("input",{type:"color",value:he.color||"#888888",onChange:Pe=>Vo(Pe.target.value),style:{width:"36px",height:"24px",border:"none",cursor:"pointer",background:"none"}}),t.jsx("span",{className:"building-panel__info-value",style:{fontSize:"10px"},children:he.color||"#888888"})]})})]}):null})(),t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"효과"}),t.jsx("div",{className:"building-panel__info",children:t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"눈"}),t.jsx("button",{className:`building-panel__toggle ${N?"building-panel__toggle--on":""}`,onClick:()=>H(!N),children:N?"ON":"OFF"})]})})]}),e==="object"&&B!=="none"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"오브젝트 회전"}),t.jsx("div",{className:"building-panel__grid",children:[0,Math.PI/4,Math.PI/2,Math.PI*.75,Math.PI,Math.PI*1.25,Math.PI*1.5,Math.PI*1.75].map((v,pe)=>t.jsx("button",{className:`building-panel__grid-btn ${Math.abs(fe-v)<.01?"building-panel__grid-btn--active":""}`,onClick:()=>xe(v),children:pe*45},v))})]}),e==="object"&&B==="sakura"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"벚꽃나무 색상"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"꽃잎"}),t.jsx("input",{type:"color",value:et,onChange:v=>Rn(v.target.value),style:{width:"36px",height:"24px",border:"none",cursor:"pointer",background:"none"}}),t.jsx("span",{className:"building-panel__info-value",style:{fontSize:"10px"},children:et})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"나무껍질"}),t.jsx("input",{type:"color",value:Ht,onChange:v=>$t(v.target.value),style:{width:"36px",height:"24px",border:"none",cursor:"pointer",background:"none"}}),t.jsx("span",{className:"building-panel__info-value",style:{fontSize:"10px"},children:Ht})]})]})]}),B==="fire"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"불 설정"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"강도"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>ie(Math.max(.5,X-.5)),children:"-"}),t.jsx("span",{className:"building-panel__stepper-value",children:X.toFixed(1)}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>ie(Math.min(3,X+.5)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"너비"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>ue(Math.max(.3,Q-.2)),children:"-"}),t.jsxs("span",{className:"building-panel__stepper-value",children:[Q.toFixed(1),"m"]}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>ue(Math.min(4,Q+.2)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"높이"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>O(Math.max(.5,se-.3)),children:"-"}),t.jsxs("span",{className:"building-panel__stepper-value",children:[se.toFixed(1),"m"]}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>O(Math.min(5,se+.3)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"색상"}),t.jsx("input",{type:"color",value:q,onChange:v=>me(v.target.value),style:{width:"36px",height:"24px",border:"none",cursor:"pointer",background:"none"}}),t.jsx("span",{className:"building-panel__info-value",style:{fontSize:"10px"},children:q})]})]})]}),B==="billboard"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"간판 설정"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",style:{flexDirection:"column",alignItems:"stretch",gap:"4px"},children:[t.jsx("span",{className:"building-panel__info-label",children:"문구"}),t.jsx("input",{type:"text",value:An,onChange:v=>kn(v.target.value),placeholder:"표시할 문구...",style:{width:"100%",padding:"4px 6px",fontSize:"11px",background:"var(--panel-bg, #1a1a2e)",border:"1px solid var(--border-color, #333)",borderRadius:"3px",color:"inherit",boxSizing:"border-box"}})]}),t.jsxs("div",{className:"building-panel__info-item",style:{flexDirection:"column",alignItems:"stretch",gap:"4px"},children:[t.jsx("span",{className:"building-panel__info-label",children:"이미지 URL"}),t.jsx("input",{type:"text",value:Bn,onChange:v=>Wt(v.target.value),placeholder:"https://...",style:{width:"100%",padding:"4px 6px",fontSize:"11px",background:"var(--panel-bg, #1a1a2e)",border:"1px solid var(--border-color, #333)",borderRadius:"3px",color:"inherit",boxSizing:"border-box"}})]}),t.jsxs("div",{className:"building-panel__info-item",style:{flexDirection:"column",alignItems:"stretch",gap:"4px"},children:[t.jsx("span",{className:"building-panel__info-label",children:"색상"}),t.jsx("div",{className:"building-panel__grid",children:br.map(v=>t.jsx("button",{className:`building-panel__grid-btn ${En===v.value?"building-panel__grid-btn--active":""}`,onClick:()=>xt(v.value),style:{borderBottom:`3px solid ${v.value}`},children:v.label},v.value))})]})]})]}),B==="flag"&&t.jsxs("div",{className:"building-panel__section",children:[t.jsx("div",{className:"building-panel__section-title",children:"깃발 설정"}),t.jsxs("div",{className:"building-panel__info",children:[t.jsxs("div",{className:"building-panel__info-item",style:{flexDirection:"column",alignItems:"stretch",gap:"4px"},children:[t.jsx("span",{className:"building-panel__info-label",children:"스타일"}),t.jsx("div",{className:"building-panel__grid",children:gr.map(([v,pe])=>t.jsx("button",{className:`building-panel__grid-btn ${ee===v?"building-panel__grid-btn--active":""}`,onClick:()=>te(v),children:pe.label},v))})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"너비"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>Y(Math.max(.5,U-.5)),children:"-"}),t.jsxs("span",{className:"building-panel__stepper-value",children:[U,"m"]}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>Y(Math.min(8,U+.5)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"높이"}),t.jsxs("div",{className:"building-panel__stepper",children:[t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>$(Math.max(.5,W-.5)),children:"-"}),t.jsxs("span",{className:"building-panel__stepper-value",children:[W,"m"]}),t.jsx("button",{className:"building-panel__stepper-btn",onClick:()=>$(Math.min(6,W+.5)),children:"+"})]})]}),t.jsxs("div",{className:"building-panel__info-item",style:{flexDirection:"column",alignItems:"stretch",gap:"4px"},children:[t.jsx("span",{className:"building-panel__info-label",children:"이미지 URL"}),t.jsx("input",{type:"text",value:Z,onChange:v=>J(v.target.value),placeholder:"https://...",style:{width:"100%",padding:"4px 6px",fontSize:"11px",background:"var(--panel-bg, #1a1a2e)",border:"1px solid var(--border-color, #333)",borderRadius:"3px",color:"inherit",boxSizing:"border-box"}})]})]})]}),t.jsxs("div",{className:"building-panel__info",style:{marginTop:"auto"},children:[t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"현재 모드"}),t.jsx("span",{className:"building-panel__info-value",children:Lo})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"지형 덮개"}),t.jsx("span",{className:"building-panel__info-value",children:Go})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"오브젝트"}),t.jsx("span",{className:"building-panel__info-value",children:zo})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"타일 높이"}),t.jsx("span",{className:"building-panel__info-value",children:c})]}),t.jsxs("div",{className:"building-panel__info-item",children:[t.jsx("span",{className:"building-panel__info-label",children:"타일 형태"}),t.jsx("span",{className:"building-panel__info-value",children:Oo})]})]})]})},ut={name:"플레이어",colors:{body:"#ffd9b8",hair:"#3a2a1a",hat:"#5a8acf",top:"#f0e0c8",bottom:"#3a4a6a",shoes:"#3a2a1a"},face:"default",hair:"short"},gi={hat:"모자",top:"상의",bottom:"하의",shoes:"신발",face:"표정",weapon:"무기",accessory:"액세서리"},yr={short:"단발",long:"긴머리",cap:"모자머리",bun:"쪽머리",spiky:"뻗친머리"},Sr={default:"기본",smile:"미소",wink:"윙크",sleepy:"졸림",surprised:"놀람"},zn={hat:null,top:null,bottom:null,shoes:null,face:null,weapon:null,accessory:null},an=rt.create((e,s)=>({appearance:{...ut,colors:{...ut.colors}},outfits:{...zn},setName:n=>e(i=>({appearance:{...i.appearance,name:n.slice(0,16)||"플레이어"}})),setColor:(n,i)=>e(o=>({appearance:{...o.appearance,colors:{...o.appearance.colors,[n]:i}}})),setFace:n=>e(i=>({appearance:{...i.appearance,face:n}})),setHair:n=>e(i=>({appearance:{...i.appearance,hair:n}})),equipOutfit:(n,i)=>e(o=>({outfits:{...o.outfits,[n]:i}})),resetAppearance:()=>e({appearance:{...ut,colors:{...ut.colors}},outfits:{...zn}}),getEquippedAssetIds:()=>Object.values(s().outfits).filter(n=>typeof n=="string"&&n.length>0),serialize:()=>{const n=s();return{version:2,appearance:{...n.appearance,colors:{...n.appearance.colors}},outfits:{...n.outfits}}},hydrate:n=>{!n||n.version!==1&&n.version!==2||e({appearance:{...ut,...n.appearance,colors:{...ut.colors,...n.appearance.colors}},outfits:{...zn,...n.outfits}})}})),Mr=["hat","top","bottom","shoes","face","weapon","accessory"],jr=(e,s)=>s==="weapon"?e.kind==="weapon"||e.slot==="weapon":e.slot===s&&(e.kind==="characterPart"||e.kind==="weapon"),wr=()=>{const e=an(y=>y.outfits),s=an(y=>y.equipOutfit),n=an(y=>y.resetAppearance),i=Ye.useAssetStore(y=>y.ids),o=Ye.useAssetStore(y=>y.records),r=Ye.useAssetStore(y=>y.isLoading),a=Ye.useAssetStore(y=>y.error),[l,c]=u.useState("top"),[d,g]=u.useState(""),[p,m]=u.useState(!1),f=u.useMemo(()=>{const y=d.trim().toLowerCase();return i.map(M=>o[M]).filter(M=>!!M).filter(M=>jr(M,l)).filter(M=>y?M.tags?.some(_=>_.toLowerCase().includes(y))??!1:!0).filter(M=>!p||M.metadata?.owned!==!1)},[i,o,p,l,d]);return t.jsxs("div",{className:"character-asset-panel",children:[t.jsxs("section",{className:"character-asset-panel__section",children:[t.jsxs("div",{className:"character-asset-panel__header",children:[t.jsx("span",{className:"character-asset-panel__section-title",children:"캐릭터 에셋"}),t.jsx("button",{className:"character-asset-panel__ghost-btn",onClick:n,type:"button",children:"초기화"})]}),t.jsx("div",{className:"character-asset-panel__slot-grid",children:Mr.map(y=>t.jsxs("button",{type:"button",className:`character-asset-panel__slot-btn ${l===y?"character-asset-panel__slot-btn--active":""}`,onClick:()=>c(y),children:[t.jsx("span",{children:gi[y]}),t.jsx("small",{children:e[y]??"비어있음"})]},y))})]}),t.jsxs("section",{className:"character-asset-panel__section",children:[t.jsxs("div",{className:"character-asset-panel__filters",children:[t.jsx("input",{value:d,onChange:y=>g(y.target.value),placeholder:"태그 검색",className:"character-asset-panel__input"}),t.jsxs("label",{className:"character-asset-panel__check",children:[t.jsx("input",{type:"checkbox",checked:p,onChange:y=>m(y.target.checked)}),"보유만"]})]}),a&&t.jsx("p",{className:"character-asset-panel__notice",children:a}),r&&t.jsx("p",{className:"character-asset-panel__notice",children:"에셋 로딩 중"}),t.jsxs("div",{className:"character-asset-panel__asset-list",children:[t.jsxs("button",{type:"button",className:`character-asset-panel__asset-card ${e[l]===null?"character-asset-panel__asset-card--active":""}`,onClick:()=>s(l,null),children:[t.jsx("div",{className:"character-asset-panel__empty-preview"}),t.jsx("span",{children:"비우기"})]}),f.map(y=>t.jsxs("button",{type:"button",className:`character-asset-panel__asset-card ${e[l]===y.id?"character-asset-panel__asset-card--active":""}`,onClick:()=>s(l,y.id),children:[t.jsx(pt.AssetPreviewCanvas,{asset:y,size:58}),t.jsx("span",{children:y.name})]},y.id)),f.length===0&&t.jsx("p",{className:"character-asset-panel__notice",children:"선택한 슬롯에 사용할 에셋이 없습니다."})]})]})]})},_r=e=>{const s=e.trigger;switch(s.type){case"manual":return{type:"manual",key:s.key};case"interaction":return{type:"interaction",targetId:s.targetId,...s.action?{action:s.action}:{}};case"enterArea":return{type:"enterArea",areaId:s.areaId};case"itemCollected":return{type:"itemCollected",itemId:s.itemId};case"timeChanged":return{type:"timeChanged",...s.hour!==void 0?{hour:s.hour}:{}};case"calendarEventStarted":return{type:"calendarEventStarted",eventId:s.eventId};case"questChanged":return{type:"questChanged",questId:s.questId,...s.status?{status:s.status}:{}};case"custom":return{type:"custom",key:s.key};default:return s}},Cr=({data:e,id:s})=>{const[n,i]=u.useState(null),[o,r]=u.useState(""),a=l=>{e.onEdit?.(s,l,ln(o)),i(null)};return t.jsxs("div",{className:"gameplay-event-node",children:[t.jsx(Be.Handle,{type:"target",position:Be.Position.Top,className:"gameplay-event-node__handle"}),t.jsxs("div",{className:"gameplay-event-node__header",children:[t.jsx("span",{children:e.title}),s!=="root"&&s!=="trigger"&&s!=="policy"&&t.jsx("button",{type:"button",className:"gameplay-event-node__delete",onClick:()=>e.onDelete?.(s),children:"Delete"})]}),e.fields&&Object.entries(e.fields).map(([l,c])=>t.jsx("div",{className:"gameplay-event-node__field",children:n===l?t.jsxs("div",{className:"gameplay-event-node__edit",children:[t.jsx("input",{value:o,onChange:d=>r(d.target.value),onKeyDown:d=>{d.key==="Enter"&&a(l),d.key==="Escape"&&i(null)},autoFocus:!0}),t.jsx("button",{type:"button",onClick:()=>a(l),children:"Save"}),t.jsx("button",{type:"button",onClick:()=>i(null),children:"Cancel"})]}):t.jsxs("button",{type:"button",className:"gameplay-event-node__value",onClick:()=>{l!=="type"&&(i(l),r(String(c)))},children:[t.jsx("span",{children:l}),t.jsx("strong",{children:String(c)})]})},l)),t.jsx(Be.Handle,{type:"source",position:Be.Position.Bottom,className:"gameplay-event-node__handle"})]})},Tr=e=>{switch(e){case"manual":return{type:e,key:"custom.run"};case"interaction":return{type:e,targetId:"npc:tommy",action:"talk"};case"enterArea":return{type:e,areaId:"meadow"};case"itemCollected":return{type:e,itemId:"apple"};case"timeChanged":return{type:e,hour:9};case"calendarEventStarted":return{type:e,eventId:"event.cherryblossom"};case"questChanged":return{type:e,questId:"welcome",status:"active"};case"custom":return{type:e,key:"custom.event"};default:return e}},Nr=e=>{switch(e){case"always":return{type:e};case"hasItem":return{type:e,itemId:"apple",count:1};case"questStatus":return{type:e,questId:"welcome",status:"active"};case"eventActive":return{type:e,eventId:"event.cherryblossom"};case"flagEquals":return{type:e,key:"gameplayReady",value:!0};case"custom":return{type:e,key:"custom.condition"};default:return e}},Ir=e=>{switch(e){case"giveItem":return{type:e,itemId:"apple",count:1};case"removeItem":return{type:e,itemId:"apple",count:1};case"startQuest":return{type:e,questId:"welcome"};case"completeQuest":return{type:e,questId:"welcome"};case"showDialog":return{type:e,dialogTreeId:"npc.villager",npcId:"mei"};case"toast":return{type:e,kind:"success",text:"이벤트 실행"};case"setFlag":return{type:e,key:"customFlag",value:!0};case"notifyQuestFlag":return{type:e,key:"customFlag",value:!0};case"emit":return{type:e,eventName:"gameplay.custom"};case"custom":return{type:e,key:"custom.action"};default:return e}},ln=e=>{if(e==="true")return!0;if(e==="false")return!1;const s=Number(e);return Number.isFinite(s)&&e.trim()!==""?s:e},Ar=e=>Array.isArray(e)||typeof e=="object"&&e!==null?JSON.stringify(e):e,qt={stroke:"#7a86a8",strokeWidth:2},Kt={type:Be.MarkerType.ArrowClosed,color:"#7a86a8",width:20,height:20},Br={editable:Cr},Er=(e,s,n)=>{const i=[{id:"root",type:"editable",position:{x:260,y:20},data:{title:e.name,fields:{id:e.id,name:e.name,description:e.description??""},onEdit:s,onDelete:n}},{id:"trigger",type:"editable",position:{x:260,y:180},data:{title:`Trigger: ${e.trigger.type}`,fields:{...e.trigger},onEdit:s,onDelete:n}},{id:"policy",type:"editable",position:{x:560,y:180},data:{title:"Policy",fields:{run:e.policy?.run??"repeat",cooldownMs:e.policy?.cooldownMs??0,requiresServer:e.policy?.requiresServer??!1},onEdit:s,onDelete:n}}],o=[{id:"root-trigger",source:"root",target:"trigger",style:qt,markerEnd:Kt},{id:"root-policy",source:"root",target:"policy",style:qt,markerEnd:Kt}];return(e.conditions??[]).forEach((r,a)=>{const l=`condition:${a}`;i.push({id:l,type:"editable",position:{x:40,y:360+a*150},data:{title:`Condition: ${r.type}`,fields:{...r},onEdit:s,onDelete:n}}),o.push({id:`trigger-${l}`,source:"trigger",target:l,style:qt,markerEnd:Kt})}),e.actions.forEach((r,a)=>{const l=`action:${a}`;i.push({id:l,type:"editable",position:{x:420,y:360+a*150},data:{title:`Action: ${r.type}`,fields:{...r},onEdit:s,onDelete:n}}),o.push({id:`${a===0?"trigger":`action:${a-1}`}-${l}`,source:a===0?"trigger":`action:${a-1}`,target:l,style:qt,markerEnd:Kt})}),{nodes:i,edges:o}};function kr({blueprints:e,onCreate:s,onUpdate:n,onDelete:i,onRun:o}){const r=u.useMemo(()=>new At.GameplayEventEngine({blueprints:e}),[e]),[a,l]=u.useState("custom-toast"),[c,d]=u.useState("Custom Toast Event"),[g,p]=u.useState("custom.run"),[m,f]=u.useState("커스텀 이벤트 실행"),[y,M]=u.useState(e[0]?.id??null),_=u.useMemo(()=>e.find(h=>h.id===y)??e[0]??null,[e,y]),[j,A]=u.useState({kind:"idle",message:"Ready"}),[w,x,T]=Be.useNodesState([]),[C,B,I]=Be.useEdgesState([]),F=()=>{const h={id:a.trim()||`event-${Date.now()}`,name:c.trim()||"Untitled Event",trigger:{type:"manual",key:g.trim()||"custom.run"},conditions:[{type:"always"}],actions:[{type:"toast",kind:"success",text:m.trim()||"이벤트 실행"},{type:"setFlag",key:a.trim()||"customEvent",value:!0}],policy:{run:"repeat"},tags:["editor"]};s?.(h),M(h.id),A({kind:"success",message:`Created ${h.id}`})},R=u.useCallback(h=>{if(!_)return;const k={..._,...h};n?.(k),M(k.id),A({kind:"success",message:`Updated ${k.id}`})},[n,_]),D=()=>{if(!_)return;i?.(_.id);const h=e.find(k=>k.id!==_.id)??null;M(h?.id??null),A({kind:"success",message:`Deleted ${_.id}`})},E=async h=>{const k=_r(h);o?await o(k):await r.dispatch(k),A({kind:"success",message:`Ran ${h.id}`})},P=u.useCallback((h,k)=>{if(!_)return;const U=[..._.conditions??[]];U[h]=k,R({conditions:U})},[_,R]),G=u.useCallback((h,k)=>{if(!_)return;const U=[..._.actions];U[h]=k,R({actions:U})},[_,R]),z=u.useCallback((h,k,U)=>{if(!_||k==="type")return;const W=Ar(U);if(h==="root"){R({[k]:W});return}if(h==="policy"){k==="run"&&(W==="once"||W==="repeat")&&R({policy:{..._.policy,run:W}}),k==="cooldownMs"&&R({policy:{..._.policy,cooldownMs:Number(W)}}),k==="requiresServer"&&R({policy:{..._.policy,requiresServer:ln(String(W))===!0}});return}if(h==="trigger"){const Z=_.trigger;Z.type==="manual"&&k==="key"&&R({trigger:{type:"manual",key:String(W)}}),Z.type==="interaction"&&(k==="targetId"||k==="action")&&R({trigger:{...Z,[k]:String(W)}}),Z.type==="enterArea"&&k==="areaId"&&R({trigger:{type:"enterArea",areaId:String(W)}}),Z.type==="itemCollected"&&k==="itemId"&&R({trigger:{type:"itemCollected",itemId:String(W)}}),Z.type==="timeChanged"&&k==="hour"&&R({trigger:{type:"timeChanged",hour:Number(W)}}),Z.type==="calendarEventStarted"&&k==="eventId"&&R({trigger:{type:"calendarEventStarted",eventId:String(W)}}),Z.type==="questChanged"&&(k==="questId"||k==="status")&&R({trigger:{...Z,[k]:String(W)}}),Z.type==="custom"&&k==="key"&&R({trigger:{type:"custom",key:String(W)}});return}if(h.startsWith("condition:")){const Z=Number(h.split(":")[1]),Y=_.conditions?.[Z];if(!Y)return;P(Z,{...Y,[k]:k==="value"?ln(String(W)):W});return}if(h.startsWith("action:")){const Z=Number(h.split(":")[1]),Y=_.actions[Z];if(!Y)return;G(Z,{...Y,[k]:k==="value"?ln(String(W)):W})}},[_,G,P,R]),L=u.useCallback(h=>{if(_){if(h.startsWith("condition:")){const k=Number(h.split(":")[1]);R({conditions:(_.conditions??[]).filter((U,W)=>W!==k)});return}if(h.startsWith("action:")){const k=Number(h.split(":")[1]);R({actions:_.actions.filter((U,W)=>W!==k)})}}},[_,R]);return u.useEffect(()=>{if(!_){x([]),B([]);return}const h=Er(_,z,L);x(h.nodes),B(h.edges)},[L,z,_,B,x]),t.jsxs("div",{className:"gameplay-event-panel",children:[t.jsxs("section",{className:"gameplay-event-panel__section",children:[t.jsx("div",{className:"gameplay-event-panel__title",children:"Create Manual Event"}),t.jsxs("label",{className:"gameplay-event-panel__field",children:[t.jsx("span",{children:"ID"}),t.jsx("input",{value:a,onChange:h=>l(h.target.value)})]}),t.jsxs("label",{className:"gameplay-event-panel__field",children:[t.jsx("span",{children:"Name"}),t.jsx("input",{value:c,onChange:h=>d(h.target.value)})]}),t.jsxs("label",{className:"gameplay-event-panel__field",children:[t.jsx("span",{children:"Trigger Key"}),t.jsx("input",{value:g,onChange:h=>p(h.target.value)})]}),t.jsxs("label",{className:"gameplay-event-panel__field",children:[t.jsx("span",{children:"Toast Message"}),t.jsx("input",{value:m,onChange:h=>f(h.target.value)})]}),t.jsx("button",{type:"button",className:"gameplay-event-panel__primary",onClick:F,children:"Create Event Blueprint"})]}),t.jsxs("section",{className:"gameplay-event-panel__section",children:[t.jsx("div",{className:"gameplay-event-panel__title",children:"Blueprint Library"}),t.jsx("div",{className:"gameplay-event-panel__list",children:e.map(h=>t.jsxs("article",{className:"gameplay-event-panel__card",children:[t.jsxs("div",{children:[t.jsx("div",{className:"gameplay-event-panel__card-title",children:h.name}),t.jsxs("div",{className:"gameplay-event-panel__card-meta",children:[h.id," · ",h.trigger.type," · ",h.actions.length," action(s)"]})]}),t.jsxs("div",{className:"gameplay-event-panel__card-actions",children:[t.jsx("button",{type:"button",onClick:()=>M(h.id),children:"Edit"}),t.jsx("button",{type:"button",onClick:()=>{E(h)},children:"Run"})]})]},h.id))})]}),_&&t.jsxs("section",{className:"gameplay-event-panel__section gameplay-event-panel__detail",children:[t.jsxs("div",{className:"gameplay-event-panel__editor-head",children:[t.jsxs("div",{children:[t.jsx("div",{className:"gameplay-event-panel__title",children:"Blueprint Node Editor"}),t.jsx("div",{className:"gameplay-event-panel__hint",children:"노드 필드를 클릭해서 값을 수정합니다. 타입 변경은 아래 노드 추가/변경 액션에서 처리합니다."})]}),t.jsxs("label",{className:"gameplay-event-panel__type-select",children:[t.jsx("span",{children:"Trigger"}),t.jsx("select",{value:_.trigger.type,onChange:h=>R({trigger:Tr(h.target.value)}),children:["manual","interaction","enterArea","itemCollected","timeChanged","calendarEventStarted","questChanged","custom"].map(h=>t.jsx("option",{value:h,children:h},h))})]})]}),t.jsx("div",{className:"gameplay-event-panel__flow",children:t.jsxs(Be,{nodes:w,edges:C,nodeTypes:Br,onNodesChange:T,onEdgesChange:I,fitView:!0,children:[t.jsx(Be.Background,{variant:Be.BackgroundVariant.Dots,gap:18,size:1}),t.jsx(Be.Controls,{})]})}),t.jsxs("div",{className:"gameplay-event-panel__node-toolbar",children:[t.jsxs("select",{"aria-label":"Condition type",onChange:h=>{R({conditions:[..._.conditions??[],Nr(h.target.value)]}),h.currentTarget.value=""},defaultValue:"",children:[t.jsx("option",{value:"",disabled:!0,children:"Add Condition Node"}),["always","hasItem","questStatus","eventActive","flagEquals","custom"].map(h=>t.jsx("option",{value:h,children:h},h))]}),t.jsxs("select",{"aria-label":"Action type",onChange:h=>{R({actions:[..._.actions,Ir(h.target.value)]}),h.currentTarget.value=""},defaultValue:"",children:[t.jsx("option",{value:"",disabled:!0,children:"Add Action Node"}),["giveItem","removeItem","startQuest","completeQuest","showDialog","toast","setFlag","notifyQuestFlag","emit","custom"].map(h=>t.jsx("option",{value:h,children:h},h))]})]}),t.jsxs("div",{className:"gameplay-event-panel__actions",children:[t.jsx("button",{type:"button",onClick:D,children:"Delete Blueprint"}),t.jsx("button",{type:"button",onClick:()=>{E(_)},children:"Run Selected"})]})]}),t.jsx("section",{className:"gameplay-event-panel__section",children:t.jsx("div",{className:`gameplay-event-panel__status gameplay-event-panel__status--${j.kind}`,children:j.message})})]})}const Rr="studio-social-world",Pr="Studio Social World",Dr="1.0.0",Fr=(e,s)=>{if(typeof window>"u"||typeof document>"u")return;const n=new Blob([JSON.stringify(s,null,2)],{type:"application/json"}),i=window.URL.createObjectURL(n),o=document.createElement("a");o.href=i,o.download=e,o.click(),window.URL.revokeObjectURL(i)};function Lr({gameplayEvents:e=At.SEED_GAMEPLAY_EVENTS}){const s=Ye.useAssetStore(I=>I.ids),n=Ye.useAssetStore(I=>I.records),i=u.useMemo(()=>s.map(I=>n[I]).filter(I=>!!I),[s,n]),[o,r]=u.useState("main"),[a,l]=u.useState(Rr),[c,d]=u.useState(Pr),[g,p]=u.useState(Dr),[m,f]=u.useState([]),[y,M]=u.useState({kind:"idle",message:"Ready"}),[_,j]=u.useState(null),A=u.useCallback(()=>At.createContentBundleFromSaveSystem(st.getSaveSystem(),i,{id:a,name:c,version:g,gameplayEvents:e}),[i,a,c,e,g]),w=u.useCallback(async()=>{const I=await st.getSaveSystem().list();f(I),M({kind:"success",message:`Loaded ${I.length} save slot(s)`})},[]),x=u.useCallback(async()=>{await st.getSaveSystem().save(o),M({kind:"success",message:`Saved slot "${o}"`}),await w()},[w,o]),T=u.useCallback(async()=>{const I=await st.getSaveSystem().load(o);M({kind:I?"success":"error",message:I?`Loaded slot "${o}"`:`No save data in slot "${o}"`})},[o]),C=u.useCallback(()=>{const I=At.validateContentBundle(A());j(I),M({kind:I.ok?"success":"error",message:I.ok?"Bundle is valid":`Bundle has ${I.errors.length} error(s)`})},[A]),B=u.useCallback(()=>{const I=A(),F=At.validateContentBundle(I);if(j(F),!F.ok){M({kind:"error",message:"Fix bundle validation before export"});return}Fr(`${I.id}-${I.version}.bundle.json`,I),M({kind:"success",message:"Exported content bundle JSON"})},[A]);return t.jsxs("div",{className:"studio-panel",children:[t.jsxs("section",{className:"studio-panel__section",children:[t.jsx("div",{className:"studio-panel__title",children:"World Save"}),t.jsxs("label",{className:"studio-panel__field",children:[t.jsx("span",{children:"Slot"}),t.jsx("input",{value:o,onChange:I=>r(I.target.value||"main")})]}),t.jsxs("div",{className:"studio-panel__actions",children:[t.jsx("button",{type:"button",onClick:()=>{x()},children:"Save"}),t.jsx("button",{type:"button",onClick:()=>{T()},children:"Load"}),t.jsx("button",{type:"button",onClick:()=>{w()},children:"Refresh"})]}),m.length>0&&t.jsx("div",{className:"studio-panel__chips",children:m.map(I=>t.jsx("button",{type:"button",onClick:()=>r(I),children:I},I))})]}),t.jsxs("section",{className:"studio-panel__section",children:[t.jsx("div",{className:"studio-panel__title",children:"Content Bundle"}),t.jsxs("label",{className:"studio-panel__field",children:[t.jsx("span",{children:"Bundle ID"}),t.jsx("input",{value:a,onChange:I=>l(I.target.value)})]}),t.jsxs("label",{className:"studio-panel__field",children:[t.jsx("span",{children:"Name"}),t.jsx("input",{value:c,onChange:I=>d(I.target.value)})]}),t.jsxs("label",{className:"studio-panel__field",children:[t.jsx("span",{children:"Version"}),t.jsx("input",{value:g,onChange:I=>p(I.target.value)})]}),t.jsxs("div",{className:"studio-panel__meta",children:[i.length," asset(s), ",e.length," gameplay event(s),"," ",Array.from(st.getSaveSystem().getBindings()).length," save domain(s)"]}),t.jsxs("div",{className:"studio-panel__actions",children:[t.jsx("button",{type:"button",onClick:C,children:"Validate"}),t.jsx("button",{type:"button",onClick:B,children:"Export JSON"})]})]}),t.jsxs("section",{className:"studio-panel__section",children:[t.jsx("div",{className:"studio-panel__title",children:"Status"}),t.jsx("div",{className:`studio-panel__status studio-panel__status--${y.kind}`,children:y.message}),_&&!_.ok&&t.jsx("ul",{className:"studio-panel__errors",children:_.errors.map(I=>t.jsx("li",{children:I},I))})]})]})}const Gr=()=>t.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:t.jsx("line",{x1:"5",y1:"12",x2:"19",y2:"12"})}),zr=()=>t.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),t.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}),cn=({children:e,title:s,initialWidth:n=280,initialHeight:i=400,minWidth:o=200,minHeight:r=150,maxWidth:a=600,maxHeight:l=800,resizeHandles:c=["right"],className:d="",style:g={},onClose:p,onMinimize:m,draggable:f=!0,onDrop:y})=>{const[M,_]=u.useState({width:n,height:i}),[j,A]=u.useState({x:0,y:0}),[w,x]=u.useState(!1),[T,C]=u.useState(!1),[B,I]=u.useState(""),[F,R]=u.useState({x:0,y:0}),D=u.useRef(null),E=u.useRef(null),P=u.useCallback(h=>k=>{k.preventDefault(),x(!0),I(h)},[]),G=u.useCallback(h=>{if(D.current)if(w){const k=D.current.getBoundingClientRect();let U=M.width,W=M.height;B.includes("right")&&(U=Math.min(a,Math.max(o,h.clientX-k.left))),B.includes("bottom")&&(W=Math.min(l,Math.max(r,h.clientY-k.top))),_({width:U,height:W})}else T&&A({x:h.clientX-F.x,y:h.clientY-F.y})},[w,T,B,M,o,a,r,l,F]),z=u.useCallback(()=>{T&&y&&y(j.x,j.y),x(!1),C(!1),I("")},[T,y,j]),L=u.useCallback(h=>{if(!f||w)return;h.preventDefault(),C(!0);const k=D.current?.getBoundingClientRect();k&&R({x:h.clientX-k.left,y:h.clientY-k.top})},[f,w]);return u.useEffect(()=>{if(w||T)return document.addEventListener("mousemove",G),document.addEventListener("mouseup",z),()=>{document.removeEventListener("mousemove",G),document.removeEventListener("mouseup",z)}},[w,T,G,z]),t.jsxs("div",{ref:D,className:`rp-panel ${d} ${T?"dragging":""}`,style:{width:`${M.width}px`,height:`${M.height}px`,...T?{position:"fixed",left:`${j.x}px`,top:`${j.y}px`,zIndex:10003}:{},...g},children:[t.jsxs("div",{ref:E,className:"rp-header",onMouseDown:L,children:[t.jsx("h3",{className:"rp-title",children:s}),t.jsxs("div",{className:"rp-controls",onMouseDown:h=>h.stopPropagation(),children:[m&&t.jsx("button",{className:"rp-btn rp-btn--minimize",onClick:m,title:"최소화",children:t.jsx(Gr,{})}),p&&t.jsx("button",{className:"rp-btn rp-btn--close",onClick:p,title:"닫기",children:t.jsx(zr,{})})]})]}),t.jsx("div",{className:"rp-content",children:e}),c.map(h=>t.jsx("div",{className:`rp-resize-handle handle-${h}`,onMouseDown:P(h.replace("corner","right bottom"))},h))]})},bi=({children:e,panels:s=[],defaultActivePanels:n=["building","character","camera"],actions:i=[]})=>{const[o,r]=u.useState(n),[a,l]=u.useState([]),[c,d]=u.useState([]),g=[{id:"building",title:"건축",component:t.jsx(vr,{}),defaultSide:"left"},{id:"character",title:"캐릭터",component:t.jsx(wr,{}),defaultSide:"left"},{id:"vehicle",title:"탑승체",component:t.jsx(hi,{}),defaultSide:"left"},{id:"animation",title:"애니메이션",component:t.jsx(ui,{}),defaultSide:"left"},{id:"camera",title:"카메라",component:t.jsx(li,{}),defaultSide:"right"},{id:"motion",title:"모션",component:t.jsx(mi,{}),defaultSide:"right"},{id:"performance",title:"성능",component:t.jsx(fi,{}),defaultSide:"right"}],p=u.useMemo(()=>[...g,...s],[s]),m=x=>{r(T=>T.includes(x)?T.filter(C=>C!==x):[...T,x]),d(T=>T.filter(C=>C!==x))},f=x=>{r(T=>T.filter(C=>C!==x)),l(T=>T.filter(C=>C.id!==x)),d(T=>T.filter(C=>C!==x))},y=x=>{d(T=>[...T,x]),r(T=>T.filter(C=>C!==x)),l(T=>T.filter(C=>C.id!==x))},M=x=>{d(T=>T.filter(C=>C!==x)),r(T=>[...T,x])},_=(x,T,C)=>{const B=a.find(I=>I.id===x);l(B?I=>I.map(F=>F.id===x?{...F,x:T,y:C}:F):I=>[...I,{id:x,x:T,y:C,width:300,height:400}])},j=()=>p.filter(x=>o.includes(x.id)&&x.defaultSide==="left"&&!a.some(T=>T.id===x.id)),A=()=>p.filter(x=>o.includes(x.id)&&x.defaultSide==="right"&&!a.some(T=>T.id===x.id)),w=()=>a.filter(x=>o.includes(x.id));return t.jsxs("div",{className:"editor-root",children:[t.jsxs("div",{className:"editor-panel-bar",children:[p.map(x=>t.jsx("button",{onClick:()=>m(x.id),className:`editor-panel-toggle ${o.includes(x.id)?"active":""}`,title:x.title,children:x.title},x.id)),i.map(x=>t.jsx("button",{onClick:()=>{x.onClick()},className:"editor-panel-toggle",disabled:x.disabled,title:x.label,children:x.label},x.id))]}),j().length>0&&t.jsx("div",{className:"editor-left-stack",children:j().map((x,T)=>t.jsx(cn,{title:x.title,initialWidth:320,initialHeight:Math.min(640,Math.max(420,window.innerHeight-120)),minWidth:260,maxWidth:500,resizeHandles:["right"],className:"editor-glass-panel",style:{marginBottom:T<j().length-1?"8px":"0"},onClose:()=>f(x.id),onMinimize:()=>y(x.id),onDrop:(C,B)=>_(x.id,C,B),children:x.component},x.id))}),A().length>0&&t.jsx("div",{className:"editor-right-stack",children:A().map((x,T)=>t.jsx(cn,{title:x.title,initialWidth:300,initialHeight:Math.min(520,Math.max(360,window.innerHeight-120)),minWidth:260,maxWidth:500,resizeHandles:["corner"],className:"editor-glass-panel",style:{marginBottom:T<A().length-1?"8px":"0"},onClose:()=>f(x.id),onMinimize:()=>y(x.id),onDrop:(C,B)=>_(x.id,C,B),children:x.component},x.id))}),w().map(x=>{const T=p.find(C=>C.id===x.id);return T?t.jsx(cn,{title:T.title,initialWidth:x.width,initialHeight:x.height,minWidth:200,maxWidth:800,resizeHandles:["right","bottom","corner"],className:"editor-glass-panel",style:{position:"fixed",left:`${x.x}px`,top:`${x.y}px`,zIndex:1001},onClose:()=>f(T.id),onMinimize:()=>y(T.id),onDrop:(C,B)=>_(T.id,C,B),children:T.component},x.id):null}),c.length>0&&t.jsx("div",{className:"editor-minimized-dock",children:c.map(x=>{const T=p.find(C=>C.id===x);return T?t.jsx("button",{onClick:()=>M(x),className:"editor-minimized-item",title:`${T.title} 복원`,children:T.title},x):null})}),e]})},Or={xDistance:10,yDistance:22,zDistance:30,fov:58,zoom:1,enableZoom:!0,minZoom:.35,maxZoom:2.4,zoomSpeed:.001,enableCollision:!1,smoothing:{position:.12,rotation:.12,fov:.12}},Ur=({children:e,className:s="",style:n={},shell:i})=>{const o=u.useRef(null);return u.useEffect(()=>{const r=re.useGaesupStore.getState();return o.current={mode:r.mode,cameraOption:r.cameraOption},r.setMode({control:"thirdPerson"}),r.setCameraOption(Or),()=>{const a=o.current;a&&(re.useGaesupStore.getState().setMode(a.mode),re.useGaesupStore.getState().setCameraOption(a.cameraOption))}},[]),t.jsx("div",{className:`gaesup-editor ${s}`,style:{...n},children:t.jsx(bi,{...i?.panels?{panels:i.panels}:{},...i?.defaultActivePanels?{defaultActivePanels:i.defaultActivePanels}:{},...i?.actions?{actions:i.actions}:{},children:e})})},xs=e=>({selectedObjectIds:[],setSelectedObjectIds:s=>e({selectedObjectIds:s}),layoutConfig:null,setLayoutConfig:s=>e({layoutConfig:s}),activeNodeGraph:null,setActiveNodeGraph:s=>e({activeNodeGraph:s}),clipboard:null,setClipboard:s=>e({clipboard:s})}),Wr=xs,xi=rt.create(xs),Hr=()=>{const e=xi();return{...e,selectObject:s=>e.setSelectedObjectIds([s]),selectMultiple:s=>e.setSelectedObjectIds(s),clearSelection:()=>e.setSelectedObjectIds([])}};function $r(e={}){const s={panels:e.panels??[],actions:(e.commands??[]).map(n=>({id:n.id,label:n.label,onClick:n.run}))};return e.defaultActivePanels&&(s.defaultActivePanels=e.defaultActivePanels),e.validate&&(s.validate=e.validate),s}function Zr(){const e=[],s=[];return{execute:async n=>{await n.run(),n.undo&&(e.push(n),s.length=0)},undo:async()=>{const n=e.pop();n?.undo&&(await n.undo(),s.push(n))},redo:async()=>{const n=s.pop();n&&(await n.run(),e.push(n))},canUndo:()=>e.length>0,canRedo:()=>s.length>0,clear:()=>{e.length=0,s.length=0}}}const Vr=["intel","mali","adreno 3","adreno 4","powervr"],Yr=["swiftshader","llvmpipe","software"],Us=["rtx","radeon rx","apple m","apple a1","apple a2"];function vi(){if(typeof window>"u"||typeof document>"u")return{webgl2:!1,maxTextureSize:0,rendererName:"",vendorName:"",cores:4,memory:4,isMobile:!1,pixelRatio:1};const e=document.createElement("canvas"),s=e.getContext("webgl2")??e.getContext("webgl");let n="",i="",o=0,r=!1;if(s){r=typeof WebGL2RenderingContext<"u"&&s instanceof WebGL2RenderingContext,o=s.getParameter(s.MAX_TEXTURE_SIZE)||0;const g=s.getExtension("WEBGL_debug_renderer_info");g&&(n=String(s.getParameter(g.UNMASKED_RENDERER_WEBGL)||""),i=String(s.getParameter(g.UNMASKED_VENDOR_WEBGL)||""))}const a=navigator.hardwareConcurrency??4,l=navigator.deviceMemory??4,c=/android|iphone|ipad|ipod|mobile|opera mini/i.test(navigator.userAgent),d=Math.min(window.devicePixelRatio||1,2);return{webgl2:r,maxTextureSize:o,rendererName:n,vendorName:i,cores:a,memory:l,isMobile:c,pixelRatio:d}}function yi(e){const s=e.rendererName.toLowerCase();return Yr.some(n=>s.includes(n))?"low":e.isMobile?Us.some(n=>s.includes(n))?"medium":"low":Vr.some(n=>s.includes(n))?e.cores>=8&&e.memory>=8?"medium":"low":Us.some(n=>s.includes(n))||e.cores>=8&&e.memory>=8&&e.webgl2?"high":e.cores>=4&&e.memory>=4?"medium":"low"}function vn(e){return e==="high"?{tier:e,instanceScale:1,pixelRatio:2,shadowMapSize:2048,postprocess:!0,outline:!0}:e==="medium"?{tier:e,instanceScale:.7,pixelRatio:1.5,shadowMapSize:1024,postprocess:!0,outline:!0}:{tier:e,instanceScale:.4,pixelRatio:1,shadowMapSize:512,postprocess:!1,outline:!1}}function ls(){const e=vi(),s=yi(e);return{profile:vn(s),capabilities:e}}const Xr=vn("medium"),Si=rt.create(e=>({profile:Xr,capabilities:null,manualOverride:!1,detect:()=>{const{profile:s,capabilities:n}=ls();e({profile:s,capabilities:n,manualOverride:!1})},setTier:s=>{e({profile:vn(s),manualOverride:!0})},resetAuto:()=>{const{profile:s,capabilities:n}=ls();e({profile:s,capabilities:n,manualOverride:!1})}}));qo.enableMapSet();const oe=rt.create()(Ko.immer((e,s)=>({initialized:!1,templates:new Map,instances:new Map,categories:new Map,clothingSets:new Map,clothingCategories:new Map,animations:new Map,editMode:!1,previewAccessories:{},initializeDefaults:()=>e(n=>{n.initialized||(n.animations.set("idle",{id:"idle",name:"Idle",loop:!0,speed:1}),n.animations.set("walk",{id:"walk",name:"Walk",loop:!0,speed:1}),n.animations.set("greet",{id:"greet",name:"Greet",loop:!1,speed:1}),n.animations.set("jump",{id:"jump",name:"Jump",loop:!1,speed:1}),n.animations.set("run",{id:"run",name:"Run",loop:!0,speed:1.5}),n.clothingCategories.set("basic",{id:"basic",name:"기본 의상",description:"Basic clothing sets",clothingSetIds:["rabbit-outfit","basic-suit","formal-suit"]}),n.clothingCategories.set("accessories",{id:"accessories",name:"액세서리",description:"Hats and glasses",clothingSetIds:["hat-set-a","hat-set-b","hat-set-c","glass-set-a","glass-set-b"]}),n.clothingSets.set("rabbit-outfit",{id:"rabbit-outfit",name:"토끼옷",category:"casual",parts:[{id:"rabbit-cloth",type:"top",url:"gltf/ally_cloth_rabbit.glb",position:[0,0,0]}]}),n.clothingSets.set("basic-suit",{id:"basic-suit",name:"양복",category:"formal",parts:[{id:"basic-suit-cloth",type:"top",url:"gltf/ally_cloth.glb",position:[0,0,0]}]}),n.clothingSets.set("formal-suit",{id:"formal-suit",name:"양복 2",category:"formal",parts:[{id:"formal-suit-cloth",type:"top",url:"gltf/formal.glb",position:[0,0,0]}]}),n.clothingSets.set("hat-set-a",{id:"hat-set-a",name:"모자 A",category:"casual",parts:[{id:"hat-a",type:"hat",url:"gltf/hat_a.glb",position:[0,0,0]}]}),n.clothingSets.set("hat-set-b",{id:"hat-set-b",name:"모자 B",category:"casual",parts:[{id:"hat-b",type:"hat",url:"gltf/hat_b.glb",position:[0,0,0]}]}),n.clothingSets.set("hat-set-c",{id:"hat-set-c",name:"모자 C",category:"casual",parts:[{id:"hat-c",type:"hat",url:"gltf/hat_c.glb",position:[0,0,0]}]}),n.clothingSets.set("glass-set-a",{id:"glass-set-a",name:"안경 A",category:"casual",parts:[{id:"glass-a",type:"glasses",url:"gltf/glass_a.glb",position:[0,0,0]}]}),n.clothingSets.set("glass-set-b",{id:"glass-set-b",name:"슈퍼 안경",category:"casual",parts:[{id:"super-glass",type:"glasses",url:"gltf/super_glass.glb",position:[0,0,0]}]}),n.categories.set("humanoid",{id:"humanoid",name:"캐릭터",description:"Human-like characters",templateIds:["ally","oneyee"]}),n.templates.set("ally",{id:"ally",name:"올춘삼",description:"Ally character",category:"humanoid",baseParts:[{id:"ally-body",type:"body",url:"gltf/ally_body.glb",position:[0,0,0]}],clothingParts:[],defaultAnimation:"idle",defaultClothingSet:"rabbit-outfit"}),n.templates.set("oneyee",{id:"oneyee",name:"원덕배",description:"Oneyee character",category:"humanoid",baseParts:[{id:"oneyee-body",type:"body",url:"gltf/oneyee.glb",position:[0,0,0]}],clothingParts:[],defaultAnimation:"idle",defaultClothingSet:"basic-suit"}),n.selectedCategoryId="humanoid",n.selectedTemplateId="ally",n.selectedClothingCategoryId="basic",n.selectedClothingSetId="rabbit-outfit",n.initialized=!0)}),addTemplate:n=>e(i=>{i.templates.set(n.id,n)}),updateTemplate:(n,i)=>e(o=>{const r=o.templates.get(n);r&&o.templates.set(n,{...r,...i})}),removeTemplate:n=>e(i=>{i.templates.delete(n)}),addInstance:n=>e(i=>{i.instances.set(n.id,n)}),updateInstance:(n,i)=>e(o=>{const r=o.instances.get(n);r&&o.instances.set(n,{...r,...i})}),removeInstance:n=>e(i=>{i.instances.delete(n)}),addCategory:n=>e(i=>{i.categories.set(n.id,n)}),updateCategory:(n,i)=>e(o=>{const r=o.categories.get(n);r&&o.categories.set(n,{...r,...i})}),removeCategory:n=>e(i=>{i.categories.delete(n)}),addClothingSet:n=>e(i=>{i.clothingSets.set(n.id,n)}),updateClothingSet:(n,i)=>e(o=>{const r=o.clothingSets.get(n);r&&o.clothingSets.set(n,{...r,...i})}),removeClothingSet:n=>e(i=>{i.clothingSets.delete(n)}),addClothingCategory:n=>e(i=>{i.clothingCategories.set(n.id,n)}),updateClothingCategory:(n,i)=>e(o=>{const r=o.clothingCategories.get(n);r&&o.clothingCategories.set(n,{...r,...i})}),removeClothingCategory:n=>e(i=>{i.clothingCategories.delete(n)}),addAnimation:n=>e(i=>{i.animations.set(n.id,n)}),updateAnimation:(n,i)=>e(o=>{const r=o.animations.get(n);r&&o.animations.set(n,{...r,...i})}),removeAnimation:n=>e(i=>{i.animations.delete(n)}),setSelectedTemplate:n=>e(i=>{i.selectedTemplateId=n}),setSelectedCategory:n=>e(i=>{i.selectedCategoryId=n;const o=i.categories.get(n);if(o&&o.templateIds.length>0){const r=o.templateIds[0];r&&(i.selectedTemplateId=r)}else delete i.selectedTemplateId}),setSelectedInstance:n=>e(i=>{i.selectedInstanceId=n}),setSelectedClothingSet:n=>e(i=>{i.selectedClothingSetId=n}),setSelectedClothingCategory:n=>e(i=>{i.selectedClothingCategoryId=n;const o=i.clothingCategories.get(n);if(o&&o.clothingSetIds.length>0){const r=o.clothingSetIds[0];r&&(i.selectedClothingSetId=r)}else delete i.selectedClothingSetId}),setEditMode:n=>e(i=>{i.editMode=n}),createInstanceFromTemplate:(n,i)=>{const o=s().templates.get(n);if(!o)return;const r=`npc-${Date.now()}`,a=s().selectedClothingSetId||o.defaultClothingSet,l=[],c=s().previewAccessories.hat;if(c){const m=s().clothingSets.get(c)?.parts[0];m&&l.push(m)}const d=s().previewAccessories.glasses;if(d){const m=s().clothingSets.get(d)?.parts[0];m&&l.push(m)}const g={id:r,templateId:n,name:`${o.name} ${Date.now()}`,position:i,rotation:[0,0,0],scale:[1,1,1],...o.defaultAnimation?{currentAnimation:o.defaultAnimation}:{},...a?{currentClothingSetId:a}:{},...l.length>0?{customParts:l}:{},events:[]};s().addInstance(g),s().setSelectedInstance(r)},updateInstancePart:(n,i,o)=>e(r=>{const a=r.instances.get(n);if(!a)return;const l=a.customParts||[],c=l.findIndex(d=>d.id===i);if(c>=0){const d=l[c];l[c]={...d,...o,id:d.id,type:d.type,url:d.url}}else{const d=o.type??"accessory",g=o.url??"";l.push({id:i,type:d,url:g,...o.category!==void 0?{category:o.category}:{},...o.position!==void 0?{position:o.position}:{},...o.rotation!==void 0?{rotation:o.rotation}:{},...o.scale!==void 0?{scale:o.scale}:{},...o.color!==void 0?{color:o.color}:{},...o.metadata!==void 0?{metadata:o.metadata}:{}})}r.instances.set(n,{...a,customParts:l})}),changeInstanceClothing:(n,i)=>e(o=>{const r=o.instances.get(n);r&&o.instances.set(n,{...r,currentClothingSetId:i})}),addInstanceEvent:(n,i)=>e(o=>{const r=o.instances.get(n);if(r){const a=r.events||[];a.push(i),o.instances.set(n,{...r,events:a})}}),removeInstanceEvent:(n,i)=>e(o=>{const r=o.instances.get(n);if(r&&r.events){const a=r.events.filter(l=>l.id!==i);o.instances.set(n,{...r,events:a})}}),setPreviewAccessory:(n,i)=>e(o=>{i?o.previewAccessories[n]=i:delete o.previewAccessories[n]}),setNavigation:(n,i,o=3)=>e(r=>{const a=r.instances.get(n);if(!a||i.length===0)return;const l={waypoints:i,currentIndex:0,speed:o,state:"moving"};r.instances.set(n,{...a,navigation:l,currentAnimation:"walk"})}),advanceNavigation:n=>e(i=>{const o=i.instances.get(n);if(!o?.navigation||o.navigation.state!=="moving")return;const r=o.navigation,a=r.currentIndex+1;a>=r.waypoints.length?i.instances.set(n,{...o,navigation:{...r,state:"arrived",currentIndex:a},currentAnimation:"idle"}):i.instances.set(n,{...o,navigation:{...r,currentIndex:a}})}),clearNavigation:n=>e(i=>{const o=i.instances.get(n);if(!o)return;const r={...o,currentAnimation:"idle"};delete r.navigation,i.instances.set(n,r)}),updateNavigationPosition:(n,i)=>e(o=>{const r=o.instances.get(n);r&&o.instances.set(n,{...r,position:i})})})));function qr({part:e}){return t.jsxs("mesh",{position:e.position||[0,0,0],rotation:e.rotation||[0,0,0],scale:e.scale||[1,1,1],children:[t.jsx("boxGeometry",{args:[.5,1.8,.5]}),t.jsx("meshStandardMaterial",{color:"royalblue",transparent:!0,opacity:.7})]})}function Kr(){const e=S.useBuildingStore(d=>d.editMode),s=S.useBuildingStore(d=>d.hoverPosition),n=oe(d=>d.templates),i=oe(d=>d.clothingSets),o=oe(d=>d.selectedTemplateId),r=oe(d=>d.selectedClothingSetId),a=oe(d=>d.previewAccessories);if(e!=="npc"||!s||!o)return null;const l=n.get(o);if(!l)return null;const c=[];if(c.push(...l.baseParts),r){const d=i.get(r);d&&c.push(...d.parts)}if(a.hat){const d=i.get(a.hat);if(d&&d.parts.length>0){const g=d.parts[0];g&&c.push(g)}}if(a.glasses){const d=i.get(a.glasses);if(d&&d.parts.length>0){const g=d.parts[0];g&&c.push(g)}}return t.jsxs("group",{position:[s.x,s.y,s.z],children:[c.map(d=>t.jsx(qr,{part:d},d.id)),t.jsxs("mesh",{position:[0,.01,0],rotation:[-Math.PI/2,0,0],children:[t.jsx("circleGeometry",{args:[1,32]}),t.jsx("meshStandardMaterial",{color:"#00ff00",transparent:!0,opacity:.3,emissive:"#00ff00",emissiveIntensity:.3})]})]})}const Ue=new Set,_e=rt.create(e=>({active:!1,version:0,visibleTileGroupIds:Ue,visibleWallGroupIds:Ue,visibleBlockIds:Ue,visibleObjectIds:Ue,clusterCounts:new Uint32Array(0),setResult:({version:s,tileIds:n,wallIds:i,blockIds:o,objectIds:r,clusterCounts:a})=>e({active:!0,version:s,visibleTileGroupIds:n,visibleWallGroupIds:i,visibleBlockIds:o??Ue,visibleObjectIds:r,clusterCounts:a}),reset:()=>e({active:!1,version:0,visibleTileGroupIds:Ue,visibleWallGroupIds:Ue,visibleBlockIds:Ue,visibleObjectIds:Ue,clusterCounts:new Uint32Array(0)})})),ze=18,Le=140,Jr=.12,Qr=8,ea=3.2,Ws=2.4,ta=.985;function Ke(e,s){return Math.floor(e/s)}function Mi(e,s){return`${e}:${s}`}function na(e,s,n,i,o=ze,r=Qr){const a=Ke(e,o),l=Ke(s,o),c=Math.atan2(i,n),d=c<0?c+Math.PI*2:c,g=Math.floor(d/(Math.PI*2)*r)%r;return`${a}:${l}:${g}`}function un(e,s,n,i=ze){const o=Math.max(0,Math.ceil(s.radius/i));for(let r=s.cellZ-o;r<=s.cellZ+o;r+=1)for(let a=s.cellX-o;a<=s.cellX+o;a+=1)sa(e,a,r,n)}function Jt(e,s,n=ze){un(e,s,s.id,n)}function sa(e,s,n,i){const o=Mi(s,n),r=e.get(o);if(r){r.push(i);return}e.set(o,[i])}function vs(e,s,n,i,o,r,a,l){const c=(s+n)*.5,d=(i+o)*.5,g=(r+a)*.5,p=n-s,m=o-i,f=a-r;return{id:e,centerX:c,centerY:d,centerZ:g,radius:Math.max(1,Math.hypot(p,m,f)*.5),cellX:Ke(c,l),cellZ:Ke(g,l)}}function ji(e,s=ze){if(e.tiles.length===0)return null;let n=1/0,i=-1/0,o=0,r=.2,a=1/0,l=-1/0;for(const c of e.tiles){const g=(c.size??1)*.5;n=Math.min(n,c.position.x-g),i=Math.max(i,c.position.x+g),o=Math.min(o,0),r=Math.max(r,Math.max(c.position.y,.2)+1.5),a=Math.min(a,c.position.z-g),l=Math.max(l,c.position.z+g)}return vs(e.id,n,i,o,r,a,l,s)}function wi(e,s=ze){if(e.walls.length===0)return null;let n=1/0,i=-1/0,o=0,r=2.5,a=1/0,l=-1/0;for(const c of e.walls)n=Math.min(n,c.position.x-1.1),i=Math.max(i,c.position.x+1.1),o=Math.min(o,c.position.y),r=Math.max(r,c.position.y+3.5),a=Math.min(a,c.position.z-1.1),l=Math.max(l,c.position.z+1.1);return vs(e.id,n,i,o,r,a,l,s)}function _i(e,s=ze){const n=Math.max(1,Math.round(e.size?.x??1))*S.TILE_CONSTANTS.GRID_CELL_SIZE,i=Math.max(1,Math.round(e.size?.y??1))*S.TILE_CONSTANTS.HEIGHT_STEP,o=Math.max(1,Math.round(e.size?.z??1))*S.TILE_CONSTANTS.GRID_CELL_SIZE,r=S.TILE_CONSTANTS.GRID_CELL_SIZE*.5;return vs(e.id,e.position.x-r,e.position.x-r+n,e.position.y,e.position.y+i,e.position.z-r,e.position.z-r+o,s)}function ia(e){const s=e.config?.size??1;switch(e.type){case"sakura":return Math.max(2.2,s*.8);case"flag":return Math.max(1.4,(e.config?.flagWidth??1.5)*.8);case"fire":return Math.max(1.2,e.config?.fireWidth??1);case"billboard":return 1.8;default:return 1.5}}function Ci(e,s=ze){const n=ia(e);return{id:e.id,centerX:e.position.x,centerY:e.position.y+n*.5,centerZ:e.position.z,radius:n,cellX:Ke(e.position.x,s),cellZ:Ke(e.position.z,s)}}function oa(e,s,n,i=[],o=ze){const r=Array.isArray(i)?i:[],a=typeof i=="number"?i:o,l={tileById:new Map,wallById:new Map,blockById:new Map,objectById:new Map,tileBuckets:new Map,wallBuckets:new Map,blockBuckets:new Map,objectBuckets:new Map,occluderByKey:new Map,occluderBuckets:new Map};for(const c of s){const d=ji(c,a);if(d&&(l.tileById.set(d.id,d),Jt(l.tileBuckets,d,a),d.radius>=ea)){const g={...d,key:`tile:${d.id}`,kind:"tile",strength:d.radius};l.occluderByKey.set(g.key,g),un(l.occluderBuckets,g,g.key,a)}}for(const c of e){const d=wi(c,a);if(d&&(l.wallById.set(d.id,d),Jt(l.wallBuckets,d,a),d.radius>=Ws||c.walls.length>=4)){const g={...d,key:`wall:${d.id}`,kind:"wall",strength:d.radius*1.15};l.occluderByKey.set(g.key,g),un(l.occluderBuckets,g,g.key,a)}}for(const c of r){const d=_i(c,a);if(l.blockById.set(d.id,d),Jt(l.blockBuckets,d,a),d.radius>=Ws||(c.size?.y??1)>=2){const g={...d,key:`block:${d.id}`,kind:"block",strength:d.radius*1.1};l.occluderByKey.set(g.key,g),un(l.occluderBuckets,g,g.key,a)}}for(const c of n){const d=Ci(c,a);l.objectById.set(d.id,d),Jt(l.objectBuckets,d,a)}return l}function Bt(e,s,n,i=Le,o=ze){const r=Ke(s,o),a=Ke(n,o),l=Math.ceil(i/o),c=new Set;for(let d=a-l;d<=a+l;d+=1)for(let g=r-l;g<=r+l;g+=1){const p=e.get(Mi(g,d));if(p)for(const m of p)c.add(m)}return c}function ra(e,s,n,i=Le,o=ze){const r=Bt(e.occluderBuckets,s,n,i,o),a=[];for(const l of r){const c=e.occluderByKey.get(l);c&&a.push(c)}return a}function aa(e,s,n,i,o){const r=e.centerX-n.x,a=e.centerY-n.y,l=e.centerZ-n.z,c=Math.sqrt(r*r+a*a+l*l);if(c<10)return!1;o.targetDir.set(r,a,l).normalize();for(const d of i){if(d.kind===s&&d.id===e.id)continue;const g=d.centerX-n.x,p=d.centerY-n.y,m=d.centerZ-n.z,f=Math.sqrt(g*g+p*p+m*m);if(f<=1||f>=c-Math.max(e.radius,1.2)||(o.occDir.set(g,p,m).normalize(),o.targetDir.dot(o.occDir)<ta))continue;const M=o.cross.crossVectors(o.targetDir,o.occDir).length()*f,_=d.strength+Math.min(e.radius*.45,1.8);if(!(M>_))return!0}return!1}const ys=0,Ss=1,Ms=2,js=3,la=0,Ti=1,Ni=2,Ii=3,Ai=4,ca=10,Bi=20,Ei=21,cs=22,ki=23,Ri=24,ua=30;function Pi(){return{version:0,ids:[],kinds:new Uint8Array(0),subKinds:new Uint8Array(0),centerX:new Float32Array(0),centerY:new Float32Array(0),centerZ:new Float32Array(0),radius:new Float32Array(0),cellX:new Int16Array(0),cellZ:new Int16Array(0),memberCount:new Uint16Array(0)}}function da(e,s,n,i){let o=n.length+i.length;for(const r of e)r.walls.length>0&&(o+=1);for(const r of s)r.tiles.length>0&&(o+=1);return o}function pa(e){const s=e.blocks??[],n=da(e.wallGroups,e.tileGroups,e.objects,s);if(n===0)return{...Pi(),version:e.version};const i=new Array(n),o=new Uint8Array(n),r=new Uint8Array(n),a=new Float32Array(n),l=new Float32Array(n),c=new Float32Array(n),d=new Float32Array(n),g=new Int16Array(n),p=new Int16Array(n),m=new Uint16Array(n);let f=0;const y=(M,_,j,A,w)=>{i[f]=M,o[f]=_,r[f]=j,a[f]=A.centerX,l[f]=A.centerY,c[f]=A.centerZ,d[f]=A.radius,g[f]=A.cellX,p[f]=A.cellZ,m[f]=w,f+=1};for(const M of e.tileGroups){const _=ji(M);if(!_)continue;const j=M.tiles.find(w=>w.objectType&&w.objectType!=="none")?.objectType??"none",A=j==="grass"?Ti:j==="water"?Ni:j==="sand"?Ii:j==="snowfield"?Ai:la;y(M.id,ys,A,_,M.tiles.length)}for(const M of e.wallGroups){const _=wi(M);_&&y(M.id,Ss,ca,_,M.walls.length)}for(const M of s)y(M.id,js,ua,_i(M),1);for(const M of e.objects){const _=M.type==="sakura"?Bi:M.type==="flag"?Ei:M.type==="fire"?cs:M.type==="billboard"?ki:M.type==="model"?Ri:cs;y(M.id,Ms,_,Ci(M),1)}return{version:e.version,ids:i,kinds:o,subKinds:r,centerX:a,centerY:l,centerZ:c,radius:d,cellX:g,cellZ:p,memberCount:m}}const mt=0,ws=1,ft=2,ht=3,gt=4,yn=5,Sn=6,Mn=7,jn=8,wn=9,_n=10,Cn=11,Tn=12;function Di(e,s){const n=e.kinds[s],i=e.subKinds[s];if(n===ys)return i===Ti?ws:i===Ni?ft:i===Ii?ht:i===Ai?gt:mt;if(n===Ss)return yn;if(n===js)return _n;if(n===Ms){if(i===Bi)return Sn;if(i===Ei)return Mn;if(i===cs)return jn;if(i===ki)return wn;if(i===Ri)return Cn}return mt}function Fi(e,s){const n=new Set,i=new Set,o=new Set,r=new Set,a=new Uint32Array(Tn),l=Math.min(e.ids.length,s.length);for(let c=0;c<l;c+=1){if((s[c]??0)===0)continue;const d=e.ids[c];if(!d)continue;const g=e.kinds[c];g===ys?n.add(d):g===Ss?i.add(d):g===js?o.add(d):g===Ms&&r.add(d);const p=Di(e,c);a[p]=(a[p]??0)+1}return{version:e.version,tileIds:n,wallIds:i,blockIds:o,objectIds:r,clusterCounts:a}}const ke=4;function Ne(e,s){const n=s*ke;return e.args[n+1]??0}const Li=[{id:mt,label:"tile",vertexCountHint:36},{id:ws,label:"grass",vertexCountHint:36},{id:ft,label:"water",vertexCountHint:36},{id:ht,label:"sand",vertexCountHint:36},{id:gt,label:"snowfield",vertexCountHint:36},{id:yn,label:"wall",vertexCountHint:36},{id:Sn,label:"sakura",vertexCountHint:12},{id:Mn,label:"flag",vertexCountHint:12},{id:jn,label:"fire",vertexCountHint:6},{id:wn,label:"billboard",vertexCountHint:6},{id:_n,label:"block",vertexCountHint:36},{id:Cn,label:"model",vertexCountHint:36}];function _s(){return{version:0,args:new Uint32Array(Tn*ke),dirtyRanges:[]}}function ma(e,s){if(e.length!==s.length)return s.length>0?[{start:0,end:s.length/ke}]:[];const n=[];let i=-1;const o=s.length/ke;for(let r=0;r<o;r+=1){const a=r*ke;let l=!1;for(let c=0;c<ke;c+=1)if((e[a+c]??0)!==(s[a+c]??0)){l=!0;break}if(l){i<0&&(i=r);continue}i>=0&&(n.push({start:i,end:r}),i=-1)}return i>=0&&n.push({start:i,end:o}),n}function Gi(e,s,n){const i=new Uint32Array(Tn*ke);for(const r of Li){const a=r.id*ke;i[a]=r.vertexCountHint,i[a+1]=s[r.id]??0,i[a+2]=0,i[a+3]=0}const o=n??_s();return{version:e,args:i,dirtyRanges:ma(o.args,i)}}function zi(e){return{version:e.version,slices:e.dirtyRanges.map(s=>{const n=s.start*ke,i=(s.end-s.start)*ke;return{byteOffset:n*e.args.BYTES_PER_ELEMENT,elementOffset:n,elementCount:i,data:e.args.subarray(n,n+i)}})}}const Ft=4,Lt=5;function Cs(){return{version:0,count:0,spatial:new Float32Array(0),meta:new Int32Array(0),spatialDirty:[],metaDirty:[]}}function fa(e){const s=new Float32Array(e.ids.length*Ft);for(let n=0;n<e.ids.length;n+=1){const i=n*Ft;s[i]=e.centerX[n]??0,s[i+1]=e.centerY[n]??0,s[i+2]=e.centerZ[n]??0,s[i+3]=e.radius[n]??0}return s}function ha(e){const s=new Int32Array(e.ids.length*Lt);for(let n=0;n<e.ids.length;n+=1){const i=n*Lt;s[i]=e.cellX[n]??0,s[i+1]=e.cellZ[n]??0,s[i+2]=e.kinds[n]??0,s[i+3]=e.subKinds[n]??0,s[i+4]=e.memberCount[n]??0}return s}function Hs(e,s,n){if(e.length!==s.length)return s.length>0?[{start:0,end:Math.ceil(s.length/n)}]:[];const i=[];let o=-1;const r=Math.ceil(s.length/n);for(let a=0;a<r;a+=1){const l=a*n;let c=!1;for(let d=0;d<n;d+=1)if((e[l+d]??0)!==(s[l+d]??0)){c=!0;break}if(c){o<0&&(o=a);continue}o>=0&&(i.push({start:o,end:a}),o=-1)}return o>=0&&i.push({start:o,end:r}),i}function Oi(e,s){const n=fa(e),i=ha(e),o=s??Cs();return{version:e.version,count:e.ids.length,spatial:n,meta:i,spatialDirty:Hs(o.spatial,n,Ft),metaDirty:Hs(o.meta,i,Lt)}}function $s(e,s,n){return n.map(i=>{const o=i.start*s,r=(i.end-i.start)*s;return{byteOffset:o*e.BYTES_PER_ELEMENT,elementOffset:o,elementCount:r,data:e.subarray(o,o+r)}})}function Ui(e){return{version:e.version,count:e.count,spatial:$s(e.spatial,Ft,e.spatialDirty),meta:$s(e.meta,Lt,e.metaDirty)}}const ga=8,ba=128;function Gt(){return{backend:"none",uploadedVersion:0,spatialBuffer:null,metaBuffer:null,indirectArgsBuffer:null,spatialBytes:0,metaBytes:0,indirectArgsBytes:0}}function Nn(e){if(typeof e!="object"||e===null)return null;const s=e,n=s.backend?.device??s.device??null;return!n||typeof n.createBuffer!="function"||typeof n.queue?.writeBuffer!="function"?null:n}function kt(e){e?.destroy&&e.destroy()}function Wi(e){kt(e.spatialBuffer),kt(e.metaBuffer),kt(e.indirectArgsBuffer)}function us(e,s,n,i,o){return i<=0?(kt(s),null):s&&n===i?s:(kt(s),e.createBuffer({label:o,size:i,usage:ba|ga}))}function Hi(e,s,n){const i=Ui(n),o=n.spatial.byteLength,r=n.meta.byteLength,a=us(e,s.spatialBuffer,s.spatialBytes,o,"building-spatial"),l=us(e,s.metaBuffer,s.metaBytes,r,"building-meta");if(a)for(const c of i.spatial)e.queue.writeBuffer(a,c.byteOffset,c.data);if(l)for(const c of i.meta)e.queue.writeBuffer(l,c.byteOffset,c.data);return{backend:"webgpu",uploadedVersion:n.version,spatialBuffer:a,metaBuffer:l,indirectArgsBuffer:s.indirectArgsBuffer,spatialBytes:o,metaBytes:r,indirectArgsBytes:s.indirectArgsBytes}}function $i(e,s,n){const i=zi(n),o=n.args.byteLength,r=us(e,s.indirectArgsBuffer,s.indirectArgsBytes,o,"building-indirect-args");if(r)for(const a of i.slices)e.queue.writeBuffer(r,a.byteOffset,a.data);return{...s,backend:"webgpu",uploadedVersion:Math.max(s.uploadedVersion,n.version),indirectArgsBuffer:r,indirectArgsBytes:o}}const Zs=Pi(),Vs=Cs(),Ys=Gt(),Xs=_s(),ge=rt.create(e=>({snapshot:Zs,gpuMirror:Vs,uploadResources:Ys,drawMirror:Xs,setSnapshot:s=>e({snapshot:s}),setGpuMirror:s=>e({gpuMirror:s}),setUploadResources:s=>e({uploadResources:s}),setDrawMirror:s=>e({drawMirror:s}),reset:()=>e({snapshot:Zs,gpuMirror:Vs,uploadResources:Ys,drawMirror:Xs})}));function Qt(e,s){if(e===s)return!0;if(e.size!==s.size)return!1;for(const n of e)if(!s.has(n))return!1;return!0}const We=new Set,Ze=rt.create(e=>({initialized:!1,visibleTileGroupIds:We,visibleWallGroupIds:We,visibleBlockIds:We,visibleObjectIds:We,setVisible:({tileIds:s,wallIds:n,blockIds:i,objectIds:o})=>e(r=>{const a=!Qt(r.visibleTileGroupIds,s),l=!Qt(r.visibleWallGroupIds,n),c=i??We,d=!Qt(r.visibleBlockIds,c),g=!Qt(r.visibleObjectIds,o);return!a&&!l&&!d&&!g&&r.initialized?r:{initialized:!0,visibleTileGroupIds:a?s:r.visibleTileGroupIds,visibleWallGroupIds:l?n:r.visibleWallGroupIds,visibleBlockIds:d?c:r.visibleBlockIds,visibleObjectIds:g?o:r.visibleObjectIds}}),reset:()=>e({initialized:!1,visibleTileGroupIds:We,visibleWallGroupIds:We,visibleBlockIds:We,visibleObjectIds:We})}));var xa=Object.defineProperty,va=Object.getOwnPropertyDescriptor,Ut=(e,s,n,i)=>{for(var o=va(s,n),r=e.length-1,a;r>=0;r--)(a=e[r])&&(o=a(s,n,o)||o);return o&&xa(s,n,o),o};class Je{materials=new Map;textures=new Map;textureLoader;constructor(){this.textureLoader=new b.TextureLoader}getMaterial(s){const n=this.createMaterialKey(s),i=this.materials.get(n);if(i)return i;const o=this.createMaterial(s);return this.materials.set(n,o),o}createMaterialKey(s){return[s.id,s.assetId??"",s.color??s.materialParams?.color??"",s.material??"",s.textureUrl??"",s.mapTextureUrl??s.materialParams?.mapTextureUrl??"",s.normalTextureUrl??s.materialParams?.normalTextureUrl??"",s.roughness??s.materialParams?.roughness??"",s.metalness??s.materialParams?.metalness??"",s.opacity??s.materialParams?.opacity??"",s.transparent??s.materialParams?.transparent??""].join("|")}createMaterial(s){const n=s.color??s.materialParams?.color??"#ffffff",i=s.roughness??s.materialParams?.roughness??.5,o=s.metalness??s.materialParams?.metalness??0,r=s.opacity??s.materialParams?.opacity??1,a=s.transparent??s.materialParams?.transparent??!1,l=s.mapTextureUrl??s.textureUrl??s.materialParams?.mapTextureUrl,c=s.normalTextureUrl??s.materialParams?.normalTextureUrl,d={color:n,roughness:i,metalness:o,opacity:r,transparent:a};if(S.getDefaultToonMode()){const g=s.material==="GLASS",p=new b.MeshToonMaterial({color:n,opacity:g?.45:r,transparent:g?!0:a,gradientMap:S.getToonGradient(g?2:4)});return l&&(p.map=this.loadTexture(l)),c&&(p.normalMap=this.loadTexture(c)),p}return s.material==="GLASS"?new b.MeshPhysicalMaterial({...d,transmission:.98,roughness:.1,envMapIntensity:1}):(l&&(d.map=this.loadTexture(l)),c&&(d.normalMap=this.loadTexture(c)),new b.MeshStandardMaterial(d))}loadTexture(s){const n=this.textures.get(s);if(n)return n;const i=this.textureLoader.load(s);return i.wrapS=b.RepeatWrapping,i.wrapT=b.RepeatWrapping,i.needsUpdate=!0,this.textures.set(s,i),i}updateMaterial(s,n){const i=this.materials.get(s);i&&(i instanceof b.MeshStandardMaterial?(n.color&&i.color.set(n.color),n.roughness!==void 0&&(i.roughness=n.roughness),n.metalness!==void 0&&(i.metalness=n.metalness),n.opacity!==void 0&&(i.opacity=n.opacity),i.needsUpdate=!0):i instanceof b.MeshToonMaterial&&(n.color&&i.color.set(n.color),n.opacity!==void 0&&(i.opacity=n.opacity),i.needsUpdate=!0))}dispose(){this.materials.forEach(s=>s.dispose()),this.materials.clear(),this.textures.forEach(s=>s.dispose()),this.textures.clear()}}Ut([re.HandleError(),re.Profile()],Je.prototype,"getMaterial");Ut([re.HandleError(),re.Profile()],Je.prototype,"createMaterial");Ut([re.HandleError(),re.MonitorMemory(20)],Je.prototype,"loadTexture");Ut([re.HandleError(),re.Profile()],Je.prototype,"updateMaterial");Ut([re.HandleError()],Je.prototype,"dispose");const qs={id:"default-block",color:"#8b8174",material:"STANDARD",roughness:.92};function ya(e){return{width:Math.max(1,Math.round(e.size?.x??1))*S.TILE_CONSTANTS.GRID_CELL_SIZE,height:Math.max(1,Math.round(e.size?.y??1))*S.TILE_CONSTANTS.HEIGHT_STEP,depth:Math.max(1,Math.round(e.size?.z??1))*S.TILE_CONSTANTS.GRID_CELL_SIZE}}function ds(e){const{width:s,height:n,depth:i}=ya(e);return{position:[e.position.x-S.TILE_CONSTANTS.GRID_CELL_SIZE*.5+s*.5,e.position.y+n*.5,e.position.z-S.TILE_CONSTANTS.GRID_CELL_SIZE*.5+i*.5],scale:[s,n,i]}}function Zi({blocks:e,meshes:s,isEditMode:n=!1,selectedBlockId:i=null,onBlockClick:o}){const r=u.useRef(new Je),a=u.useMemo(()=>new b.Object3D,[]),l=u.useMemo(()=>new b.BoxGeometry(1,1,1),[]),c=u.useMemo(()=>new b.MeshStandardMaterial({color:"#60a5fa",transparent:!0,opacity:.16,emissive:new b.Color("#2563eb"),emissiveIntensity:.08,wireframe:!0,depthWrite:!1}),[]),d=u.useMemo(()=>new b.MeshStandardMaterial({color:"#bae6fd",transparent:!0,opacity:.28,emissive:new b.Color("#60a5fa"),emissiveIntensity:.2,wireframe:!0,depthWrite:!1}),[]),g=u.useMemo(()=>{const p=new Map;for(const f of e){const y=f.materialId??qs.id,M=p.get(y)??[];M.push(f),p.set(y,M)}const m=r.current;return Array.from(p.entries()).map(([f,y])=>({key:f,blocks:y,material:m.getMaterial(s.get(f)??{...qs,id:f})}))},[e,s]);return u.useEffect(()=>()=>{r.current.dispose(),l.dispose(),c.dispose(),d.dispose()},[c,l,d]),t.jsxs(t.Fragment,{children:[!n&&e.length>0&&t.jsx(ot.RigidBody,{type:"fixed",colliders:!1,children:e.map(p=>{const m=ds(p);return t.jsx(ot.CuboidCollider,{position:m.position,args:[m.scale[0]*.5,m.scale[1]*.5,m.scale[2]*.5]},p.id)})}),g.map(p=>t.jsx(Sa,{batch:p,geometry:l,dummy:a},p.key)),n&&e.map(p=>{const m=ds(p),f=p.id===i;return t.jsx("mesh",{name:`block-edit-${p.id}`,position:m.position,scale:[m.scale[0]*.82,m.scale[1]*.82,m.scale[2]*.82],geometry:l,material:f?d:c,onClick:()=>o?.(p.id)},`${p.id}-edit`)})]})}function Sa({batch:e,geometry:s,dummy:n}){const i=u.useRef(null);return u.useLayoutEffect(()=>{const o=i.current;if(o){o.count=e.blocks.length;for(let r=0;r<e.blocks.length;r+=1){const a=e.blocks[r];if(!a)continue;const l=ds(a);n.position.set(...l.position),n.scale.set(...l.scale),n.rotation.set(0,0,0),n.updateMatrix(),o.setMatrixAt(r,n.matrix)}o.instanceMatrix.needsUpdate=!0,e.blocks.length>0&&(o.computeBoundingBox(),o.computeBoundingSphere())}},[e.blocks,n]),t.jsx("instancedMesh",{ref:i,name:`block-system-${e.key}`,args:[s,e.material,Math.max(1,e.blocks.length)],castShadow:!0,receiveShadow:!0})}function Vi({size:e=S.TILE_CONSTANTS.DEFAULT_GRID_SIZE,divisions:s=e/S.TILE_CONSTANTS.GRID_CELL_SIZE,color1:n="#888888",color2:i="#444444"}){return t.jsx("gridHelper",{args:[e,s,n,i],position:[0,.01,0]})}function Ma(e,s,n,i){const o=document.createElement("canvas"),r=512,a=Math.round(r*(n/s));o.width=r,o.height=a;const l=o.getContext("2d");l.fillStyle="#0a0a0a",l.fillRect(0,0,r,a),l.strokeStyle="#333",l.lineWidth=4,l.strokeRect(2,2,r-4,a-4),l.fillStyle=i;const c=Math.floor(a*.25);l.font=`bold ${c}px monospace`,l.textAlign="center",l.textBaseline="middle";const d=e.split(`
|
|
2
|
+
`),g=c*1.3,p=a/2-(d.length-1)*g/2;d.forEach((f,y)=>{l.fillText(f,r/2,p+y*g,r-20)});const m=new b.CanvasTexture(o);return m.needsUpdate=!0,m}const Yi=20,Xi=100,qi=3;function ja({imageUrl:e,width:s,height:n,color:i,toon:o}){const r=u.useRef(null),a=u.useRef(null),l=u.useRef(null),c=u.useMemo(()=>new b.Vector3,[]),g=o??S.getDefaultToonMode()?S.getToonGradient(3):null,p=Ge.useTexture(e),m=s??2,f=n??1.5,y=u.useMemo(()=>new b.Color(i||"#00ff88"),[i]),M=u.useMemo(()=>new b.PlaneGeometry(m,f),[m,f]),_=u.useMemo(()=>new b.PlaneGeometry(m*1.15,f*1.15),[m,f]);return ae.useFrame(j=>{r.current.getWorldPosition(c);const A=j.camera.position.distanceTo(c),w=Ot.weightFromDistance(A,Yi,Xi,qi);a.current.emissiveIntensity=2*w,l.current.opacity=(.2+.05*Math.sin(j.clock.elapsedTime*2))*w}),u.useEffect(()=>()=>{M.dispose(),_.dispose()},[M,_]),t.jsxs("group",{position:[0,f/2+1,0],children:[t.jsx("mesh",{geometry:_,position:[0,0,-.01],children:t.jsx("meshBasicMaterial",{ref:l,color:y,transparent:!0,opacity:.25,blending:b.AdditiveBlending,depthWrite:!1,side:b.DoubleSide})}),t.jsx("mesh",{ref:r,geometry:M,children:g?t.jsx("meshToonMaterial",{ref:a,map:p,emissive:y,emissiveIntensity:2,gradientMap:g,side:b.DoubleSide}):t.jsx("meshStandardMaterial",{ref:a,map:p,emissive:y,emissiveIntensity:2,side:b.DoubleSide})})]})}function wa({text:e,width:s,height:n,color:i,toon:o}){const r=u.useRef(null),a=u.useRef(null),l=u.useRef(null),c=u.useMemo(()=>new b.Vector3,[]),g=o??S.getDefaultToonMode()?S.getToonGradient(3):null,p=s??2,m=n??1.5,f=i||"#00ff88",y=u.useMemo(()=>Ma(e||"HELLO",p,m,f),[e,p,m,f]),M=u.useMemo(()=>new b.Color(f),[f]),_=u.useMemo(()=>new b.PlaneGeometry(p,m),[p,m]),j=u.useMemo(()=>new b.PlaneGeometry(p*1.15,m*1.15),[p,m]);return ae.useFrame(A=>{r.current.getWorldPosition(c);const w=A.camera.position.distanceTo(c),x=Ot.weightFromDistance(w,Yi,Xi,qi);a.current.emissiveIntensity=2*x,l.current.opacity=(.2+.05*Math.sin(A.clock.elapsedTime*2))*x}),u.useEffect(()=>()=>{_.dispose(),j.dispose(),y.dispose()},[_,j,y]),t.jsxs("group",{position:[0,m/2+1,0],children:[t.jsx("mesh",{geometry:j,position:[0,0,-.01],children:t.jsx("meshBasicMaterial",{ref:l,color:M,transparent:!0,opacity:.25,blending:b.AdditiveBlending,depthWrite:!1,side:b.DoubleSide})}),t.jsx("mesh",{ref:r,geometry:_,children:g?t.jsx("meshToonMaterial",{ref:a,map:y,emissive:M,emissiveIntensity:2,gradientMap:g,side:b.DoubleSide}):t.jsx("meshStandardMaterial",{ref:a,map:y,emissive:M,emissiveIntensity:2,side:b.DoubleSide})})]})}const _a=e=>e.imageUrl?t.jsx(ja,{...e,imageUrl:e.imageUrl}):t.jsx(wa,{...e}),Ki=u.memo(_a);var Ca=`varying vec2 vUv;
|
|
3
|
+
uniform float time;
|
|
4
|
+
uniform float intensity;
|
|
5
|
+
uniform float seed;
|
|
6
|
+
uniform float lean;
|
|
7
|
+
uniform float flare;
|
|
8
|
+
uniform vec3 tint;
|
|
9
|
+
|
|
10
|
+
float hash(vec2 p) {
|
|
11
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
float noise(vec2 p) {
|
|
15
|
+
vec2 i = floor(p);
|
|
16
|
+
vec2 f = fract(p);
|
|
17
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
18
|
+
return mix(
|
|
19
|
+
mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x),
|
|
20
|
+
mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x),
|
|
21
|
+
f.y
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
float fbm(vec2 p) {
|
|
26
|
+
float v = 0.0, a = 0.5;
|
|
27
|
+
for (int i = 0; i < 3; i++) {
|
|
28
|
+
v += a * noise(p);
|
|
29
|
+
p = p * 2.1 + vec2(100.0);
|
|
30
|
+
a *= 0.5;
|
|
31
|
+
}
|
|
32
|
+
return v;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void main() {
|
|
36
|
+
vec2 uv = vUv;
|
|
37
|
+
|
|
38
|
+
vec2 q = vec2(
|
|
39
|
+
fbm(vec2(uv.x * 4.2 + seed * 5.1, uv.y * 5.8 - time * 1.5)),
|
|
40
|
+
fbm(vec2(uv.x * 3.6 - seed * 3.3, uv.y * 4.6 + time * 0.6))
|
|
41
|
+
);
|
|
42
|
+
float n1 = fbm(uv * vec2(3.8, 5.6) + q * 1.5 + vec2(seed * 2.0, -time * 1.1));
|
|
43
|
+
float n2 = noise(vec2(uv.y * 9.0 + seed * 11.0, time * 4.7 + seed * 17.0));
|
|
44
|
+
|
|
45
|
+
float skew = lean * pow(uv.y, 1.2);
|
|
46
|
+
float sway = (n1 - 0.5) * 0.28 * (1.0 - uv.y * 0.35);
|
|
47
|
+
float x = (uv.x - 0.5) - skew + sway;
|
|
48
|
+
float w = mix(0.46 * flare, 0.02, pow(uv.y, 0.72));
|
|
49
|
+
|
|
50
|
+
float edgeTurb = q.x * 0.07 * uv.y;
|
|
51
|
+
float body = 1.0 - smoothstep(w - edgeTurb, w + 0.06, abs(x));
|
|
52
|
+
float tongue1 = 1.0 - smoothstep(w * 0.82, w * 0.82 + 0.06, abs(x + 0.12 + q.y * 0.08));
|
|
53
|
+
float tongue2 = 1.0 - smoothstep(w * 0.68, w * 0.68 + 0.07, abs(x - 0.1 + q.x * 0.06));
|
|
54
|
+
|
|
55
|
+
float baseGlow = 1.0 - smoothstep(0.1, 0.42, distance(uv, vec2(0.5 + skew * 0.1, 0.1)));
|
|
56
|
+
float plume = max(body, max(tongue1 * 0.82, tongue2 * 0.68));
|
|
57
|
+
|
|
58
|
+
float bite = smoothstep(0.55, 1.0, n1 + uv.y * 0.4);
|
|
59
|
+
plume *= mix(1.0, 0.72, bite * smoothstep(0.2, 0.85, uv.y));
|
|
60
|
+
plume *= 1.0 - smoothstep(0.8, 1.0, uv.y);
|
|
61
|
+
plume = smoothstep(0.14, 0.9, plume + baseGlow * 0.38 + n1 * 0.2);
|
|
62
|
+
|
|
63
|
+
float core = 1.0 - smoothstep(0.01, 0.14, abs(x));
|
|
64
|
+
float fire = clamp(plume * (0.85 + 0.15 * n2), 0.0, 1.0);
|
|
65
|
+
|
|
66
|
+
vec3 deepRed = vec3(0.35, 0.02, 0.0);
|
|
67
|
+
vec3 ember = vec3(0.65, 0.08, 0.01);
|
|
68
|
+
vec3 orange = vec3(1.0, 0.38, 0.04);
|
|
69
|
+
vec3 golden = vec3(1.0, 0.65, 0.18);
|
|
70
|
+
vec3 hot = vec3(1.0, 0.88, 0.55);
|
|
71
|
+
vec3 white = vec3(1.0, 0.97, 0.92);
|
|
72
|
+
|
|
73
|
+
vec3 color = mix(deepRed, ember, smoothstep(0.02, 0.15, fire));
|
|
74
|
+
color = mix(color, orange, smoothstep(0.12, 0.35, fire));
|
|
75
|
+
color = mix(color, golden, smoothstep(0.28, 0.52, fire));
|
|
76
|
+
color = mix(color, hot, smoothstep(0.45, 0.72, fire));
|
|
77
|
+
color = mix(color, white, smoothstep(0.62, 1.0, fire * core));
|
|
78
|
+
|
|
79
|
+
float trail = smoothstep(0.8, 1.0, n2 + n1 * 0.3)
|
|
80
|
+
* smoothstep(0.18, 0.7, uv.y)
|
|
81
|
+
* smoothstep(0.35, 0.0, abs(x));
|
|
82
|
+
color += trail * vec3(1.0, 0.4, 0.06) * 0.4;
|
|
83
|
+
|
|
84
|
+
float smokeY = smoothstep(0.75, 0.98, uv.y);
|
|
85
|
+
float smoke = smokeY * q.x * 0.22 * smoothstep(0.28, 0.0, abs(x));
|
|
86
|
+
color = mix(color, vec3(0.18, 0.14, 0.12), smoke);
|
|
87
|
+
|
|
88
|
+
float alpha = smoothstep(0.06, 0.35, fire) * min(1.0, 0.5 + intensity * 0.26);
|
|
89
|
+
alpha += trail * 0.15 + smoke * 0.3;
|
|
90
|
+
|
|
91
|
+
if (alpha < 0.01) discard;
|
|
92
|
+
|
|
93
|
+
gl_FragColor = vec4(color * tint * (0.62 + intensity * 0.48), alpha);
|
|
94
|
+
}`,Ta=`varying vec2 vUv;
|
|
95
|
+
uniform float seed;
|
|
96
|
+
uniform float lean;
|
|
97
|
+
uniform float time;
|
|
98
|
+
|
|
99
|
+
void main() {
|
|
100
|
+
vUv = uv;
|
|
101
|
+
|
|
102
|
+
vec3 right = vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]);
|
|
103
|
+
vec3 up = vec3(0.0, 1.0, 0.0);
|
|
104
|
+
float uy = clamp(uv.y, 0.0, 1.0);
|
|
105
|
+
|
|
106
|
+
float sway = sin(time * 0.7 + seed * 3.14) * 0.04 * uy;
|
|
107
|
+
float bend = lean * pow(uy, 1.35) * (0.35 + uy * 0.65);
|
|
108
|
+
float wobble = sin((uy * 6.0 + seed * 5.73) + position.y * 1.15) * 0.03 * uy;
|
|
109
|
+
float lift = sin(uv.x * 3.14159 + seed * 3.7) * 0.015 * uy;
|
|
110
|
+
|
|
111
|
+
vec3 billboarded = right * (position.x + bend + wobble + sway) + up * (position.y + lift);
|
|
112
|
+
|
|
113
|
+
vec4 center = modelMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
|
114
|
+
center.xyz += billboarded;
|
|
115
|
+
|
|
116
|
+
gl_Position = projectionMatrix * viewMatrix * center;
|
|
117
|
+
}`;const Na=Ge.shaderMaterial({time:0,intensity:1.5,seed:0,lean:0,flare:1,tint:new b.Color(1,1,1)},Ta,Ca);ae.extend({FireMaterial:Na});const Ia=`
|
|
118
|
+
attribute float aLife;
|
|
119
|
+
attribute float aSpeed;
|
|
120
|
+
attribute float aDrift;
|
|
121
|
+
varying float vAlpha;
|
|
122
|
+
varying float vHeat;
|
|
123
|
+
uniform float uTime;
|
|
124
|
+
|
|
125
|
+
void main() {
|
|
126
|
+
float t = fract(uTime * aSpeed + aLife);
|
|
127
|
+
vec3 pos = position;
|
|
128
|
+
float angle = t * 8.0 + aDrift;
|
|
129
|
+
float radius = 0.08 + t * 0.2;
|
|
130
|
+
pos.y += t * t * 3.2;
|
|
131
|
+
pos.x += sin(angle) * radius;
|
|
132
|
+
pos.z += cos(angle) * radius;
|
|
133
|
+
float flicker = 0.75 + 0.25 * sin(uTime * 14.0 + aDrift * 4.0);
|
|
134
|
+
vAlpha = (1.0 - t) * (1.0 - t) * 0.9 * flicker;
|
|
135
|
+
vHeat = 1.0 - t * 0.85;
|
|
136
|
+
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
|
|
137
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
138
|
+
gl_PointSize = mix(4.5, 0.6, t) * (220.0 / -mvPosition.z);
|
|
139
|
+
}
|
|
140
|
+
`,Ji=`
|
|
141
|
+
varying float vAlpha;
|
|
142
|
+
varying float vHeat;
|
|
143
|
+
|
|
144
|
+
void main() {
|
|
145
|
+
float d = length(gl_PointCoord - 0.5);
|
|
146
|
+
if (d > 0.5) discard;
|
|
147
|
+
float glow = smoothstep(0.5, 0.05, d);
|
|
148
|
+
vec3 red = vec3(0.75, 0.12, 0.02);
|
|
149
|
+
vec3 orange = vec3(1.0, 0.5, 0.08);
|
|
150
|
+
vec3 hot = vec3(1.0, 0.92, 0.65);
|
|
151
|
+
vec3 color = mix(red, orange, vHeat);
|
|
152
|
+
color = mix(color, hot, vHeat * vHeat);
|
|
153
|
+
gl_FragColor = vec4(color * glow * 1.4, vAlpha * glow);
|
|
154
|
+
}
|
|
155
|
+
`,wt=18;let On=null,Un=null;function Qi(){return On||(On={log:new b.CylinderGeometry(.035,.045,.5,5),charcoal:new b.CircleGeometry(.18,6),glow:new b.CircleGeometry(.7,8)}),On}function eo(){return Un||(Un={log:new b.MeshStandardMaterial({color:2759178,roughness:1}),charcoal:new b.MeshStandardMaterial({color:1118481,roughness:1,emissive:new b.Color("#3a0c00"),emissiveIntensity:.8}),ember:new b.ShaderMaterial({vertexShader:Ia,fragmentShader:Ji,uniforms:{uTime:{value:0}},transparent:!0,depthWrite:!1,blending:b.AdditiveBlending})}),Un}const Aa=({intensity:e=1.5,width:s=1,height:n=1.5,color:i="#ffffff"})=>{const o=u.useMemo(()=>new b.Color(i),[i]),r=Qi(),a=eo(),l=u.useMemo(()=>Math.max(.4,(s+n*.5)/1.5),[s,n]),c=u.useMemo(()=>[{w:s*.78,h:n,x:0,y:n*.5,z:0,seed:.17,lean:.06,flare:1,speed:1.45,tOff:0,iMul:1},{w:s*.52,h:n*.85,x:-s*.12,y:n*.43,z:.02,seed:1.31,lean:-.2,flare:.85,speed:1.9,tOff:1.7,iMul:.82},{w:s*.42,h:n*.7,x:s*.14,y:n*.36,z:-.02,seed:2.63,lean:.16,flare:.74,speed:2.2,tOff:3.4,iMul:.72}],[s,n]),d=u.useMemo(()=>c.map(()=>u.createRef()),[c]),g=u.useMemo(()=>c.map(m=>new b.PlaneGeometry(m.w,m.h)),[c]),p=u.useMemo(()=>{const m=new b.BufferGeometry,f=new Float32Array(wt*3),y=new Float32Array(wt),M=new Float32Array(wt),_=new Float32Array(wt);for(let j=0;j<wt;j++)f[j*3]=(Math.random()-.5)*s*.35,f[j*3+1]=Math.random()*n*.2,f[j*3+2]=(Math.random()-.5)*s*.35,y[j]=Math.random(),M[j]=.12+Math.random()*.22,_[j]=Math.random()*Math.PI*2;return m.setAttribute("position",new b.BufferAttribute(f,3)),m.setAttribute("aLife",new b.BufferAttribute(y,1)),m.setAttribute("aSpeed",new b.BufferAttribute(M,1)),m.setAttribute("aDrift",new b.BufferAttribute(_,1)),m},[s,n]);return ae.useFrame(m=>{const f=m.clock.elapsedTime;for(let M=0;M<c.length;M++){const _=d[M]?.current;if(!_)continue;const j=c[M];j&&(_.time=f*j.speed+j.tOff,_.intensity=e*j.iMul,_.seed=j.seed,_.lean=j.lean,_.flare=j.flare,_.tint=o)}const y=a.ember.uniforms.uTime;y&&(y.value=f)}),u.useEffect(()=>()=>{g.forEach(m=>m.dispose()),p.dispose()},[g,p]),t.jsxs("group",{children:[t.jsx("mesh",{geometry:r.glow,rotation:[-Math.PI/2,0,0],position:[0,.02,0],scale:[s,s,1],children:t.jsx("meshBasicMaterial",{color:o,transparent:!0,opacity:.18,blending:b.AdditiveBlending,depthWrite:!1})}),t.jsx("mesh",{geometry:r.charcoal,material:a.charcoal,rotation:[-Math.PI/2,0,0],position:[0,.018,0],scale:[s,s,1]}),t.jsx("mesh",{geometry:r.log,material:a.log,position:[.12*l,.06*l,.05*l],rotation:[.3,0,.65],scale:l}),t.jsx("mesh",{geometry:r.log,material:a.log,position:[-.1*l,.06*l,.08*l],rotation:[.25,1.2,-.6],scale:l}),t.jsx("mesh",{geometry:r.log,material:a.log,position:[.02*l,.06*l,-.13*l],rotation:[-.2,.6,1],scale:l}),c.map((m,f)=>(()=>{const y=g[f],M=d[f];return!y||!M?null:t.jsx("mesh",{geometry:y,position:[m.x,m.y,m.z],children:t.jsx("fireMaterial",{ref:M,transparent:!0,depthWrite:!1,side:b.DoubleSide,blending:b.AdditiveBlending})},f)})()),t.jsx("points",{geometry:p,material:a.ember})]})},Ba=u.memo(Aa),Ea=`
|
|
156
|
+
attribute float aSeed;
|
|
157
|
+
attribute float aLean;
|
|
158
|
+
attribute float aFlare;
|
|
159
|
+
attribute float aIntensity;
|
|
160
|
+
attribute float aSpeed;
|
|
161
|
+
attribute float aTOff;
|
|
162
|
+
attribute float aWidth;
|
|
163
|
+
attribute float aHeight;
|
|
164
|
+
attribute vec3 aTint;
|
|
165
|
+
uniform float uTime;
|
|
166
|
+
|
|
167
|
+
varying vec2 vUv;
|
|
168
|
+
varying float vSeed;
|
|
169
|
+
varying float vLean;
|
|
170
|
+
varying float vFlare;
|
|
171
|
+
varying float vIntensity;
|
|
172
|
+
varying float vTime;
|
|
173
|
+
varying vec3 vTint;
|
|
174
|
+
|
|
175
|
+
void main() {
|
|
176
|
+
vUv = uv;
|
|
177
|
+
vSeed = aSeed;
|
|
178
|
+
vLean = aLean;
|
|
179
|
+
vFlare = aFlare;
|
|
180
|
+
vIntensity = aIntensity;
|
|
181
|
+
vTint = aTint;
|
|
182
|
+
vTime = uTime * aSpeed + aTOff;
|
|
183
|
+
|
|
184
|
+
vec3 right = vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]);
|
|
185
|
+
vec3 up = vec3(0.0, 1.0, 0.0);
|
|
186
|
+
|
|
187
|
+
float px = position.x * aWidth;
|
|
188
|
+
float py = position.y * aHeight;
|
|
189
|
+
float uy = clamp(uv.y, 0.0, 1.0);
|
|
190
|
+
|
|
191
|
+
float sway = sin(vTime * 0.7 + aSeed * 3.14) * 0.04 * uy;
|
|
192
|
+
float bend = aLean * pow(uy, 1.35) * (0.35 + uy * 0.65);
|
|
193
|
+
float wobble = sin((uy * 6.0 + aSeed * 5.73) + py * 1.15) * 0.03 * uy;
|
|
194
|
+
float lift = sin(uv.x * 3.14159 + aSeed * 3.7) * 0.015 * uy;
|
|
195
|
+
|
|
196
|
+
vec3 billboarded = right * (px + bend + wobble + sway) + up * (py + lift);
|
|
197
|
+
|
|
198
|
+
vec4 center = modelMatrix * instanceMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
|
199
|
+
center.xyz += billboarded;
|
|
200
|
+
|
|
201
|
+
gl_Position = projectionMatrix * viewMatrix * center;
|
|
202
|
+
}
|
|
203
|
+
`,ka=`
|
|
204
|
+
varying vec2 vUv;
|
|
205
|
+
varying float vSeed;
|
|
206
|
+
varying float vLean;
|
|
207
|
+
varying float vFlare;
|
|
208
|
+
varying float vIntensity;
|
|
209
|
+
varying float vTime;
|
|
210
|
+
varying vec3 vTint;
|
|
211
|
+
|
|
212
|
+
float hash(vec2 p) {
|
|
213
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
float noise(vec2 p) {
|
|
217
|
+
vec2 i = floor(p);
|
|
218
|
+
vec2 f = fract(p);
|
|
219
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
220
|
+
return mix(
|
|
221
|
+
mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x),
|
|
222
|
+
mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x),
|
|
223
|
+
f.y
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
float fbm(vec2 p) {
|
|
228
|
+
float v = 0.0, a = 0.5;
|
|
229
|
+
for (int i = 0; i < 3; i++) {
|
|
230
|
+
v += a * noise(p);
|
|
231
|
+
p = p * 2.1 + vec2(100.0);
|
|
232
|
+
a *= 0.5;
|
|
233
|
+
}
|
|
234
|
+
return v;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
void main() {
|
|
238
|
+
vec2 uv = vUv;
|
|
239
|
+
float time = vTime;
|
|
240
|
+
float seed = vSeed;
|
|
241
|
+
|
|
242
|
+
vec2 q = vec2(
|
|
243
|
+
fbm(vec2(uv.x * 4.2 + seed * 5.1, uv.y * 5.8 - time * 1.5)),
|
|
244
|
+
fbm(vec2(uv.x * 3.6 - seed * 3.3, uv.y * 4.6 + time * 0.6))
|
|
245
|
+
);
|
|
246
|
+
float n1 = fbm(uv * vec2(3.8, 5.6) + q * 1.5 + vec2(seed * 2.0, -time * 1.1));
|
|
247
|
+
float n2 = noise(vec2(uv.y * 9.0 + seed * 11.0, time * 4.7 + seed * 17.0));
|
|
248
|
+
|
|
249
|
+
float skew = vLean * pow(uv.y, 1.2);
|
|
250
|
+
float sway = (n1 - 0.5) * 0.28 * (1.0 - uv.y * 0.35);
|
|
251
|
+
float x = (uv.x - 0.5) - skew + sway;
|
|
252
|
+
float w = mix(0.46 * vFlare, 0.02, pow(uv.y, 0.72));
|
|
253
|
+
|
|
254
|
+
float edgeTurb = q.x * 0.07 * uv.y;
|
|
255
|
+
float body = 1.0 - smoothstep(w - edgeTurb, w + 0.06, abs(x));
|
|
256
|
+
float tongue1 = 1.0 - smoothstep(w * 0.82, w * 0.82 + 0.06, abs(x + 0.12 + q.y * 0.08));
|
|
257
|
+
float tongue2 = 1.0 - smoothstep(w * 0.68, w * 0.68 + 0.07, abs(x - 0.1 + q.x * 0.06));
|
|
258
|
+
|
|
259
|
+
float baseGlow = 1.0 - smoothstep(0.1, 0.42, distance(uv, vec2(0.5 + skew * 0.1, 0.1)));
|
|
260
|
+
float plume = max(body, max(tongue1 * 0.82, tongue2 * 0.68));
|
|
261
|
+
|
|
262
|
+
float bite = smoothstep(0.55, 1.0, n1 + uv.y * 0.4);
|
|
263
|
+
plume *= mix(1.0, 0.72, bite * smoothstep(0.2, 0.85, uv.y));
|
|
264
|
+
plume *= 1.0 - smoothstep(0.8, 1.0, uv.y);
|
|
265
|
+
plume = smoothstep(0.14, 0.9, plume + baseGlow * 0.38 + n1 * 0.2);
|
|
266
|
+
|
|
267
|
+
float core = 1.0 - smoothstep(0.01, 0.14, abs(x));
|
|
268
|
+
float fire = clamp(plume * (0.85 + 0.15 * n2), 0.0, 1.0);
|
|
269
|
+
|
|
270
|
+
vec3 deepRed = vec3(0.35, 0.02, 0.0);
|
|
271
|
+
vec3 ember = vec3(0.65, 0.08, 0.01);
|
|
272
|
+
vec3 orange = vec3(1.0, 0.38, 0.04);
|
|
273
|
+
vec3 golden = vec3(1.0, 0.65, 0.18);
|
|
274
|
+
vec3 hot = vec3(1.0, 0.88, 0.55);
|
|
275
|
+
vec3 white = vec3(1.0, 0.97, 0.92);
|
|
276
|
+
|
|
277
|
+
vec3 color = mix(deepRed, ember, smoothstep(0.02, 0.15, fire));
|
|
278
|
+
color = mix(color, orange, smoothstep(0.12, 0.35, fire));
|
|
279
|
+
color = mix(color, golden, smoothstep(0.28, 0.52, fire));
|
|
280
|
+
color = mix(color, hot, smoothstep(0.45, 0.72, fire));
|
|
281
|
+
color = mix(color, white, smoothstep(0.62, 1.0, fire * core));
|
|
282
|
+
|
|
283
|
+
float trail = smoothstep(0.8, 1.0, n2 + n1 * 0.3)
|
|
284
|
+
* smoothstep(0.18, 0.7, uv.y)
|
|
285
|
+
* smoothstep(0.35, 0.0, abs(x));
|
|
286
|
+
color += trail * vec3(1.0, 0.4, 0.06) * 0.4;
|
|
287
|
+
|
|
288
|
+
float smokeY = smoothstep(0.75, 0.98, uv.y);
|
|
289
|
+
float smoke = smokeY * q.x * 0.22 * smoothstep(0.28, 0.0, abs(x));
|
|
290
|
+
color = mix(color, vec3(0.18, 0.14, 0.12), smoke);
|
|
291
|
+
|
|
292
|
+
float alpha = smoothstep(0.06, 0.35, fire) * min(1.0, 0.5 + vIntensity * 0.26);
|
|
293
|
+
alpha += trail * 0.15 + smoke * 0.3;
|
|
294
|
+
|
|
295
|
+
if (alpha < 0.01) discard;
|
|
296
|
+
|
|
297
|
+
gl_FragColor = vec4(color * vTint * (0.62 + vIntensity * 0.48), alpha);
|
|
298
|
+
}
|
|
299
|
+
`,Ra=`
|
|
300
|
+
attribute float aLife;
|
|
301
|
+
attribute float aSpeed;
|
|
302
|
+
attribute float aDrift;
|
|
303
|
+
attribute vec3 aFirePos;
|
|
304
|
+
uniform float uTime;
|
|
305
|
+
varying float vAlpha;
|
|
306
|
+
varying float vHeat;
|
|
307
|
+
|
|
308
|
+
void main() {
|
|
309
|
+
float t = fract(uTime * aSpeed + aLife);
|
|
310
|
+
vec3 pos = position;
|
|
311
|
+
float angle = t * 8.0 + aDrift;
|
|
312
|
+
float radius = 0.08 + t * 0.2;
|
|
313
|
+
pos.y += t * t * 3.2;
|
|
314
|
+
pos.x += sin(angle) * radius;
|
|
315
|
+
pos.z += cos(angle) * radius;
|
|
316
|
+
float flicker = 0.75 + 0.25 * sin(uTime * 14.0 + aDrift * 4.0);
|
|
317
|
+
vAlpha = (1.0 - t) * (1.0 - t) * 0.9 * flicker;
|
|
318
|
+
vHeat = 1.0 - t * 0.85;
|
|
319
|
+
vec4 mvPosition = modelViewMatrix * vec4(pos + aFirePos, 1.0);
|
|
320
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
321
|
+
gl_PointSize = mix(4.5, 0.6, t) * (220.0 / -mvPosition.z);
|
|
322
|
+
}
|
|
323
|
+
`,Wn=[{wMul:.78,hMul:1,xMul:0,yMul:.5,z:0,seed:.17,lean:.06,flare:1,speed:1.45,tOff:0,iMul:1},{wMul:.52,hMul:.85,xMul:-.12,yMul:.43,z:.02,seed:1.31,lean:-.2,flare:.85,speed:1.9,tOff:1.7,iMul:.82},{wMul:.42,hMul:.7,xMul:.14,yMul:.36,z:-.02,seed:2.63,lean:.16,flare:.74,speed:2.2,tOff:3.4,iMul:.72}];let Hn=null,$n=null,Zn=null;function Pa(){return Hn||(Hn=new b.ShaderMaterial({vertexShader:Ea,fragmentShader:ka,uniforms:{uTime:{value:0}},transparent:!0,depthWrite:!1,side:b.DoubleSide,blending:b.AdditiveBlending})),Hn}function Da(){return $n||($n=new b.ShaderMaterial({vertexShader:Ra,fragmentShader:Ji,uniforms:{uTime:{value:0}},transparent:!0,depthWrite:!1,blending:b.AdditiveBlending})),$n}function Fa(){return Zn||(Zn=new b.MeshBasicMaterial({color:16777215,transparent:!0,opacity:.18,blending:b.AdditiveBlending,depthWrite:!1})),Zn}const _t=new b.Object3D,ce=new b.Object3D,en=new b.Matrix4,dt=new b.Color;function La(e){let s=`${e.length}`;for(const n of e)s+=`|${n.position[0]},${n.position[1]},${n.position[2]},${n.rotation},${n.intensity},${n.width},${n.height},${n.color}`;return s}const Ga=u.memo(function({fires:s}){const n=u.useRef(null),i=u.useRef(null),o=u.useRef(null),r=u.useRef(null),a=u.useRef(null),l=s.length,c=l*Wn.length,d=l*2,g=Qi(),p=eo(),m=Pa(),f=Fa(),y=Da(),M=u.useMemo(()=>La(s),[s]),_=u.useRef({signature:M,fires:s});_.current.signature!==M&&(_.current={signature:M,fires:s});const j=_.current.fires,A=u.useMemo(()=>{if(l===0)return null;const x=new b.PlaneGeometry(1,1),T=new Float32Array(c),C=new Float32Array(c),B=new Float32Array(c),I=new Float32Array(c),F=new Float32Array(c),R=new Float32Array(c),D=new Float32Array(c),E=new Float32Array(c),P=new Float32Array(c*3);let G=0;for(const z of j){dt.set(z.color);for(const L of Wn)T[G]=L.seed,C[G]=L.lean,B[G]=L.flare,I[G]=z.intensity*L.iMul,F[G]=L.speed,R[G]=L.tOff,D[G]=z.width*L.wMul,E[G]=z.height*L.hMul,P[G*3]=dt.r,P[G*3+1]=dt.g,P[G*3+2]=dt.b,G++}return x.setAttribute("aSeed",new b.InstancedBufferAttribute(T,1)),x.setAttribute("aLean",new b.InstancedBufferAttribute(C,1)),x.setAttribute("aFlare",new b.InstancedBufferAttribute(B,1)),x.setAttribute("aIntensity",new b.InstancedBufferAttribute(I,1)),x.setAttribute("aSpeed",new b.InstancedBufferAttribute(F,1)),x.setAttribute("aTOff",new b.InstancedBufferAttribute(R,1)),x.setAttribute("aWidth",new b.InstancedBufferAttribute(D,1)),x.setAttribute("aHeight",new b.InstancedBufferAttribute(E,1)),x.setAttribute("aTint",new b.InstancedBufferAttribute(P,3)),x},[M,j,l,c]),w=u.useMemo(()=>{if(l===0)return null;const x=18,T=l*x,C=new Float32Array(T*3),B=new Float32Array(T),I=new Float32Array(T),F=new Float32Array(T),R=new Float32Array(T*3);for(let E=0;E<l;E++){const P=j[E],G=E*x;for(let z=0;z<x;z++){const L=G+z;C[L*3]=(Math.random()-.5)*P.width*.35,C[L*3+1]=Math.random()*P.height*.2,C[L*3+2]=(Math.random()-.5)*P.width*.35,B[L]=Math.random(),I[L]=.12+Math.random()*.22,F[L]=Math.random()*Math.PI*2,R[L*3]=P.position[0],R[L*3+1]=P.position[1],R[L*3+2]=P.position[2]}}const D=new b.BufferGeometry;return D.setAttribute("position",new b.BufferAttribute(C,3)),D.setAttribute("aLife",new b.BufferAttribute(B,1)),D.setAttribute("aSpeed",new b.BufferAttribute(I,1)),D.setAttribute("aDrift",new b.BufferAttribute(F,1)),D.setAttribute("aFirePos",new b.BufferAttribute(R,3)),D.computeBoundingSphere(),D},[M,j,l]);return u.useLayoutEffect(()=>{if(l===0)return;const x=n.current;if(!x)return;let T=0;for(const C of s){const B=Math.cos(C.rotation),I=Math.sin(C.rotation);for(const F of Wn){const R=C.width*F.xMul,D=F.z;ce.position.set(C.position[0]+R*B+D*I,C.position[1]+C.height*F.yMul,C.position[2]+D*B-R*I),ce.rotation.set(0,0,0),ce.scale.set(1,1,1),ce.updateMatrix(),x.setMatrixAt(T++,ce.matrix)}}x.count=c,x.instanceMatrix.needsUpdate=!0},[s,l,c]),u.useLayoutEffect(()=>{if(l===0)return;const x=i.current;if(!x)return;let T=0;for(const C of s){_t.position.set(C.position[0],C.position[1],C.position[2]),_t.rotation.set(0,C.rotation,0),_t.updateMatrix();const B=Math.max(.4,(C.width+C.height*.5)/1.5);ce.position.set(.12*B,.06*B,.05*B),ce.rotation.set(.3,0,.65),ce.scale.set(B,B,B),ce.updateMatrix(),en.multiplyMatrices(_t.matrix,ce.matrix),x.setMatrixAt(T++,en),ce.position.set(-.1*B,.06*B,.08*B),ce.rotation.set(.25,1.2,-.6),ce.scale.set(B,B,B),ce.updateMatrix(),en.multiplyMatrices(_t.matrix,ce.matrix),x.setMatrixAt(T++,en)}x.count=d,x.instanceMatrix.needsUpdate=!0},[s,l,d]),u.useLayoutEffect(()=>{if(l===0)return;const x=o.current;if(x){for(let T=0;T<l;T++){const C=s[T];ce.position.set(C.position[0],C.position[1]+.018,C.position[2]),ce.rotation.set(-Math.PI/2,0,C.rotation),ce.scale.set(C.width,C.width,1),ce.updateMatrix(),x.setMatrixAt(T,ce.matrix)}x.count=l,x.instanceMatrix.needsUpdate=!0}},[s,l]),u.useLayoutEffect(()=>{if(l===0)return;const x=r.current;if(x){for(let T=0;T<l;T++){const C=s[T];ce.position.set(C.position[0],C.position[1]+.02,C.position[2]),ce.rotation.set(-Math.PI/2,0,C.rotation),ce.scale.set(C.width,C.width,1),ce.updateMatrix(),x.setMatrixAt(T,ce.matrix),dt.set(C.color),x.setColorAt(T,dt)}x.count=l,x.instanceMatrix.needsUpdate=!0,x.instanceColor&&(x.instanceColor.needsUpdate=!0)}},[s,l]),ae.useFrame(x=>{const T=x.clock.elapsedTime;m.uniforms.uTime.value=T,y.uniforms.uTime.value=T,f.opacity=.16+Math.sin(T*2.5)*.06}),u.useEffect(()=>()=>{A?.dispose(),w?.dispose()},[A,w]),l===0?null:t.jsxs(t.Fragment,{children:[A&&t.jsx("instancedMesh",{ref:n,args:[A,m,c],frustumCulled:!1}),t.jsx("instancedMesh",{ref:i,args:[g.log,p.log,d]}),t.jsx("instancedMesh",{ref:o,args:[g.charcoal,p.charcoal,l]}),t.jsx("instancedMesh",{ref:r,args:[g.glow,f,l]}),w&&t.jsx("points",{ref:a,geometry:w,material:y,frustumCulled:!1})]})});var za=`precision highp float;
|
|
324
|
+
|
|
325
|
+
uniform sampler2D map;\r
|
|
326
|
+
uniform float transmission;\r
|
|
327
|
+
uniform float envMapIntensity;
|
|
328
|
+
|
|
329
|
+
varying vec2 vUv;
|
|
330
|
+
|
|
331
|
+
void main() {\r
|
|
332
|
+
vec4 texColor = texture2D(map, vUv);\r
|
|
333
|
+
float alpha = texColor.a * (1.0 - transmission);\r
|
|
334
|
+
if (alpha < 0.01) discard;\r
|
|
335
|
+
gl_FragColor = vec4(texColor.rgb * envMapIntensity, alpha);\r
|
|
336
|
+
}`,Oa=`precision highp float;
|
|
337
|
+
|
|
338
|
+
uniform float time;\r
|
|
339
|
+
uniform float windStrength;
|
|
340
|
+
|
|
341
|
+
varying vec2 vUv;
|
|
342
|
+
|
|
343
|
+
void main() {\r
|
|
344
|
+
vUv = uv;\r
|
|
345
|
+
vec3 pos = position;
|
|
346
|
+
|
|
347
|
+
float fixGradient = uv.x * uv.x;
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
float phase = 0.0;\r
|
|
351
|
+
#ifdef USE_INSTANCING\r
|
|
352
|
+
phase = instanceMatrix[3][0] * 0.3 + instanceMatrix[3][2] * 0.5;\r
|
|
353
|
+
#endif
|
|
354
|
+
|
|
355
|
+
float wave1 = sin(uv.x * 4.0 + time * 1.0 + phase) * 0.12;\r
|
|
356
|
+
float wave2 = sin(uv.x * 7.0 + time * 1.7 + 1.3 + phase * 0.7) * 0.06;\r
|
|
357
|
+
float wave3 = sin(uv.x * 13.0 + time * 2.9 + 2.7 + phase * 1.3) * 0.025;
|
|
358
|
+
|
|
359
|
+
float verticalRipple = sin(uv.y * 6.0 + time * 0.8 + phase * 0.4) * 0.02 * fixGradient;
|
|
360
|
+
|
|
361
|
+
float displacement = (wave1 + wave2 + wave3) * fixGradient * windStrength;\r
|
|
362
|
+
pos.z += displacement + verticalRipple;\r
|
|
363
|
+
pos.y -= fixGradient * 0.03 * windStrength;
|
|
364
|
+
|
|
365
|
+
vec4 mvPosition = vec4(pos, 1.0);\r
|
|
366
|
+
#ifdef USE_INSTANCING\r
|
|
367
|
+
mvPosition = instanceMatrix * mvPosition;\r
|
|
368
|
+
#endif\r
|
|
369
|
+
gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\r
|
|
370
|
+
}`;const Ua=Ge.shaderMaterial({map:null,time:0,windStrength:1,transmission:.05,envMapIntensity:1},Oa,za);ae.extend({FlagMaterial:Ua});let Ct=null;function Wa(){if(Ct)return Ct;const e=document.createElement("canvas");e.width=4,e.height=4;const s=e.getContext("2d");return s.fillStyle="#cc2222",s.fillRect(0,0,4,4),Ct=new b.CanvasTexture(e),Ct.needsUpdate=!0,Ct}const Ha=new b.MeshStandardMaterial({color:"#8B4513"}),$a=new b.MeshStandardMaterial({color:"#444444",metalness:.6,roughness:.3}),K=new b.Object3D;function Za(e){const s=[];for(const n of e)switch(S.FLAG_STYLE_META[n.style].poleType){case"side":{const o=n.flagHeight+2.5;K.position.set(n.x,n.y+o/2,n.z),K.scale.set(1,o,1),K.updateMatrix(),s.push(K.matrix.clone());break}case"top":{const o=n.flagHeight+1.5;K.position.set(n.x,n.y+o+.025,n.z),K.rotation.set(0,0,Math.PI/2),K.scale.set(1,n.flagWidth,1),K.updateMatrix(),s.push(K.matrix.clone()),K.rotation.set(0,0,0);break}case"frame":{const o=n.flagHeight+.5;K.position.set(n.x-n.flagWidth/2,n.y+o/2,n.z),K.scale.set(1,o,1),K.updateMatrix(),s.push(K.matrix.clone()),K.position.set(n.x+n.flagWidth/2,n.y+o/2,n.z),K.updateMatrix(),s.push(K.matrix.clone()),K.position.set(n.x,n.y+o,n.z),K.rotation.set(0,0,Math.PI/2),K.scale.set(1,n.flagWidth+.05,1),K.updateMatrix(),s.push(K.matrix.clone()),K.rotation.set(0,0,0),K.position.set(n.x,n.y+.025,n.z),K.rotation.set(0,0,Math.PI/2),K.scale.set(1,n.flagWidth+.05,1),K.updateMatrix(),s.push(K.matrix.clone()),K.rotation.set(0,0,0);break}case"both":{const o=n.flagHeight+2.5;K.position.set(n.x-n.flagWidth/2,n.y+o/2,n.z),K.scale.set(1,o,1),K.updateMatrix(),s.push(K.matrix.clone()),K.position.set(n.x+n.flagWidth/2,n.y+o/2,n.z),K.updateMatrix(),s.push(K.matrix.clone());break}}return s}function Va({entries:e}){const s=u.useRef(null),n=u.useMemo(()=>new b.BoxGeometry(.05,1,.05),[]),i=u.useMemo(()=>Za(e),[e]),o=i.length,r=u.useMemo(()=>Math.max(1,o),[o]),l=e.some(c=>c.style==="panel")?$a:Ha;return u.useLayoutEffect(()=>{const c=s.current;if(c){c.count=o;for(let d=0;d<o;d++){const g=i[d];g&&c.setMatrixAt(d,g)}c.instanceMatrix.needsUpdate=!0}},[i,o]),u.useEffect(()=>()=>{n.dispose()},[n]),o===0?null:t.jsx("instancedMesh",{ref:s,args:[n,l,r]})}function to({entries:e,windStrength:s,texture:n}){const i=u.useRef(null),o=u.useRef(null),r=e.length,a=u.useMemo(()=>Math.max(1,r),[r]),l=e[0]?.flagWidth??1.5,c=e[0]?.flagHeight??1,d=s>0?16:1,g=s>0?8:1,p=u.useMemo(()=>new b.PlaneGeometry(l,c,d,g),[l,c,d,g]);return u.useLayoutEffect(()=>{const m=i.current;if(m){m.count=r;for(let f=0;f<r;f++){const y=e[f];if(!y)continue;const M=S.FLAG_STYLE_META[y.style];let _=y.x,j=y.y;switch(M.poleType){case"side":_=y.x+y.flagWidth/2,j=y.y+y.flagHeight+2.5-y.flagHeight/2;break;case"top":j=y.y+y.flagHeight+1.5-y.flagHeight/2;break;case"frame":j=y.y+(y.flagHeight+.5)/2+.025;break;case"both":j=y.y+y.flagHeight+2.5-y.flagHeight/2;break}K.position.set(_,j,y.z),K.scale.set(y.flagWidth/l,y.flagHeight/c,1),K.updateMatrix(),m.setMatrixAt(f,K.matrix)}m.instanceMatrix.needsUpdate=!0}},[e,r,l,c]),ae.useFrame(m=>{const f=o.current;f.time=m.clock.elapsedTime*5,f.windStrength=s}),u.useEffect(()=>()=>{p.dispose()},[p]),r===0?null:t.jsx("instancedMesh",{ref:i,args:[p,void 0,a],frustumCulled:!1,children:t.jsx("flagMaterial",{ref:o,map:n,transmission:.05,windStrength:s,envMapIntensity:1,side:b.DoubleSide,transparent:!0})})}function Ya({entries:e,textureUrl:s,windStrength:n}){const i=Ge.useTexture(s);return t.jsx(to,{entries:e,windStrength:n,texture:i})}function Xa({entries:e,windStrength:s}){const n=u.useMemo(()=>Wa(),[]);return t.jsx(to,{entries:e,windStrength:s,texture:n})}function qa({entries:e,textureUrl:s,windStrength:n}){return s?t.jsx(Ya,{entries:e,textureUrl:s,windStrength:n}):t.jsx(Xa,{entries:e,windStrength:n})}const Ka=u.memo(function({flags:s}){const n=u.useMemo(()=>s.map(o=>({x:o.position.x,y:o.position.y,z:o.position.z,flagWidth:o.config?.flagWidth??1.5,flagHeight:o.config?.flagHeight??1,style:o.config?.flagStyle??"flag",textureUrl:o.config?.flagTexture??""})),[s]),i=u.useMemo(()=>{const o=new Map;for(const r of n){const a=`${r.textureUrl}|${r.style}`;let l=o.get(a);l||(l=[],o.set(a,l)),l.push(r)}return Array.from(o.entries())},[n]);return t.jsxs(t.Fragment,{children:[t.jsx(Va,{entries:n}),i.map(([o,r])=>{const a=r[0];if(!a)return null;const l=a.style,c=S.FLAG_STYLE_META[l].windStrength,d=a.textureUrl;return t.jsx(qa,{entries:r,textureUrl:d,windStrength:c},o)})]})});class Ja extends u.Component{state={failed:!1};static getDerivedStateFromError(){return{failed:!0}}componentDidUpdate(s){s.children!==this.props.children&&this.state.failed&&this.setState({failed:!1})}render(){return this.state.failed?this.props.fallback:this.props.children}}function Qa({url:e}){const{scene:s}=Ge.useGLTF(e),n=u.useMemo(()=>gs.SkeletonUtils.clone(s),[s]);return t.jsx("primitive",{object:n})}function ne(e,s,n,i){return t.jsxs("mesh",{position:s,castShadow:!0,receiveShadow:!0,children:[t.jsx("boxGeometry",{args:e}),t.jsx("meshStandardMaterial",{color:n,roughness:.75,metalness:.04})]},i)}function Vn(e,s,n,i){return t.jsxs("mesh",{position:s,castShadow:!0,receiveShadow:!0,children:[t.jsx("cylinderGeometry",{args:e}),t.jsx("meshStandardMaterial",{color:n,roughness:.7,metalness:.05})]},i)}function el({kind:e="generic",color:s="#9b7653"}){const n=new b.Color(s).multiplyScalar(.72).getStyle(),i=new b.Color(s).lerp(new b.Color("#ffffff"),.35).getStyle();return e==="door"?t.jsxs("group",{children:[ne([.9,1.9,.12],[0,.95,0],s,"panel"),ne([.08,2.05,.16],[-.5,1.02,0],n,"left-frame"),ne([.08,2.05,.16],[.5,1.02,0],n,"right-frame"),Vn([.045,.045,.06,12],[.32,.95,.08],"#f3c969","knob")]}):e==="window"?t.jsxs("group",{children:[ne([1.1,.08,.12],[0,1.3,0],n,"top"),ne([1.1,.08,.12],[0,.55,0],n,"bottom"),ne([.08,.82,.12],[-.55,.92,0],n,"left"),ne([.08,.82,.12],[.55,.92,0],n,"right"),ne([.9,.62,.04],[0,.92,.02],s,"glass")]}):e==="fence"?t.jsxs("group",{children:[ne([.16,1,.16],[-.65,.5,0],n,"post-a"),ne([.16,1,.16],[.65,.5,0],n,"post-b"),ne([1.5,.16,.12],[0,.72,0],s,"rail-a"),ne([1.5,.16,.12],[0,.36,0],s,"rail-b")]}):e==="lamp"?t.jsxs("group",{children:[Vn([.06,.08,1.5,12],[0,.75,0],n,"pole"),Vn([.28,.18,.35,16],[0,1.55,0],s,"shade"),t.jsx("pointLight",{position:[0,1.55,0],intensity:.65,distance:5,color:i})]}):e==="chair"?t.jsxs("group",{children:[ne([.8,.12,.75],[0,.55,0],s,"seat"),ne([.8,.9,.12],[0,1,.33],n,"back"),ne([.09,.55,.09],[-.3,.28,-.25],n,"leg-a"),ne([.09,.55,.09],[.3,.28,-.25],n,"leg-b"),ne([.09,.55,.09],[-.3,.28,.25],n,"leg-c"),ne([.09,.55,.09],[.3,.28,.25],n,"leg-d")]}):e==="table"||e==="crafting"?t.jsxs("group",{children:[ne([1.4,.16,.9],[0,.8,0],s,"top"),ne([.12,.75,.12],[-.52,.38,-.3],n,"leg-a"),ne([.12,.75,.12],[.52,.38,-.3],n,"leg-b"),ne([.12,.75,.12],[-.52,.38,.3],n,"leg-c"),ne([.12,.75,.12],[.52,.38,.3],n,"leg-d"),e==="crafting"&&ne([.55,.12,.12],[.22,.96,0],i,"tool")]}):e==="bed"?t.jsxs("group",{children:[ne([1.3,.35,2],[0,.35,0],s,"base"),ne([1.25,.18,1.45],[0,.62,.2],i,"blanket"),ne([1.25,.55,.14],[0,.72,.92],n,"headboard")]}):e==="storage"||e==="mailbox"?t.jsxs("group",{children:[ne([1,.8,.7],[0,.4,0],s,"body"),ne([1.08,.12,.78],[0,.86,0],n,"lid"),ne([.38,.08,.04],[0,.46,.37],i,"handle")]}):e==="shop"?t.jsxs("group",{children:[ne([1.7,.18,.9],[0,.72,0],s,"counter"),ne([1.9,.16,1],[0,1.55,0],i,"awning"),ne([.08,1.45,.08],[-.82,.8,-.35],n,"post-a"),ne([.08,1.45,.08],[.82,.8,-.35],n,"post-b")]}):ne([1,1,1],[0,.5,0],s,"generic")}function tl({url:e,label:s,fallbackKind:n,scale:i=1,color:o}){const r=t.jsx(el,{kind:n,color:o});return u.useEffect(()=>{e&&Ge.useGLTF.preload(e)},[e]),t.jsx("group",{name:s??"building-model-object",scale:[i,i,i],children:e?t.jsx(Ja,{fallback:r,children:t.jsx(u.Suspense,{fallback:r,children:t.jsx(Qa,{url:e})})}):r})}function V(e){const s=Math.sin(e*127.1+311.7)*43758.5453123;return s-Math.floor(s)}function Ts(e,s,n){e[s]=n.r,e[s+1]=n.g,e[s+2]=n.b}let Yn=null,Xn=null,qn=null;function no(){return Yn||(Yn={limb:new b.CylinderGeometry(.5,1,1,8,1,!1),canopyCluster:new b.IcosahedronGeometry(1,1),canopyCore:new b.SphereGeometry(1,10,8),trunkTop:new b.SphereGeometry(1,10,8)}),Yn}function so(e){return e?(qn||(qn={bark:S.createToonMaterial({color:"#5e3d30",steps:3}),barkDark:S.createToonMaterial({color:"#3f271e",steps:3}),blossomShell:S.createToonMaterial({color:"#f7bfd2",transparent:!0,opacity:.78,steps:4,depthWrite:!1}),blossomCore:S.createToonMaterial({color:"#ffe6f0",transparent:!0,opacity:.6,steps:4,depthWrite:!1})}),qn):(Xn||(Xn={bark:new b.MeshStandardMaterial({color:"#5e3d30",roughness:.95,metalness:.02}),barkDark:new b.MeshStandardMaterial({color:"#3f271e",roughness:1,metalness:.01}),blossomShell:new b.MeshStandardMaterial({color:"#f7bfd2",roughness:.92,metalness:0,transparent:!0,opacity:.68}),blossomCore:new b.MeshStandardMaterial({color:"#ffe6f0",roughness:.84,metalness:0,transparent:!0,opacity:.5})}),Xn)}function io(e,s){const n=Math.max(11,Math.min(18,Math.round(10+e*4)));return Array.from({length:n},(i,o)=>{const r=19.3+o*13.17+e*5.1,a=(1.05+V(r+1)*1.35)*e,l=V(r+2)>.5?1:-1;return{pivotY:s*(.38+V(r+3)*.42),length:a,radius:(.08+V(r+4)*.045)*e,yaw:V(r+5)*Math.PI*2,bend:(.58+V(r+6)*.34)*l,lean:(V(r+7)-.5)*.34,twigLength:a*(.34+V(r+8)*.26),twigYaw:(V(r+9)-.5)*.95,twigLean:(.25+V(r+10)*.38)*-l}})}function oo(e){return Array.from({length:5},(s,n)=>{const i=101.2+n*8.31+e*3.7;return{angle:n/5*Math.PI*2+(V(i)-.5)*.4,length:(.52+V(i+1)*.42)*e,radius:(.09+V(i+2)*.04)*e,spread:(.8+V(i+3)*.28)*(V(i+4)>.5?1:-1)}})}function ro(e,s,n,i){const o=Math.max(9,Math.min(16,Math.round(9+e*4)));return Array.from({length:o},(r,a)=>{const l=220.4+a*10.73+e*4.4,c=V(l)*Math.PI*2,d=n*(.18+V(l+1)*.72),g=(.7+V(l+5)*.9)*e,p=(.52+V(l+6)*.56)*e,m=(.66+V(l+7)*.88)*e;return{position:[Math.cos(c)*d,s*(.64+V(l+3)*.22)+V(l+4)*i*.42,Math.sin(c)*d*(.86+V(l+2)*.22)],rotation:[(V(l+8)-.5)*.55,V(l+9)*Math.PI*2,(V(l+10)-.5)*.55],outerScale:[g,p,m],innerScale:[g*.7,p*.72,m*.7]}})}const tn=new b.Object3D,Ee=new b.Object3D,Rt=new b.Matrix4,pn=new b.Matrix4,$e=new b.Color;function Ve(e,s,n,i,o,r,a,l){tn.position.set(i[0],i[1],i[2]),tn.rotation.set(o[0],o[1],o[2]),tn.updateMatrix(),Ee.position.set(r[0],r[1],r[2]),Ee.rotation.set(a?a[0]:0,a?a[1]:0,a?a[2]:0),Ee.scale.set(l[0],l[1],l[2]),Ee.updateMatrix(),Rt.multiplyMatrices(tn.matrix,Ee.matrix),n&&(pn.makeTranslation(n[0],n[1]+.02,n[2]),Rt.premultiply(pn)),e.setMatrixAt(s,Rt)}function mn(e,s,n,i,o,r){Ee.position.set(i[0],i[1],i[2]),Ee.rotation.set(o[0],o[1],o[2]),Ee.scale.set(r[0],r[1],r[2]),Ee.updateMatrix(),n?(pn.makeTranslation(n[0],n[1]+.02,n[2]),Rt.multiplyMatrices(pn,Ee.matrix),e.setMatrixAt(s,Rt)):e.setMatrixAt(s,Ee.matrix)}function ao(e,s,n,i,o,r,a,l,c,d,g){const p=g?g.clone().multiplyScalar(.85):new b.Color("#f3a1bf"),m=g?g.clone().lerp(new b.Color("#ffffff"),.6):new b.Color("#fff1f6"),f=new b.Color;for(let y=0;y<i;y++){const M=330.7+y*17.13,_=V(M)*Math.PI*2,j=r*(.18+Math.sqrt(V(M+1))*.86),A=(n+y)*3;e[A]=Math.cos(_)*j*(.82+V(M+2)*.22)+l,e[A+1]=o*.58+Math.pow(V(M+4),.72)*a+(V(M+5)-.5)*.36+c,e[A+2]=Math.sin(_)*j*(.8+V(M+3)*.26)+d,f.copy(p).lerp(m,.28+V(M+6)*.72).multiplyScalar(.92+V(M+7)*.18),Ts(s,A,f)}}function lo(e,s,n,i,o,r,a,l,c){const d=c?c.clone().multiplyScalar(.9):new b.Color("#f7cadb"),g=c?c.clone().lerp(new b.Color("#ffffff"),.7):new b.Color("#fff3f8"),p=new b.Color;for(let m=0;m<i;m++){const f=510.9+m*9.41,y=V(f)*Math.PI*2,M=o*(.18+Math.pow(V(f+1),.6)*.92),_=(n+m)*3;e[_]=Math.cos(y)*M+r,e[_+1]=.035+V(f+2)*.03+a,e[_+2]=Math.sin(y)*M+l,p.copy(d).lerp(g,.35+V(f+3)*.65).multiplyScalar(.9+V(f+4)*.12),Ts(s,_,p)}}function co(e,s,n,i,o,r,a,l,c,d,g,p,m,f,y,M){const _=M?M.clone().multiplyScalar(.88):new b.Color("#f8b3ca"),j=M?M.clone().lerp(new b.Color("#ffffff"),.65):new b.Color("#fff5fa"),A=new b.Color;for(let w=0;w<l;w++){const x=740.6+w*6.83,T=V(x)*Math.PI*2,C=d*(.1+V(x+1)*.72),B=a+w,I=B*3;e[I]=Math.cos(T)*C,e[I+1]=c*.66+V(x+2)*g*.88,e[I+2]=Math.sin(T)*C;const F=B*4;n[F]=.12+V(x+3)*.18,n[F+1]=V(x+4),n[F+2]=.08+V(x+5)*.18,n[F+3]=1+V(x+6)*1.9;const R=B*2;i[R]=(V(x+7)-.5)*.8,i[R+1]=(V(x+8)-.5)*.8,o&&(o[I]=m,o[I+1]=f,o[I+2]=y),r&&(r[B]=.11*p),A.copy(_).lerp(j,.2+V(x+9)*.8).multiplyScalar(.94+V(x+10)*.12),Ts(s,I,A)}}function fn(e,s,n=!1){const i=new b.BufferGeometry;return i.setAttribute("position",new b.Float32BufferAttribute(e,3)),i.setAttribute("color",new b.Float32BufferAttribute(s,3)),n&&i.computeBoundingBox(),i.computeBoundingSphere(),i}const nt=new b.Color("#f7bfd2"),Et=new b.Color("#5e3d30"),nl=new b.Color("#ffffff");function sl(e){return e.map(s=>{const n=b.MathUtils.clamp(s.size/4,.95,1.85),i=3.8*n,o=1.65*n+Math.min(s.size*.08,.55),r=2.15*n+Math.min(s.size*.04,.35);return{pos:s.position,scale:n,trunkHeight:i,crownRadius:o,crownHeight:r,branches:io(n,i),roots:oo(n),clusters:ro(n,i,o,r),canopyN:Math.max(180,Math.min(420,Math.round(210+n*95))),groundN:Math.max(44,Math.min(120,Math.round(54+n*26))),fallingN:Math.max(52,Math.min(132,Math.round(62+n*30))),blossom:s.blossomColor?new b.Color(s.blossomColor):nt,bark:s.barkColor?new b.Color(s.barkColor):Et}})}const il=`
|
|
371
|
+
attribute vec3 color;
|
|
372
|
+
attribute vec4 aParams1;
|
|
373
|
+
attribute vec2 aParams2;
|
|
374
|
+
attribute vec3 aTreePos;
|
|
375
|
+
attribute float aPointScale;
|
|
376
|
+
|
|
377
|
+
uniform float uTime;
|
|
378
|
+
uniform float uScale;
|
|
379
|
+
uniform float uWind;
|
|
380
|
+
|
|
381
|
+
varying vec3 vColor;
|
|
382
|
+
|
|
383
|
+
void main() {
|
|
384
|
+
float cycle = fract(uTime * aParams1.x + aParams1.y);
|
|
385
|
+
float drift = 1.0 - pow(cycle, 1.22);
|
|
386
|
+
float w = uTime * aParams1.w + aParams1.y * 6.28318;
|
|
387
|
+
|
|
388
|
+
vec3 localPos = vec3(
|
|
389
|
+
position.x + sin(w) * aParams1.z * uWind + aParams2.x * cycle * uWind,
|
|
390
|
+
0.18 + position.y * drift + sin(w * 0.6) * 0.06,
|
|
391
|
+
position.z + cos(w * 0.82) * aParams1.z * 0.72 * uWind + aParams2.y * cycle * uWind
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
vColor = color;
|
|
395
|
+
vec4 mvPosition = modelViewMatrix * vec4(localPos + aTreePos, 1.0);
|
|
396
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
397
|
+
gl_PointSize = aPointScale * (uScale / -mvPosition.z);
|
|
398
|
+
}
|
|
399
|
+
`,uo=`
|
|
400
|
+
uniform float uOpacity;
|
|
401
|
+
varying vec3 vColor;
|
|
402
|
+
void main() {
|
|
403
|
+
vec2 d = gl_PointCoord - vec2(0.5);
|
|
404
|
+
float r2 = dot(d, d);
|
|
405
|
+
if (r2 > 0.25) discard;
|
|
406
|
+
gl_FragColor = vec4(vColor, uOpacity * exp(-r2 * 8.0));
|
|
407
|
+
}
|
|
408
|
+
`;function po({trees:e,toon:s}){const n=u.useRef(null),i=u.useRef(null),o=u.useRef(null),r=u.useRef(null),a=u.useRef(null),l=u.useRef(null),c=s??S.getDefaultToonMode(),d=no(),g=so(c),p=u.useMemo(()=>sl(e),[e]),m=u.useMemo(()=>{let w=0,x=0,T=0,C=0,B=0,I=0;for(const F of p)w+=F.branches.length+1,x+=F.roots.length+F.branches.length,T+=F.clusters.length,C+=F.canopyN,B+=F.groundN,I+=F.fallingN;return{bark:w,dark:x,top:p.length,cluster:T,canopy:C,ground:B,falling:I}},[p]),f=u.useMemo(()=>p.length===0?1:p.reduce((w,x)=>w+x.scale,0)/p.length,[p]),y=u.useMemo(()=>p.some(w=>w.blossom!==nt||w.bark!==Et),[p]),M=u.useMemo(()=>{const w=new Float32Array(m.canopy*3),x=new Float32Array(m.canopy*3);let T=0;for(const C of p){const B=C.blossom!==nt?C.blossom:void 0;ao(w,x,T,C.canopyN,C.trunkHeight,C.crownRadius,C.crownHeight,C.pos[0],C.pos[1]+.02,C.pos[2],B),T+=C.canopyN}return fn(w,x)},[p,m.canopy]),_=u.useMemo(()=>{const w=new Float32Array(m.ground*3),x=new Float32Array(m.ground*3);let T=0;for(const C of p){const B=C.blossom!==nt?C.blossom:void 0;lo(w,x,T,C.groundN,C.crownRadius,C.pos[0],C.pos[1]+.02,C.pos[2],B),T+=C.groundN}return fn(w,x)},[p,m.ground]),j=u.useMemo(()=>{const w=m.falling,x=new Float32Array(w*3),T=new Float32Array(w*3),C=new Float32Array(w*4),B=new Float32Array(w*2),I=new Float32Array(w*3),F=new Float32Array(w);let R=0;for(const E of p){const P=E.blossom!==nt?E.blossom:void 0;co(x,T,C,B,I,F,R,E.fallingN,E.trunkHeight,E.crownRadius,E.crownHeight,E.scale,E.pos[0],E.pos[1]+.02,E.pos[2],P),R+=E.fallingN}const D=new b.BufferGeometry;return D.setAttribute("position",new b.Float32BufferAttribute(x,3)),D.setAttribute("color",new b.Float32BufferAttribute(T,3)),D.setAttribute("aParams1",new b.Float32BufferAttribute(C,4)),D.setAttribute("aParams2",new b.Float32BufferAttribute(B,2)),D.setAttribute("aTreePos",new b.Float32BufferAttribute(I,3)),D.setAttribute("aPointScale",new b.Float32BufferAttribute(F,1)),D.computeBoundingSphere(),D},[p,m.falling]),A=u.useMemo(()=>new b.ShaderMaterial({uniforms:{uTime:{value:0},uScale:{value:1},uOpacity:{value:.88},uWind:{value:1}},vertexShader:il,fragmentShader:uo,transparent:!0,depthWrite:!1}),[]);return u.useLayoutEffect(()=>{let w=0,x=0,T=0,C=0,B=0;for(const I of p){const F=I.pos,R=I.bark!==Et,D=I.blossom!==nt;if(Ve(n.current,w,F,[0,I.trunkHeight*.5,0],[.02,0,-.04],[0,0,0],null,[.3*I.scale,I.trunkHeight,.3*I.scale]),y&&n.current.setColorAt(w,R?I.bark:Et),w++,Ve(o.current,T,F,[0,I.trunkHeight*.5,0],[.02,0,-.04],[0,I.trunkHeight*.48,0],null,[.24*I.scale,.32*I.scale,.24*I.scale]),y){const E=R?$e.copy(I.bark).multiplyScalar(.65):$e.set("#3f271e");o.current.setColorAt(T,E)}T++;for(const E of I.branches)Ve(n.current,w,F,[0,E.pivotY,0],[E.lean,E.yaw,E.bend],[0,E.length*.5,0],null,[E.radius,E.length,E.radius]),y&&n.current.setColorAt(w,R?I.bark:Et),w++;for(const E of I.roots){if(Ve(i.current,x,F,[0,.14*I.scale,0],[0,E.angle,E.spread],[0,E.length*.22,0],null,[E.radius,E.length,E.radius]),y){const P=R?$e.copy(I.bark).multiplyScalar(.65):$e.set("#3f271e");i.current.setColorAt(x,P)}x++}for(const E of I.branches){if(Ve(i.current,x,F,[0,E.pivotY,0],[E.lean,E.yaw,E.bend],[0,E.length*.76,0],[E.twigLean,E.twigYaw,E.bend*-.42],[E.radius*.52,E.twigLength,E.radius*.52]),y){const P=R?$e.copy(I.bark).multiplyScalar(.65):$e.set("#3f271e");i.current.setColorAt(x,P)}x++}for(const E of I.clusters){if(mn(r.current,C,F,E.position,E.rotation,E.outerScale),y&&r.current.setColorAt(C,D?I.blossom:nt),C++,mn(a.current,B,F,E.position,E.rotation,E.innerScale),y){const P=D?$e.copy(I.blossom).lerp(nl,.4):$e.set("#ffe6f0");a.current.setColorAt(B,P)}B++}}for(const[I,F]of[[n,w],[i,x],[o,T],[r,C],[a,B]])I.current.count=F,I.current.instanceMatrix.needsUpdate=!0,y&&I.current.instanceColor&&(I.current.instanceColor.needsUpdate=!0)},[p,y,m]),u.useEffect(()=>()=>{M.dispose(),_.dispose(),j.dispose(),A.dispose()},[M,_,j,A]),ae.useFrame(w=>{const x=l.current;if(!x)return;const T=x.parent;if(T&&!T.visible)return;const C=x.material;if(C?.uniforms){const B=C.uniforms.uTime,I=C.uniforms.uScale,F=oi.useWeatherStore.getState().current,R=F?.intensity??0,D=F?.kind==="storm"?2.4:F?.kind==="rain"?1.6:F?.kind==="snow"?1.2:F?.kind==="cloudy"?1.1:.9,E=C.uniforms.uWind;B&&(B.value=w.clock.getElapsedTime()),I&&(I.value=w.gl.domElement.height*.5),E&&(E.value=D+R*.7)}}),p.length===0?null:t.jsxs(t.Fragment,{children:[t.jsx("instancedMesh",{ref:n,args:[d.limb,g.bark,m.bark],castShadow:!0}),t.jsx("instancedMesh",{ref:i,args:[d.limb,g.barkDark,m.dark]}),t.jsx("instancedMesh",{ref:o,args:[d.trunkTop,g.barkDark,m.top],castShadow:!0}),t.jsx("instancedMesh",{ref:r,args:[d.canopyCluster,g.blossomShell,m.cluster],castShadow:!0}),t.jsx("instancedMesh",{ref:a,args:[d.canopyCore,g.blossomCore,m.cluster]}),t.jsx("points",{geometry:M,children:t.jsx("pointsMaterial",{size:.08*f,sizeAttenuation:!0,vertexColors:!0,transparent:!0,opacity:.82,depthWrite:!1})}),t.jsx("points",{ref:l,geometry:j,material:A,frustumCulled:!1}),t.jsx("points",{geometry:_,children:t.jsx("pointsMaterial",{size:.085*f,sizeAttenuation:!0,vertexColors:!0,transparent:!0,opacity:.7,depthWrite:!1})})]})}function ol({size:e=4,toon:s}){const n=u.useRef(null),i=u.useRef(null),o=u.useRef(null),r=u.useRef(null),a=u.useRef(null),l=u.useRef(null),c=u.useMemo(()=>b.MathUtils.clamp(e/4,.95,1.85),[e]),d=3.8*c,g=1.65*c+Math.min(e*.08,.55),p=2.15*c+Math.min(e*.04,.35),m=s??S.getDefaultToonMode(),f=no(),y=so(m),M=u.useMemo(()=>io(c,d),[c,d]),_=u.useMemo(()=>oo(c),[c]),j=u.useMemo(()=>ro(c,d,g,p),[c,d,g,p]),A=M.length,w=_.length+M.length,x=j.length,T=Math.max(180,Math.min(420,Math.round(210+c*95))),C=Math.max(44,Math.min(120,Math.round(54+c*26))),B=Math.max(52,Math.min(132,Math.round(62+c*30))),I=u.useMemo(()=>{const E=new Float32Array(T*3),P=new Float32Array(T*3);return ao(E,P,0,T,d,g,p,0,0,0),fn(E,P,!0)},[T,d,g,p]),F=u.useMemo(()=>{const E=new Float32Array(C*3),P=new Float32Array(C*3);return lo(E,P,0,C,g,0,0,0),fn(E,P,!0)},[C,g]),R=u.useMemo(()=>{const E=new Float32Array(B*3),P=new Float32Array(B*3),G=new Float32Array(B*4),z=new Float32Array(B*2);co(E,P,G,z,null,null,0,B,d,g,p,c,0,0,0);const L=new b.BufferGeometry;return L.setAttribute("position",new b.Float32BufferAttribute(E,3)),L.setAttribute("color",new b.Float32BufferAttribute(P,3)),L.setAttribute("aParams1",new b.Float32BufferAttribute(G,4)),L.setAttribute("aParams2",new b.Float32BufferAttribute(z,2)),L.computeBoundingSphere(),L},[B,d,g,p,c]),D=u.useMemo(()=>new b.ShaderMaterial({uniforms:{uTime:{value:0},uPointSize:{value:.11*c},uScale:{value:1},uOpacity:{value:.88}},vertexShader:rl,fragmentShader:uo,transparent:!0,depthWrite:!1}),[c]);return u.useLayoutEffect(()=>{const E=o.current;if(E){E.count=A;for(let L=0;L<M.length;L++){const h=M[L];h&&Ve(E,L,null,[0,h.pivotY,0],[h.lean,h.yaw,h.bend],[0,h.length*.5,0],null,[h.radius,h.length,h.radius])}E.instanceMatrix.needsUpdate=!0}const P=r.current;if(P){P.count=w;let L=0;for(const h of _)Ve(P,L++,null,[0,.14*c,0],[0,h.angle,h.spread],[0,h.length*.22,0],null,[h.radius,h.length,h.radius]);for(const h of M)Ve(P,L++,null,[0,h.pivotY,0],[h.lean,h.yaw,h.bend],[0,h.length*.76,0],[h.twigLean,h.twigYaw,h.bend*-.42],[h.radius*.52,h.twigLength,h.radius*.52]);P.instanceMatrix.needsUpdate=!0}const G=a.current;if(G){G.count=x;for(let L=0;L<j.length;L++){const h=j[L];h&&mn(G,L,null,h.position,h.rotation,h.outerScale)}G.instanceMatrix.needsUpdate=!0}const z=l.current;if(z){z.count=x;for(let L=0;L<j.length;L++){const h=j[L];h&&mn(z,L,null,h.position,h.rotation,h.innerScale)}z.instanceMatrix.needsUpdate=!0}},[M,_,j,c,A,w,x]),u.useEffect(()=>()=>{I.dispose(),F.dispose(),R.dispose(),D.dispose()},[I,F,R,D]),ae.useFrame(E=>{const P=i.current?.parent;if(P&&!P.visible)return;const G=E.clock.getElapsedTime(),z=i.current?.material;if(z?.uniforms){const L=z.uniforms.uTime,h=z.uniforms.uScale;L&&(L.value=G),h&&(h.value=E.gl.domElement.height*.5)}n.current&&(n.current.rotation.z=Math.sin(G*.42+c)*.028,n.current.rotation.x=Math.cos(G*.35+c*.6)*.012,n.current.position.x=Math.sin(G*.28+c)*.04*c)}),t.jsxs("group",{position:[0,.02,0],children:[t.jsxs("group",{position:[0,d*.5,0],rotation:[.02,0,-.04],children:[t.jsx("mesh",{geometry:f.limb,material:y.bark,scale:[.3*c,d,.3*c],castShadow:!0,receiveShadow:!0}),t.jsx("mesh",{geometry:f.trunkTop,material:y.barkDark,position:[0,d*.48,0],scale:[.24*c,.32*c,.24*c],castShadow:!0,receiveShadow:!0})]}),t.jsx("instancedMesh",{ref:o,args:[f.limb,y.bark,A]}),t.jsx("instancedMesh",{ref:r,args:[f.limb,y.barkDark,w]}),t.jsxs("group",{ref:n,children:[t.jsx("instancedMesh",{ref:a,args:[f.canopyCluster,y.blossomShell,x],castShadow:!0}),t.jsx("instancedMesh",{ref:l,args:[f.canopyCore,y.blossomCore,x]}),t.jsx("points",{geometry:I,children:t.jsx("pointsMaterial",{size:.08*c,sizeAttenuation:!0,vertexColors:!0,transparent:!0,opacity:.82,depthWrite:!1})})]}),t.jsx("points",{ref:i,geometry:R,material:D,frustumCulled:!1}),t.jsx("points",{geometry:F,children:t.jsx("pointsMaterial",{size:.085*c,sizeAttenuation:!0,vertexColors:!0,transparent:!0,opacity:.7,depthWrite:!1})})]})}const rl=`
|
|
409
|
+
attribute vec3 color;
|
|
410
|
+
attribute vec4 aParams1;
|
|
411
|
+
attribute vec2 aParams2;
|
|
412
|
+
uniform float uTime;
|
|
413
|
+
uniform float uPointSize;
|
|
414
|
+
uniform float uScale;
|
|
415
|
+
varying vec3 vColor;
|
|
416
|
+
void main() {
|
|
417
|
+
float cycle = fract(uTime * aParams1.x + aParams1.y);
|
|
418
|
+
float drift = 1.0 - pow(cycle, 1.22);
|
|
419
|
+
float w = uTime * aParams1.w + aParams1.y * 6.28318;
|
|
420
|
+
vec3 pos = vec3(
|
|
421
|
+
position.x + sin(w) * aParams1.z + aParams2.x * cycle,
|
|
422
|
+
0.18 + position.y * drift + sin(w * 0.6) * 0.06,
|
|
423
|
+
position.z + cos(w * 0.82) * aParams1.z * 0.72 + aParams2.y * cycle
|
|
424
|
+
);
|
|
425
|
+
vColor = color;
|
|
426
|
+
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
|
|
427
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
428
|
+
gl_PointSize = uPointSize * (uScale / -mvPosition.z);
|
|
429
|
+
}
|
|
430
|
+
`;let nn=null;function al(){try{const e="/";if(e){const s=e.endsWith("/")?e:`${e}/`;return new URL(`${s}wasm/gaesup_core.wasm`,document.baseURI).toString()}if(typeof document<"u"&&typeof document.baseURI=="string"&&document.baseURI.length>0)return`${new URL(document.baseURI).origin}/wasm/gaesup_core.wasm`}catch{}return"/wasm/gaesup_core.wasm"}async function mo(){return typeof WebAssembly>"u"?null:nn||(nn=(async()=>{try{const e=al(),s=await fetch(e);if(!s.ok)return null;const n=await s.arrayBuffer(),{instance:i}=await WebAssembly.instantiate(n,{}),o=i.exports;return!o||!(o.memory instanceof WebAssembly.Memory)||typeof o.alloc_f32!="function"||typeof o.dealloc_f32!="function"?null:o}catch{return null}})(),nn)}const Se=2e3,ll=800,we=20,ps=20,cl=3,ul=`
|
|
431
|
+
attribute float aSeed;
|
|
432
|
+
attribute float aBaseX;
|
|
433
|
+
attribute float aBaseZ;
|
|
434
|
+
attribute float aFallSpeed;
|
|
435
|
+
attribute float aDriftAmp;
|
|
436
|
+
|
|
437
|
+
uniform float uTime;
|
|
438
|
+
uniform vec3 uOrigin;
|
|
439
|
+
uniform float uHalfRange;
|
|
440
|
+
uniform float uHeight;
|
|
441
|
+
uniform float uPointSize;
|
|
442
|
+
uniform float uScale;
|
|
443
|
+
|
|
444
|
+
void main() {
|
|
445
|
+
float fall = uHeight - mod(uTime * aFallSpeed + aSeed * uHeight * 2.0, uHeight * 1.4);
|
|
446
|
+
float dx = sin(uTime * 0.7 + aSeed * 6.2831) * aDriftAmp;
|
|
447
|
+
float dz = cos(uTime * 0.5 + aSeed * 3.1415) * aDriftAmp;
|
|
448
|
+
|
|
449
|
+
float wx = uOrigin.x + mod(aBaseX + dx - uOrigin.x + uHalfRange, uHalfRange * 2.0) - uHalfRange;
|
|
450
|
+
float wz = uOrigin.z + mod(aBaseZ + dz - uOrigin.z + uHalfRange, uHalfRange * 2.0) - uHalfRange;
|
|
451
|
+
float wy = uOrigin.y + fall - uHeight * 0.5;
|
|
452
|
+
|
|
453
|
+
vec4 mv = modelViewMatrix * vec4(wx, wy, wz, 1.0);
|
|
454
|
+
gl_Position = projectionMatrix * mv;
|
|
455
|
+
gl_PointSize = uPointSize * (uScale / -mv.z);
|
|
456
|
+
}
|
|
457
|
+
`,dl=`
|
|
458
|
+
uniform float uOpacity;
|
|
459
|
+
void main() {
|
|
460
|
+
vec2 d = gl_PointCoord - vec2(0.5);
|
|
461
|
+
float r2 = dot(d, d);
|
|
462
|
+
if (r2 > 0.25) discard;
|
|
463
|
+
gl_FragColor = vec4(1.0, 1.0, 1.0, uOpacity * exp(-r2 * 6.0));
|
|
464
|
+
}
|
|
465
|
+
`;let Tt=null;function pl(){if(Tt)return Tt;const e=document.createElement("canvas");e.width=16,e.height=16;const s=e.getContext("2d"),n=s.createRadialGradient(8,8,0,8,8,8);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(1,"rgba(255,255,255,0)"),s.fillStyle=n,s.fillRect(0,0,16,16),Tt=new b.CanvasTexture(e),Tt.needsUpdate=!0,Tt}function ml(){const e=u.useRef(null),s=u.useRef(null),n=u.useMemo(()=>{const o=new b.BufferGeometry,r=new Float32Array(Se*3),a=new Float32Array(Se),l=new Float32Array(Se),c=new Float32Array(Se),d=new Float32Array(Se),g=new Float32Array(Se);for(let p=0;p<Se;p++)r[p*3]=0,r[p*3+1]=0,r[p*3+2]=0,a[p]=Math.random(),l[p]=(Math.random()-.5)*we*2,c[p]=(Math.random()-.5)*we*2,d[p]=.5+Math.random()*1.5,g[p]=.05+Math.random()*.25;return o.setAttribute("position",new b.Float32BufferAttribute(r,3)),o.setAttribute("aSeed",new b.Float32BufferAttribute(a,1)),o.setAttribute("aBaseX",new b.Float32BufferAttribute(l,1)),o.setAttribute("aBaseZ",new b.Float32BufferAttribute(c,1)),o.setAttribute("aFallSpeed",new b.Float32BufferAttribute(d,1)),o.setAttribute("aDriftAmp",new b.Float32BufferAttribute(g,1)),o.boundingSphere=new b.Sphere(new b.Vector3,we*4),o},[]),i=u.useMemo(()=>new b.ShaderMaterial({uniforms:{uTime:{value:0},uOrigin:{value:new b.Vector3},uHalfRange:{value:we},uHeight:{value:ps},uPointSize:{value:.08},uScale:{value:1},uOpacity:{value:.85}},vertexShader:ul,fragmentShader:dl,transparent:!0,depthWrite:!1}),[]);return u.useEffect(()=>()=>{n.dispose(),i.dispose()},[n,i]),ae.useFrame(o=>{const r=e.current;if(!r)return;const a=r.parent;if(a&&!a.visible)return;const l=s.current.uniforms,c=l.uTime,d=l.uOrigin,g=l.uScale;c&&(c.value=o.clock.elapsedTime),d&&d.value.copy(o.camera.position),g&&(g.value=o.gl.domElement.height*.5)}),t.jsx("points",{ref:e,geometry:n,frustumCulled:!1,children:t.jsx("primitive",{ref:s,object:i,attach:"material"})})}function Ns({gpu:e}={}){return e?t.jsx(ml,{}):t.jsx(fl,{})}function fl(){const e=u.useRef(null),s=u.useRef(new Float32Array(Se*3)),n=u.useRef(new Float32Array(Se*3)),i=u.useRef(null),o=u.useRef(null),r=u.useMemo(()=>new Float32Array(6),[]),a=u.useRef(0);u.useEffect(()=>{const d=s.current,g=n.current;for(let y=0;y<Se;y++)d[y*3]=(Math.random()-.5)*we*2,d[y*3+1]=Math.random()*ps,d[y*3+2]=(Math.random()-.5)*we*2,g[y*3]=0,g[y*3+1]=-(.5+Math.random()*1.5),g[y*3+2]=0;let p=0,m=0,f=0;return mo().then(y=>{if(!y)return;i.current=y;const M=Se*3;p=y.alloc_f32(M),m=y.alloc_f32(M),f=y.alloc_f32(6),new Float32Array(y.memory.buffer,p,M).set(d),new Float32Array(y.memory.buffer,m,M).set(g),o.current={p,v:m,b:f}}),()=>{const y=i.current;y&&(p&&y.dealloc_f32(p,Se*3),m&&y.dealloc_f32(m,Se*3),f&&y.dealloc_f32(f,6))}},[]),ae.useFrame((d,g)=>{const p=e.current?.parent;if(p&&!p.visible)return;const m=d.camera.position;r[0]=m.x-we,r[1]=m.x+we,r[2]=m.y-5,r[3]=m.y+ps,r[4]=m.z-we,r[5]=m.z+we;const f=Math.min(g,.05),y=i.current,M=o.current,_=s.current,j=n.current,w=a.current++%cl===0,x=e.current;if(x)if(y&&M){new Float32Array(y.memory.buffer,M.b,6).set(r),y.update_snow_particles(Se,M.p,M.v,M.b,.3,0,0,2,.01,f);const T=new Float32Array(y.memory.buffer,M.p,Se*3),C=x.geometry.attributes.position;if(!(C instanceof b.BufferAttribute))return;C.array=T,C.needsUpdate=!0}else{const T=w?Se:ll;for(let B=0;B<T;B++){const I=B*3,F=j[I],R=j[I+1],D=j[I+2],E=_[I],P=_[I+1],G=_[I+2],z=r[0],L=r[1],h=r[2],k=r[3],U=r[4],W=r[5];if(F===void 0||R===void 0||D===void 0||E===void 0||P===void 0||G===void 0||z===void 0||L===void 0||h===void 0||k===void 0||U===void 0||W===void 0)continue;const Z=F*.99+.3*f;let Y=R-2*f;const $=D*.99;let J=E+Z*f,ee=P+Y*f,te=G+$*f;J<z?J+=we*2:J>L&&(J-=we*2),ee<h&&(ee=k,Y=-(.5+Math.random()*1.5)),te<U?te+=we*2:te>W&&(te-=we*2),j[I]=Z,j[I+1]=Y,j[I+2]=$,_[I]=J,_[I+1]=ee,_[I+2]=te}const C=x.geometry.attributes.position;if(!(C instanceof b.BufferAttribute))return;C.needsUpdate=!0}});const l=u.useMemo(()=>{const d=new b.BufferGeometry,g=new b.Float32BufferAttribute(s.current,3);return g.setUsage(b.DynamicDrawUsage),d.setAttribute("position",g),d},[]),c=u.useMemo(()=>new b.PointsMaterial({size:.08,map:pl(),transparent:!0,opacity:.85,depthWrite:!1}),[]);return u.useEffect(()=>()=>{l.dispose(),c.dispose()},[l,c]),t.jsx("points",{ref:e,geometry:l,material:c,frustumCulled:!1})}u.memo(Ns);function hl(){const e=S.useBuildingStore(x=>x.editMode),s=S.useBuildingStore(x=>x.hoverPosition),n=S.useBuildingStore(x=>x.checkTilePosition),i=S.useBuildingStore(x=>x.currentTileMultiplier),o=S.useBuildingStore(x=>x.currentTileHeight),r=S.useBuildingStore(x=>x.currentTileShape),a=S.useBuildingStore(x=>x.currentTileRotation),l=S.useBuildingStore(x=>x.currentObjectRotation),c=S.useBuildingStore(x=>x.selectedPlacedObjectType),d=S.TILE_CONSTANTS.GRID_CELL_SIZE*i,p=(r==="stairs"||r==="ramp"?Math.max(1,o):o)*S.TILE_CONSTANTS.HEIGHT_STEP,m=Math.max(.12,p+.12),f=b.MathUtils.clamp(d/S.TILE_CONSTANTS.GRID_CELL_SIZE,.95,1.85),y=u.useMemo(()=>{const x=new b.BufferGeometry,T=new Float32Array([-.5,0,-.5,.5,0,-.5,-.5,0,.5,.5,0,.5,-.5,1,.5,.5,1,.5]),C=[0,1,3,0,3,2,0,1,5,0,5,4,0,2,4,1,5,3,2,3,5,2,5,4];return x.setAttribute("position",new b.BufferAttribute(T,3)),x.setIndex(C),x.computeVertexNormals(),x},[]);if(u.useEffect(()=>()=>{y.dispose()},[y]),e!=="tile"&&e!=="object"||!s)return null;const M=e==="tile"&&(r==="box"||r==="round")?s.y+o*S.TILE_CONSTANTS.HEIGHT_STEP:s.y,_=e==="tile"?n({x:s.x,y:M,z:s.z}):!1,j=_?"#f3b95f":"#7dd3fc",A=_?.3:.38,w=_?.08:.12;return t.jsxs("group",{position:[s.x,M,s.z],rotation:[0,e==="object"?l:a,0],children:[e==="tile"&&(r==="round"?t.jsxs("mesh",{position:[0,p>.02?p/2:-.02,0],children:[t.jsx("cylinderGeometry",{args:[d/2,d/2,p>.02?p:.04,24]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:A,emissive:j,emissiveIntensity:w})]}):r==="stairs"?t.jsx(t.Fragment,{children:Array.from({length:4},(x,T)=>{const B=Math.max(S.TILE_CONSTANTS.HEIGHT_STEP,p)/4,I=d/4,F=B*(T+1)-B/2,R=-d/2+I*T+I/2;return t.jsxs("mesh",{position:[0,F,R],children:[t.jsx("boxGeometry",{args:[d,B*(T+1),I]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:A,emissive:j,emissiveIntensity:w})]},T)})}):r==="ramp"?t.jsx("mesh",{position:[0,0,0],scale:[d,Math.max(S.TILE_CONSTANTS.HEIGHT_STEP,p),d],geometry:y,children:t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:A,emissive:j,emissiveIntensity:w})}):t.jsxs("mesh",{position:[0,m/2,0],children:[t.jsx("boxGeometry",{args:[d,m,d]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:A,emissive:j,emissiveIntensity:w})]})),e==="object"&&t.jsxs("mesh",{position:[0,.06,0],children:[t.jsx("cylinderGeometry",{args:[.35,.35,.12,16]}),t.jsx("meshStandardMaterial",{color:"#7dd3fc",transparent:!0,opacity:.38,emissive:"#2f8dbd",emissiveIntensity:.12})]}),e==="object"&&c==="sakura"&&t.jsxs("group",{position:[0,Math.max(p,.04),0],children:[t.jsxs("mesh",{position:[0,1.9*f,0],children:[t.jsx("cylinderGeometry",{args:[.16*f,.28*f,3.8*f,8]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:.32,emissive:j,emissiveIntensity:.15})]}),t.jsxs("mesh",{position:[0,4*f,0],children:[t.jsx("sphereGeometry",{args:[1.55*f,10,8]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:.18,emissive:j,emissiveIntensity:.18})]}),t.jsxs("mesh",{position:[.95*f,3.55*f,.4*f],children:[t.jsx("sphereGeometry",{args:[.92*f,8,6]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:.14,emissive:j,emissiveIntensity:.12})]}),t.jsxs("mesh",{position:[-.88*f,3.7*f,-.55*f],children:[t.jsx("sphereGeometry",{args:[1.02*f,8,6]}),t.jsx("meshStandardMaterial",{color:j,transparent:!0,opacity:.14,emissive:j,emissiveIntensity:.12})]})]})]})}function gl(){const e=S.useBuildingStore(d=>d.editMode),s=S.useBuildingStore(d=>d.hoverPosition),n=S.useBuildingStore(d=>d.currentWallRotation),i=S.useBuildingStore(d=>d.checkWallPosition),o=S.TILE_CONSTANTS.WALL_SIZES.WIDTH,r=S.TILE_CONSTANTS.WALL_SIZES.HEIGHT,a=S.TILE_CONSTANTS.WALL_SIZES.THICKNESS;if(e!=="wall"||!s)return null;const l=i(s,n),c=l?"#f3b95f":"#7dd3fc";return t.jsx("group",{position:[s.x,s.y+r/2,s.z],rotation:[0,n,0],children:t.jsxs("mesh",{position:[0,0,o/2],children:[t.jsx("boxGeometry",{args:[o,r,a]}),t.jsx("meshStandardMaterial",{color:c,transparent:!0,opacity:l?.34:.42,emissive:c,emissiveIntensity:l?.08:.14})]})})}const hn=bs.createNoise2D();let Kn=null,Jn=null;function fo(e){return e?(Kn||(Kn=S.createToonMaterial({vertexColors:!0,steps:4})),Kn):(Jn||(Jn=new b.MeshStandardMaterial({vertexColors:!0,roughness:1,metalness:.02})),Jn)}function Xe(e){const s=Math.sin(e*127.1+311.7)*43758.5453123;return s-Math.floor(s)}function gn(e,s,n){const i=Math.max(n,1),o=hn(e/(i*.8),s/(i*.8))*.07,r=hn(e/(i*.32)+8.3,s/(i*.42)-5.4)*.025,a=Math.sin(e*1.35+s*.42)*.01,l=Math.exp(-(((e+i*.18)*(e+i*.18)+(s-i*.08)*(s-i*.08))/Math.max(i*i*.55,1)))*.09,c=Math.exp(-(((e-i*.24)*(e-i*.24)+(s+i*.16)*(s+i*.16))/Math.max(i*i*.7,1)))*.05;return .025+o+r+a+l+c}function bl(e){let s=0,n=0,i=0;const o=[],r=[];for(const j of e){const A=Math.max(20,Math.round(j.size*6));o.push(A),s+=(A+1)*(A+1),n+=A*A*6;const w=Math.max(90,Math.min(240,Math.round(j.size*j.size*10)));r.push(w),i+=w}const a=new Float32Array(s*3),l=new Float32Array(s*3),c=new Uint32Array(n);let d=0,g=0;for(let j=0;j<e.length;j++){const A=e[j],w=o[j];if(!A||w===void 0)continue;const x=A.size,T=A.position[0],C=A.position[1]+.04,B=A.position[2],I=new b.Color(A.color??"#b89b66"),F=new b.Color(A.accentColor??"#e0c27a"),R=new b.Color;for(let D=0;D<=w;D++)for(let E=0;E<=w;E++){const P=d+D*(w+1)+E,G=(E/w-.5)*x,z=(D/w-.5)*x,L=gn(G,z,x),h=.5+.5*hn(G*.22+5.1,z*.22-3.6),k=P*3;a[k]=G+T,a[k+1]=L+C,a[k+2]=z+B,R.copy(I).lerp(F,h*.45).multiplyScalar(.86+h*.18),l[k]=R.r,l[k+1]=R.g,l[k+2]=R.b}for(let D=0;D<w;D++)for(let E=0;E<w;E++){const P=d+D*(w+1)+E,G=P+1,z=P+(w+1),L=z+1;c[g++]=P,c[g++]=z,c[g++]=G,c[g++]=G,c[g++]=z,c[g++]=L}d+=(w+1)*(w+1)}const p=new b.BufferGeometry;p.setAttribute("position",new b.Float32BufferAttribute(a,3)),p.setAttribute("color",new b.Float32BufferAttribute(l,3)),p.setIndex(new b.BufferAttribute(c,1)),p.computeVertexNormals(),p.computeBoundingSphere();const m=new Float32Array(i*3),f=new Float32Array(i*3);let y=0;for(let j=0;j<e.length;j++){const A=e[j],w=r[j];if(!A||w===void 0)continue;const x=A.size,T=A.position[0],C=A.position[1]+.04,B=A.position[2],I=new b.Color(A.color??"#b89b66"),F=new b.Color(A.accentColor??"#e0c27a"),R=new b.Color;for(let D=0;D<w;D++){const E=(y+D)*3,P=Xe(D*3.13+.2)*x-x*.5,G=Xe(D*4.71+1.4)*x-x*.5,z=Xe(D*5.93+2.8),L=Xe(D*2.37+.9),h=gn(P,G,x)+.01+z*.015;m[E]=P+T,m[E+1]=h+C,m[E+2]=G+B,R.copy(I).lerp(F,L*.55).multiplyScalar(.92+L*.12),f[E]=R.r,f[E+1]=R.g,f[E+2]=R.b}y+=w}const M=new b.BufferGeometry;M.setAttribute("position",new b.Float32BufferAttribute(m,3)),M.setAttribute("color",new b.Float32BufferAttribute(f,3)),M.computeBoundingSphere();const _=e.length>0?e.reduce((j,A)=>j+A.size,0)/e.length:4;return[p,M,_]}function ho({entries:e,toon:s}){const[n,i,o]=u.useMemo(()=>bl(e),[e]),r=s??S.getDefaultToonMode(),a=fo(r);return u.useEffect(()=>()=>{n.dispose(),i.dispose()},[n,i]),e.length===0?null:t.jsxs(t.Fragment,{children:[t.jsx("mesh",{geometry:n,material:a,castShadow:!0,receiveShadow:!0}),t.jsx("points",{geometry:i,children:t.jsx("pointsMaterial",{size:Math.max(.02,o*.008),vertexColors:!0,transparent:!0,opacity:.85,depthWrite:!1})})]})}function xl({size:e=4,toon:s,color:n,accentColor:i}){const o=s??S.getDefaultToonMode(),r=fo(o),[a,l]=u.useMemo(()=>{const c=Math.max(20,Math.round(e*6)),d=new b.PlaneGeometry(e,e,c,c);d.rotateX(-Math.PI/2);const g=d.getAttribute("position"),p=new Float32Array(g.count*3),m=new b.Color,f=new b.Color(n??"#b89b66"),y=new b.Color(i??"#e0c27a");for(let w=0;w<g.count;w++){const x=g.getX(w),T=g.getZ(w),C=gn(x,T,e),B=.5+.5*hn(x*.22+5.1,T*.22-3.6);g.setY(w,C),m.copy(f).lerp(y,B*.45).multiplyScalar(.86+B*.18),p[w*3]=m.r,p[w*3+1]=m.g,p[w*3+2]=m.b}d.setAttribute("color",new b.Float32BufferAttribute(p,3)),d.computeVertexNormals();const M=Math.max(90,Math.min(240,Math.round(e*e*10))),_=new Float32Array(M*3),j=new Float32Array(M*3);for(let w=0;w<M;w++){const x=Xe(w*3.13+.2)*e-e*.5,T=Xe(w*4.71+1.4)*e-e*.5,C=Xe(w*5.93+2.8),B=Xe(w*2.37+.9),I=gn(x,T,e)+.01+C*.015;_[w*3]=x,_[w*3+1]=I,_[w*3+2]=T,m.copy(f).lerp(y,B*.55).multiplyScalar(.92+B*.12),j[w*3]=m.r,j[w*3+1]=m.g,j[w*3+2]=m.b}const A=new b.BufferGeometry;return A.setAttribute("position",new b.Float32BufferAttribute(_,3)),A.setAttribute("color",new b.Float32BufferAttribute(j,3)),[d,A]},[i,n,e]);return u.useEffect(()=>()=>{a.dispose(),l.dispose()},[l,a]),t.jsxs("group",{position:[0,.04,0],children:[t.jsx("mesh",{geometry:a,material:r,castShadow:!0,receiveShadow:!0}),t.jsx("points",{geometry:l,frustumCulled:!1,children:t.jsx("pointsMaterial",{size:Math.max(.02,e*.008),vertexColors:!0,transparent:!0,opacity:.85,depthWrite:!1})})]})}const bn=bs.createNoise2D();let Qn=null,es=null;function go(e){return e?(Qn||(Qn=S.createToonMaterial({vertexColors:!0,steps:4,emissive:"#9ec1e8",emissiveIntensity:.06})),Qn):(es||(es=new b.MeshPhysicalMaterial({vertexColors:!0,roughness:.88,metalness:0,clearcoat:.12,clearcoatRoughness:.75})),es)}function qe(e){const s=Math.sin(e*91.7+173.3)*43758.5453123;return s-Math.floor(s)}function xn(e,s,n){const i=Math.max(n,1),o=Math.exp(-(((e+i*.2)*(e+i*.2)+(s-i*.14)*(s-i*.14))/Math.max(i*i*.48,1)))*.12,r=Math.exp(-(((e-i*.18)*(e-i*.18)+(s+i*.12)*(s+i*.12))/Math.max(i*i*.65,1)))*.08,a=bn(e/(i*.7),s/(i*.7))*.06,l=bn(e/(i*.24)+6.1,s/(i*.24)-3.7)*.018;return .05+o+r+a+l}function vl(e){let s=0,n=0,i=0;const o=[],r=[];for(const j of e){const A=Math.max(22,Math.round(j.size*7));o.push(A),s+=(A+1)*(A+1),n+=A*A*6;const w=Math.max(28,Math.min(96,Math.round(j.size*j.size*3)));r.push(w),i+=w}const a=new Float32Array(s*3),l=new Float32Array(s*3),c=new Uint32Array(n);let d=0,g=0;for(let j=0;j<e.length;j++){const A=e[j],w=o[j];if(!A||w===void 0)continue;const x=A.size,T=A.position[0],C=A.position[1]+.045,B=A.position[2],I=new b.Color(A.color??"#dcecff"),F=new b.Color(A.accentColor??"#ffffff"),R=new b.Color;for(let D=0;D<=w;D++)for(let E=0;E<=w;E++){const P=d+D*(w+1)+E,G=(E/w-.5)*x,z=(D/w-.5)*x,L=xn(G,z,x),h=.5+.5*bn(G*.16-2.4,z*.16+7.2),k=P*3;a[k]=G+T,a[k+1]=L+C,a[k+2]=z+B,R.copy(I).lerp(F,h*.55).multiplyScalar(.9+h*.1),l[k]=R.r,l[k+1]=R.g,l[k+2]=R.b}for(let D=0;D<w;D++)for(let E=0;E<w;E++){const P=d+D*(w+1)+E,G=P+1,z=P+(w+1),L=z+1;c[g++]=P,c[g++]=z,c[g++]=G,c[g++]=G,c[g++]=z,c[g++]=L}d+=(w+1)*(w+1)}const p=new b.BufferGeometry;p.setAttribute("position",new b.Float32BufferAttribute(a,3)),p.setAttribute("color",new b.Float32BufferAttribute(l,3)),p.setIndex(new b.BufferAttribute(c,1)),p.computeVertexNormals(),p.computeBoundingSphere();const m=new Float32Array(i*3),f=new Float32Array(i*3);let y=0;for(let j=0;j<e.length;j++){const A=e[j],w=r[j];if(!A||w===void 0)continue;const x=A.size,T=A.position[0],C=A.position[1]+.045,B=A.position[2],I=new b.Color(A.color??"#dcecff"),F=new b.Color(A.accentColor??"#ffffff"),R=new b.Color;for(let D=0;D<w;D++){const E=(y+D)*3,P=qe(D*2.71+.4)*x-x*.5,G=qe(D*3.97+1.9)*x-x*.5,z=qe(D*5.41+2.2),L=qe(D*7.13+3.1),h=xn(P,G,x)+.016+z*.02;m[E]=P+T,m[E+1]=h+C,m[E+2]=G+B,R.copy(I).lerp(F,.6+L*.4),f[E]=R.r,f[E+1]=R.g,f[E+2]=R.b}y+=w}const M=new b.BufferGeometry;M.setAttribute("position",new b.Float32BufferAttribute(m,3)),M.setAttribute("color",new b.Float32BufferAttribute(f,3)),M.computeBoundingSphere();const _=e.length>0?e.reduce((j,A)=>j+A.size,0)/e.length:4;return[p,M,_]}function bo({entries:e,toon:s}){const[n,i,o]=u.useMemo(()=>vl(e),[e]),r=s??S.getDefaultToonMode(),a=go(r);return u.useEffect(()=>()=>{n.dispose(),i.dispose()},[n,i]),e.length===0?null:t.jsxs(t.Fragment,{children:[t.jsx("mesh",{geometry:n,material:a,castShadow:!0,receiveShadow:!0}),t.jsx("points",{geometry:i,children:t.jsx("pointsMaterial",{size:Math.max(.03,o*.01),vertexColors:!0,transparent:!0,opacity:.55,depthWrite:!1})})]})}function yl({size:e=4,toon:s,color:n,accentColor:i}){const o=s??S.getDefaultToonMode(),r=go(o),[a,l]=u.useMemo(()=>{const c=Math.max(22,Math.round(e*7)),d=new b.PlaneGeometry(e,e,c,c);d.rotateX(-Math.PI/2);const g=d.getAttribute("position"),p=new Float32Array(g.count*3),m=new b.Color,f=new b.Color(n??"#dcecff"),y=new b.Color(i??"#ffffff");for(let w=0;w<g.count;w++){const x=g.getX(w),T=g.getZ(w),C=xn(x,T,e),B=.5+.5*bn(x*.16-2.4,T*.16+7.2);g.setY(w,C),m.copy(f).lerp(y,B*.55).multiplyScalar(.9+B*.1),p[w*3]=m.r,p[w*3+1]=m.g,p[w*3+2]=m.b}d.setAttribute("color",new b.Float32BufferAttribute(p,3)),d.computeVertexNormals();const M=Math.max(28,Math.min(96,Math.round(e*e*3))),_=new Float32Array(M*3),j=new Float32Array(M*3);for(let w=0;w<M;w++){const x=qe(w*2.71+.4)*e-e*.5,T=qe(w*3.97+1.9)*e-e*.5,C=qe(w*5.41+2.2),B=qe(w*7.13+3.1),I=xn(x,T,e)+.016+C*.02;_[w*3]=x,_[w*3+1]=I,_[w*3+2]=T,m.copy(f).lerp(y,.6+B*.4),j[w*3]=m.r,j[w*3+1]=m.g,j[w*3+2]=m.b}const A=new b.BufferGeometry;return A.setAttribute("position",new b.Float32BufferAttribute(_,3)),A.setAttribute("color",new b.Float32BufferAttribute(j,3)),[d,A]},[e,i,n]);return u.useEffect(()=>()=>{a.dispose(),l.dispose()},[l,a]),t.jsxs("group",{position:[0,.045,0],children:[t.jsx("mesh",{geometry:a,material:r,castShadow:!0,receiveShadow:!0}),t.jsx("points",{geometry:l,frustumCulled:!1,children:t.jsx("pointsMaterial",{size:Math.max(.03,e*.01),vertexColors:!0,transparent:!0,opacity:.55,depthWrite:!1})})]})}const Sl="/resources/blade_alpha.jpg",Ml="/resources/blade_diffuse.jpg";function jl(e={}){return{bladeDiffuseUrl:e.bladeDiffuseUrl??Ml,bladeAlphaUrl:e.bladeAlphaUrl??Sl}}var wl=`precision highp float;\r
|
|
466
|
+
uniform sampler2D map;\r
|
|
467
|
+
uniform sampler2D alphaMap;\r
|
|
468
|
+
uniform vec3 tipColor;\r
|
|
469
|
+
uniform vec3 bottomColor;\r
|
|
470
|
+
uniform float uToon;\r
|
|
471
|
+
uniform float uToonSteps;\r
|
|
472
|
+
varying vec2 vUv;\r
|
|
473
|
+
varying float frc;\r
|
|
474
|
+
varying float vCluster;\r
|
|
475
|
+
varying float vDryness;\r
|
|
476
|
+
varying float vShade;
|
|
477
|
+
|
|
478
|
+
void main() {\r
|
|
479
|
+
float alpha = texture2D(alphaMap, vUv).r;\r
|
|
480
|
+
if(alpha < 0.15)\r
|
|
481
|
+
discard;\r
|
|
482
|
+
vec3 warmBottom = vec3(0.30, 0.23, 0.08);\r
|
|
483
|
+
vec3 warmTip = vec3(0.80, 0.74, 0.34);\r
|
|
484
|
+
vec3 coolBottom = vec3(0.18, 0.31, 0.12);\r
|
|
485
|
+
vec3 coolTip = vec3(0.63, 0.82, 0.42);\r
|
|
486
|
+
vec3 lushBottom = mix(bottomColor, coolBottom, vCluster * 0.35);\r
|
|
487
|
+
vec3 lushTip = mix(tipColor, coolTip, vCluster * 0.28);\r
|
|
488
|
+
vec3 dryBottom = mix(lushBottom, warmBottom, vDryness * 0.85);\r
|
|
489
|
+
vec3 dryTip = mix(lushTip, warmTip, vDryness);
|
|
490
|
+
|
|
491
|
+
float frcStepped = mix(smoothstep(0.0, 1.0, frc), floor(frc * uToonSteps) / max(uToonSteps - 1.0, 1.0), uToon);\r
|
|
492
|
+
vec3 bladeGradient = mix(dryBottom, dryTip, frcStepped);\r
|
|
493
|
+
vec3 tex = texture2D(map, vUv).rgb;\r
|
|
494
|
+
float rib = 1.0 - smoothstep(0.0, 0.52, abs(vUv.x - 0.5));\r
|
|
495
|
+
vec3 color = mix(bladeGradient * 0.72, tex * bladeGradient, mix(0.62, 0.35, uToon));\r
|
|
496
|
+
color *= mix(0.9, 1.1, vCluster);\r
|
|
497
|
+
color *= mix(1.0, 0.82, vDryness * 0.35);\r
|
|
498
|
+
color *= mix(0.94, 1.05, rib);
|
|
499
|
+
|
|
500
|
+
float shadeStepped = mix(vShade, floor(vShade * uToonSteps) / max(uToonSteps - 1.0, 1.0), uToon);\r
|
|
501
|
+
color *= shadeStepped;
|
|
502
|
+
|
|
503
|
+
vec4 col = vec4(color, 1.0);\r
|
|
504
|
+
vec3 reinhard = col.rgb / (col.rgb + vec3(1.0));\r
|
|
505
|
+
vec3 simple = clamp(col.rgb, 0.0, 1.0);\r
|
|
506
|
+
col.rgb = mix(reinhard, simple, uToon);\r
|
|
507
|
+
col.rgb = pow(col.rgb, vec3(1.0 / 2.2));
|
|
508
|
+
|
|
509
|
+
gl_FragColor = col;\r
|
|
510
|
+
}`;let xo=null;function _l(e){xo=e}class Cl{nextId=1;tiles=new Map;positions=new Float32Array(0);weights=new Float32Array(0);trampleWorld=new b.Vector3(0,-9999,0);trampleStrength=0;lastSampleAt=0;register(s){this.tiles.size===0&&(this.lastSampleAt=0);const n=this.nextId++,i={...s,id:n};return this.tiles.set(n,i),this.ensureCapacity(this.tiles.size),i}update(s,n){const i=this.tiles.get(s);i&&Object.assign(i,n)}unregister(s){this.tiles.delete(s),this.tiles.size===0&&(this.lastSampleAt=0)}size(){return this.tiles.size}tick(s){if(this.tiles.size===0)return;const n=performance.now();if(n-this.lastSampleAt<12)return;this.lastSampleAt=n,this.refreshTrample(s.delta);const i=this.computeWindScale(),o=s.elapsedTime/4;this.ensureCapacity(this.tiles.size);let r=0;const a=[];for(const c of this.tiles.values()){const d=r*3;this.positions[d]=c.center.x,this.positions[d+1]=c.center.y,this.positions[d+2]=c.center.z,a.push(c.id),r+=1}this.computeWeights(a.length,s.cameraPosition);let l=0;for(const c of a){const d=this.tiles.get(c);if(!d){l+=1;continue}let g=this.weights[l]??0;l+=1;const p=Math.hypot(d.width,d.height)*.6,m=Tl.set(d.center,p),f=s.frustum.intersectsSphere(m);if(d.lod){const _=d.center.distanceTo(s.cameraPosition);g=Ks(_,d.lod.near??24,d.lod.far??160,d.lod.strength??4)}const y=Math.max(0,Math.floor(d.maxInstances*g)),M=f&&y>0;d.apply({visible:M,instanceCount:M?y:0,time:o,windScale:i,trampleCenter:this.trampleWorld,trampleStrength:this.trampleStrength})}}ensureCapacity(s){this.positions.length<s*3&&(this.positions=new Float32Array(s*3)),this.weights.length<s&&(this.weights=new Float32Array(s))}computeWeights(s,n){const i=xo,o=24,r=160,a=4;if(i)try{const l=i.alloc_f32(s*3),c=i.alloc_f32(s);try{new Float32Array(i.memory.buffer,l,s*3).set(this.positions.subarray(0,s*3)),i.batch_sfe_weights(s,l,n.x,n.y,n.z,o,r,a,c),this.weights.set(new Float32Array(i.memory.buffer,c,s))}finally{i.dealloc_f32(l,s*3),i.dealloc_f32(c,s)}return}catch{}for(let l=0;l<s;l+=1){const c=l*3,d=(this.positions[c]??0)-n.x,g=(this.positions[c+1]??0)-n.y,p=(this.positions[c+2]??0)-n.z,m=Math.sqrt(d*d+g*g+p*p);this.weights[l]=Ks(m,o,r,a)}}refreshTrample(s){const n=re.BridgeFactory.getOrCreate("motion"),i=n?.getActiveEntities()??[],o=i[0]?n?.snapshot(i[0]):null,r=b.MathUtils.clamp(s*6,0,1);o&&(this.trampleWorld.x+=(o.position.x-this.trampleWorld.x)*r,this.trampleWorld.y=o.position.y,this.trampleWorld.z+=(o.position.z-this.trampleWorld.z)*r);const a=o?.isMoving&&o?.isGrounded?.85:.35;this.trampleStrength+=(a-this.trampleStrength)*r}computeWindScale(){const s=oi.useWeatherStore.getState().current,n=s?.intensity??0;return(s?.kind==="storm"?2.6:s?.kind==="rain"?1.7:s?.kind==="snow"?1.3:s?.kind==="cloudy"?1.15:.85)+n*.9}}const Tl=new b.Sphere;function Ks(e,s,n,i){if(e<=s)return 1;if(e>=n)return 0;const o=(e-s)/(n-s);return Math.pow(1-o,Math.max(1,i))}let ts=null;function zt(){return ts||(ts=new Cl),ts}var Nl=`precision highp float;\r
|
|
511
|
+
attribute vec3 offset;\r
|
|
512
|
+
attribute vec4 orientation;\r
|
|
513
|
+
attribute float halfRootAngleSin;\r
|
|
514
|
+
attribute float halfRootAngleCos;\r
|
|
515
|
+
attribute float stretch;\r
|
|
516
|
+
uniform float time;\r
|
|
517
|
+
uniform float windScale;\r
|
|
518
|
+
uniform float bladeHeight;\r
|
|
519
|
+
uniform vec3 trampleCenter;\r
|
|
520
|
+
uniform float trampleRadius;\r
|
|
521
|
+
uniform float trampleStrength;\r
|
|
522
|
+
varying vec2 vUv;\r
|
|
523
|
+
varying float frc;\r
|
|
524
|
+
varying float vCluster;\r
|
|
525
|
+
varying float vDryness;\r
|
|
526
|
+
varying float vShade;
|
|
527
|
+
|
|
528
|
+
vec3 mod289(vec3 x) {\r
|
|
529
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;\r
|
|
530
|
+
}\r
|
|
531
|
+
vec2 mod289(vec2 x) {\r
|
|
532
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;\r
|
|
533
|
+
}\r
|
|
534
|
+
vec3 permute(vec3 x) {\r
|
|
535
|
+
return mod289(((x * 34.0) + 1.0) * x);\r
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
float snoise(vec2 v) {\r
|
|
539
|
+
const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\r
|
|
540
|
+
vec2 i = floor(v + dot(v, C.yy));\r
|
|
541
|
+
vec2 x0 = v - i + dot(i, C.xx);\r
|
|
542
|
+
vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\r
|
|
543
|
+
vec4 x12 = x0.xyxy + C.xxzz;\r
|
|
544
|
+
x12.xy -= i1;\r
|
|
545
|
+
i = mod289(i);\r
|
|
546
|
+
vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));\r
|
|
547
|
+
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);\r
|
|
548
|
+
m = m * m;\r
|
|
549
|
+
m = m * m;\r
|
|
550
|
+
vec3 x = 2.0 * fract(p * C.www) - 1.0;\r
|
|
551
|
+
vec3 h = abs(x) - 0.5;\r
|
|
552
|
+
vec3 ox = floor(x + 0.5);\r
|
|
553
|
+
vec3 a0 = x - ox;\r
|
|
554
|
+
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\r
|
|
555
|
+
vec3 g;\r
|
|
556
|
+
g.x = a0.x * x0.x + h.x * x0.y;\r
|
|
557
|
+
g.yz = a0.yz * x12.xz + h.yz * x12.yw;\r
|
|
558
|
+
return 130.0 * dot(m, g);\r
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
vec3 rotateVectorByQuaternion(vec3 v, vec4 q) {\r
|
|
562
|
+
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\r
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
void main() {\r
|
|
566
|
+
frc = position.y / float(bladeHeight);\r
|
|
567
|
+
float clusterNoise = snoise(offset.xz * 0.11 + vec2(3.7, -8.2));\r
|
|
568
|
+
float dryNoise = snoise(offset.xz * 0.18 + vec2(-5.4, 12.6));\r
|
|
569
|
+
float noise = 1.0 - snoise(vec2((time - offset.x / 50.0), (time - offset.z / 50.0)));\r
|
|
570
|
+
vec4 direction = vec4(0.0, halfRootAngleSin, 0.0, halfRootAngleCos);\r
|
|
571
|
+
vec4 tiltAxis = vec4(-orientation.z, 0.0, orientation.x, orientation.w);\r
|
|
572
|
+
vec4 bent = normalize(mix(direction, tiltAxis, frc));\r
|
|
573
|
+
vec3 vPosition = vec3(position.x, position.y + position.y * stretch, position.z);\r
|
|
574
|
+
vPosition = rotateVectorByQuaternion(vPosition, bent);
|
|
575
|
+
|
|
576
|
+
float windAngle = noise * 0.3 * windScale;\r
|
|
577
|
+
vec4 windQuat = vec4(sin(windAngle), 0.0, -sin(windAngle), cos(windAngle));\r
|
|
578
|
+
vPosition = rotateVectorByQuaternion(vPosition, windQuat);
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
if (trampleRadius > 0.0001) {\r
|
|
584
|
+
vec2 toCenter = offset.xz - trampleCenter.xz;\r
|
|
585
|
+
float distXZ = length(toCenter);\r
|
|
586
|
+
float falloff = clamp(1.0 - distXZ / trampleRadius, 0.0, 1.0);\r
|
|
587
|
+
if (falloff > 0.0) {\r
|
|
588
|
+
float push = falloff * falloff * trampleStrength;\r
|
|
589
|
+
vPosition.y *= mix(1.0, 0.18, push);\r
|
|
590
|
+
vec2 dir = distXZ > 0.0001 ? toCenter / distXZ : vec2(0.0);\r
|
|
591
|
+
vPosition.x += dir.x * push * 0.45 * frc;\r
|
|
592
|
+
vPosition.z += dir.y * push * 0.45 * frc;\r
|
|
593
|
+
}\r
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
vCluster = clusterNoise * 0.5 + 0.5;\r
|
|
597
|
+
vDryness = clamp((dryNoise * 0.5 + 0.5) * 0.7 + (1.0 - stretch) * 0.45, 0.0, 1.0);\r
|
|
598
|
+
vShade = clamp(0.82 + noise * 0.08 + orientation.w * 0.06, 0.72, 1.1);\r
|
|
599
|
+
vUv = uv;\r
|
|
600
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(offset + vPosition, 1.0);\r
|
|
601
|
+
}`;let ns=null,ss=null;function Il(e){return e?(ns||(ns=S.createToonMaterial({color:"#ffffff",vertexColors:!0,steps:3})),ns):(ss||(ss=new b.MeshStandardMaterial({color:"#ffffff",vertexColors:!0,roughness:.95,metalness:0})),ss)}const Pt=bs.createNoise2D(),Al=new b.Color("#5a7a35"),Bl=new b.Color("#7a8e3a"),El=new b.Color("#5b4628"),kl=Ge.shaderMaterial({bladeHeight:1,map:null,alphaMap:null,time:0,windScale:1,trampleCenter:new b.Vector3(0,-9999,0),trampleRadius:1.4,trampleStrength:.85,tipColor:new b.Color("#8fbc5a").convertSRGBToLinear(),bottomColor:new b.Color("#355b2d").convertSRGBToLinear(),uToon:0,uToonSteps:4},Nl,wl);ae.extend({GrassMaterial:kl});function Is(e,s){return .05*Pt(e/50,s/50)+.05*Pt(e/100,s/100)}function Rl(e,s,n){const i=s*3,o=s*4,r=e.alloc_f32(i),a=e.alloc_f32(o),l=e.alloc_f32(s),c=e.alloc_f32(s),d=e.alloc_f32(s);try{const g=Math.random()*4294967295>>>0;e.fill_grass_data(s,n,g,r,a,l,c,d);const p=e.memory.buffer;return{offsets:new Float32Array(p,r,i).slice(),orientations:new Float32Array(p,a,o).slice(),stretches:new Float32Array(p,l,s).slice(),halfRootAngleSin:new Float32Array(p,c,s).slice(),halfRootAngleCos:new Float32Array(p,d,s).slice()}}finally{e.dealloc_f32(r,i),e.dealloc_f32(a,o),e.dealloc_f32(l,s),e.dealloc_f32(c,s),e.dealloc_f32(d,s)}}function Pl(e,s){const n=new Float32Array(e*3),i=new Float32Array(e*4),o=new Float32Array(e),r=new Float32Array(e),a=new Float32Array(e),l=new b.Quaternion,c=new b.Quaternion,d=new b.Vector3(1,0,0),g=new b.Vector3(0,0,1),p=Math.ceil(Math.sqrt(e)),m=s/p,f=m*.9;let y=0,M=0;for(let _=0;_<e;_++){const j=_%p,A=_/p|0,w=(Math.random()-.5)*f,x=(Math.random()-.5)*f,T=(j+.5)*m-s/2+w,C=(A+.5)*m-s/2+x;n[y]=T,n[y+1]=Is(T,C),n[y+2]=C,y+=3;const B=Math.PI-Math.random()*(Math.PI/6);r[_]=Math.sin(.5*B),a[_]=Math.cos(.5*B),l.setFromAxisAngle(g,B),c.setFromAxisAngle(d,Math.random()*Math.PI/8),l.multiply(c),i[M]=l.x,i[M+1]=l.y,i[M+2]=l.z,i[M+3]=l.w,M+=4,o[_]=.7+Math.random()*.45}return{offsets:n,orientations:i,stretches:o,halfRootAngleCos:a,halfRootAngleSin:r}}function Dl(e,s,n){const i=Math.ceil(Math.sqrt(s)),r=n/i*.9,a=e.offsets,l=e.stretches;for(let c=0;c<s;c++){const d=c*3,g=(a[d]??0)+(Math.random()-.5)*r,p=(a[d+2]??0)+(Math.random()-.5)*r;a[d]=g,a[d+2]=p,a[d+1]=Is(g,p),l[c]=.7+Math.random()*.55}}const As=u.memo(({options:e={bW:.14,bH:.65,joints:5},width:s=4,instances:n,density:i,maxInstances:o=18e3,toon:r,lod:a,center:l,groundColor:c,groundAccentColor:d,bladeTipColor:g,bladeBottomColor:p,bladeDiffuseUrl:m,bladeAlphaUrl:f,...y})=>{const{bW:M,bH:_,joints:j}=e,A=Si($=>$.profile.instanceScale),w=u.useMemo(()=>{const $=Math.max(64,Math.min(o,Math.round(o*A)));if(typeof n=="number"&&n>0)return Math.max(1,Math.min($,Math.floor(n*A)));const J=typeof i=="number"&&i>0?i:90,ee=Math.max(1,s*s);return Math.max(64,Math.min($,Math.round(J*ee*A)))},[n,i,s,o,A]),x=r??S.getDefaultToonMode(),T=Il(x),C=u.useMemo(()=>new b.Color(c??Al),[c]),B=u.useMemo(()=>new b.Color(d??Bl),[d]),I=u.useMemo(()=>new b.Color(g??"#8fbc5a").convertSRGBToLinear(),[g]),F=u.useMemo(()=>new b.Color(p??"#355b2d").convertSRGBToLinear(),[p]),R=u.useRef(null),D=u.useRef(null),E=u.useRef(w),P=u.useRef(null),G=u.useRef(null),z=u.useMemo(()=>jl({...m?{bladeDiffuseUrl:m}:{},...f?{bladeAlphaUrl:f}:{}}),[m,f]),[L,h]=ae.useLoader(b.TextureLoader,[z.bladeDiffuseUrl,z.bladeAlphaUrl]),[k,U]=u.useState(null);u.useEffect(()=>{mo().then($=>{$&&(U($),_l($))})},[]);const W=u.useMemo(()=>{const $=k?Rl(k,w,s):Pl(w,s);return Dl($,w,s),$},[w,s,k]),[Z,Y]=u.useMemo(()=>{const $=new b.PlaneGeometry(M,_,1,j).translate(0,_/2,0),J=Math.max(8,Math.min(128,Math.round(s*1.5))),ee=new b.PlaneGeometry(s,s,J,J),te=ee.getAttribute("position"),X=new Float32Array(te.count*3),Q=new b.Color;for(let se=0;se<te.count;se++){const q=te.getX(se),ie=te.getZ(se);te.setY(se,Is(q,ie));const ue=.5+.5*Pt(q*.18,ie*.18),O=.5+.5*Pt(q*.04+11.3,ie*.04-7.7),me=.5+.5*Pt(q*.55-3.1,ie*.55+9.4),fe=b.MathUtils.clamp(ue*.65+O*.45,0,1);Q.copy(C).multiplyScalar(.58+fe*.42).lerp(B,O*.28),me>.86&&Q.lerp(El,(me-.86)*4);const xe=se*3;X[xe]=Q.r,X[xe+1]=Q.g,X[xe+2]=Q.b}return ee.setAttribute("color",new b.BufferAttribute(X,3)),ee.computeVertexNormals(),[$,ee]},[B,M,_,C,j,s]);return u.useEffect(()=>()=>{Z.dispose(),Y.dispose()},[Z,Y]),u.useEffect(()=>{const $=G.current;$&&($.instanceCount=w,E.current=w)},[w,W]),u.useEffect(()=>{const $=P.current;$?.uniforms&&($.uniforms.uToon&&($.uniforms.uToon.value=x?1:0),$.uniforms.uToonSteps&&($.uniforms.uToonSteps.value=4),$.uniforms.tipColor&&$.uniforms.tipColor.value.copy(I),$.uniforms.bottomColor&&$.uniforms.bottomColor.value.copy(F))},[F,I,x]),u.useEffect(()=>{const $=R.current,J=new b.Vector3;l?J.set(l[0],l[1],l[2]):$&&($.updateWorldMatrix(!0,!1),$.getWorldPosition(J));const ee=X=>{const Q=D.current,se=G.current,q=P.current?.uniforms;!Q||!se||!q||(Q.visible!==X.visible&&(Q.visible=X.visible),se.instanceCount!==X.instanceCount&&(se.instanceCount=X.instanceCount,E.current=X.instanceCount),q.time&&(q.time.value=X.time),q.windScale&&(q.windScale.value=X.windScale),q.trampleCenter&&q.trampleCenter.value.copy(X.trampleCenter),q.trampleStrength&&(q.trampleStrength.value=X.trampleStrength))},te=zt().register({width:s,height:_*1.4,center:J,maxInstances:w,...a?{lod:a}:{},apply:ee});return()=>{zt().unregister(te.id)}},[s,_,w,l?.[0],l?.[1],l?.[2],a?.near,a?.far,a?.strength]),u.useEffect(()=>{const $=G.current;if(!$)return;const J=Math.hypot(s,_*1.4)*.6;$.boundingSphere=new b.Sphere(new b.Vector3(0,_*.5,0),J),$.boundingBox=new b.Box3(new b.Vector3(-s*.5,0,-s*.5),new b.Vector3(s*.5,_*1.6,s*.5))},[s,_]),t.jsxs("group",{ref:R,...y,children:[t.jsxs("mesh",{ref:D,frustumCulled:!0,children:[t.jsxs("instancedBufferGeometry",{ref:G,index:Z.index,"attributes-position":Z.getAttribute("position"),"attributes-uv":Z.getAttribute("uv"),children:[t.jsx("instancedBufferAttribute",{attach:"attributes-offset",args:[W.offsets,3]}),t.jsx("instancedBufferAttribute",{attach:"attributes-orientation",args:[W.orientations,4]}),t.jsx("instancedBufferAttribute",{attach:"attributes-stretch",args:[W.stretches,1]}),t.jsx("instancedBufferAttribute",{attach:"attributes-halfRootAngleSin",args:[W.halfRootAngleSin,1]}),t.jsx("instancedBufferAttribute",{attach:"attributes-halfRootAngleCos",args:[W.halfRootAngleCos,1]})]}),t.jsx("grassMaterial",{ref:P,map:L??null,alphaMap:h??null,toneMapped:!1,side:b.DoubleSide,transparent:!0})]}),t.jsx("mesh",{position:[0,0,0],rotation:[-Math.PI/2,0,0],material:T,receiveShadow:!0,children:t.jsx("primitive",{object:Y,attach:"geometry"})})]})});As.displayName="Grass";ae.extend({Water:gs.Water});const Fl=`
|
|
602
|
+
uniform float uTime;
|
|
603
|
+
varying vec2 vUv;
|
|
604
|
+
varying vec3 vWorldPos;
|
|
605
|
+
varying float vWave;
|
|
606
|
+
|
|
607
|
+
void main() {
|
|
608
|
+
vUv = uv;
|
|
609
|
+
vec3 p = position;
|
|
610
|
+
float w1 = sin(p.x * 0.55 + uTime * 0.85) * 0.085;
|
|
611
|
+
float w2 = sin(p.y * 0.78 - uTime * 1.05 + p.x * 0.33) * 0.055;
|
|
612
|
+
float w3 = sin((p.x + p.y) * 1.40 + uTime * 1.60) * 0.025;
|
|
613
|
+
float w = w1 + w2 + w3;
|
|
614
|
+
p.z += w;
|
|
615
|
+
vWave = w;
|
|
616
|
+
vWorldPos = (modelMatrix * vec4(p, 1.0)).xyz;
|
|
617
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
|
|
618
|
+
}
|
|
619
|
+
`,Ll=`
|
|
620
|
+
uniform vec3 uShallow;
|
|
621
|
+
uniform vec3 uDeep;
|
|
622
|
+
uniform vec3 uFoam;
|
|
623
|
+
uniform float uTime;
|
|
624
|
+
varying vec2 vUv;
|
|
625
|
+
varying vec3 vWorldPos;
|
|
626
|
+
varying float vWave;
|
|
627
|
+
|
|
628
|
+
float hash21(vec2 p) {
|
|
629
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
float vnoise(vec2 p) {
|
|
633
|
+
vec2 i = floor(p);
|
|
634
|
+
vec2 f = fract(p);
|
|
635
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
636
|
+
float a = hash21(i);
|
|
637
|
+
float b = hash21(i + vec2(1.0, 0.0));
|
|
638
|
+
float c = hash21(i + vec2(0.0, 1.0));
|
|
639
|
+
float d = hash21(i + vec2(1.0, 1.0));
|
|
640
|
+
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
float fbm(vec2 p) {
|
|
644
|
+
float v = 0.0;
|
|
645
|
+
float a = 0.5;
|
|
646
|
+
for (int i = 0; i < 4; i++) {
|
|
647
|
+
v += a * vnoise(p);
|
|
648
|
+
p = p * 2.07 + vec2(13.7, 7.1);
|
|
649
|
+
a *= 0.5;
|
|
650
|
+
}
|
|
651
|
+
return v;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
float band(float v, float c, float w) {
|
|
655
|
+
return smoothstep(c - w, c, v) - smoothstep(c, c + w, v);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
void main() {
|
|
659
|
+
vec2 wp = vWorldPos.xz;
|
|
660
|
+
|
|
661
|
+
float baseNoise = fbm(wp * 0.18 + vec2(uTime * 0.04, -uTime * 0.03));
|
|
662
|
+
float depthCol = clamp(0.5 + vWave * 3.5 + (baseNoise - 0.5) * 0.55, 0.0, 1.0);
|
|
663
|
+
vec3 base = mix(uDeep, uShallow, depthCol);
|
|
664
|
+
|
|
665
|
+
float stripeCoord = (wp.x + wp.y) * 0.55 + uTime * 0.35 + baseNoise * 0.8;
|
|
666
|
+
float stripe = sin(stripeCoord * 6.0) * 0.5 + 0.5;
|
|
667
|
+
float stripeFoam = band(stripe, 0.86, 0.10) * (0.35 + depthCol * 0.65);
|
|
668
|
+
|
|
669
|
+
float specks = smoothstep(0.78, 0.95, fbm(wp * 0.62 + uTime * 0.10));
|
|
670
|
+
float ripple = smoothstep(0.60, 0.95, fbm(wp * 1.30 + uTime * 0.60));
|
|
671
|
+
|
|
672
|
+
vec3 col = mix(base, uFoam, stripeFoam * 0.55 + specks * 0.50 + ripple * 0.18);
|
|
673
|
+
|
|
674
|
+
float edge = smoothstep(0.0, 0.06, min(min(vUv.x, vUv.y), min(1.0 - vUv.x, 1.0 - vUv.y)));
|
|
675
|
+
col = mix(col * 0.86, col, edge);
|
|
676
|
+
|
|
677
|
+
gl_FragColor = vec4(col, 0.88);
|
|
678
|
+
}
|
|
679
|
+
`;function vo({lod:e,center:s,size:n=16,shore:i,toon:o}){const r=o??S.getDefaultToonMode(),a=u.useRef(null),l=u.useRef(null),c=u.useRef(null),d=Ge.useTexture("/resources/waternormals.jpeg"),g=u.useRef(new b.Vector3),p=u.useRef(!0),m=u.useRef(0),f=u.useMemo(()=>new b.MeshPhysicalMaterial({color:"#8dbab5",roughness:.28,metalness:.02,transparent:!0,opacity:.42,clearcoat:.18,clearcoatRoughness:.72,depthWrite:!1}),[]),y=u.useMemo(()=>({north:i?.north??!0,south:i?.south??!0,east:i?.east??!0,west:i?.west??!0}),[i?.east,i?.north,i?.south,i?.west]),M=Math.min(n*.18,.72),_=y.north?M:0,j=y.south?M:0,A=y.east?M:0,w=y.west?M:0,x=Math.max(n-w-A,n*.34),T=Math.max(n-_-j,n*.34),C=(w-A)*.5,B=(_-j)*.5,I=Math.max(n-(y.west?M*.25:0)-(y.east?M*.25:0),n*.42),F=Math.max(n-(y.north?M*.25:0)-(y.south?M*.25:0),n*.42),R=u.useMemo(()=>Math.max(2,Math.round(n/4)),[n]);u.useEffect(()=>{d&&(d.wrapS=d.wrapT=b.RepeatWrapping,d.repeat.set(R,R),d.needsUpdate=!0)},[d,R]),u.useEffect(()=>{s&&g.current.set(s[0],s[1],s[2])},[s]);const D=u.useMemo(()=>({textureWidth:512,textureHeight:512,waterNormals:d,sunDirection:new b.Vector3(.1,.7,.2),sunColor:16777215,waterColor:7695,distortionScale:3.7}),[d]),E=u.useMemo(()=>{const z=Math.max(x,T),L=Math.round(r?z*4:z*1.2);return Math.max(r?16:6,Math.min(r?96:32,L))},[r,x,T]),P=u.useMemo(()=>new b.PlaneGeometry(x,T,E,E),[T,x,E]),G=u.useMemo(()=>r?new b.ShaderMaterial({uniforms:{uTime:{value:0},uShallow:{value:new b.Color("#9ed6c8")},uDeep:{value:new b.Color("#1f5f88")},uFoam:{value:new b.Color("#ffffff")}},vertexShader:Fl,fragmentShader:Ll,transparent:!0,depthWrite:!1}):null,[r]);return u.useEffect(()=>()=>{P.dispose();const z=a.current;z?.material?.dispose?.(),typeof z?.dispose=="function"&&z.dispose(),G?.dispose()},[P,G]),u.useEffect(()=>()=>{f.dispose()},[f]),ae.useFrame((z,L)=>{const h=r?c.current:a.current;if(h){if(e){m.current+=Math.max(0,L);const k=p.current?.2:.5;if(m.current>=k){m.current=0;const U=e.near??30,W=e.far??180,Z=e.strength??4,Y=z.camera.position.distanceTo(g.current),J=Ot.weightFromDistance(Y,U,W,Z)>0;J!==p.current&&(p.current=J,h.visible=J)}if(!p.current)return}if(r){const k=l.current?.uniforms?.uTime;k&&(k.value=z.clock.elapsedTime)}else{const k=a.current?.material.uniforms?.time;k&&(k.value+=L*.3)}}}),t.jsxs("group",{children:[y.north&&t.jsx("mesh",{"rotation-x":-Math.PI/2,position:[0,.055,-n/2+M/2],material:f,receiveShadow:!0,children:t.jsx("planeGeometry",{args:[I,M,1,1]})}),y.south&&t.jsx("mesh",{"rotation-x":-Math.PI/2,position:[0,.055,n/2-M/2],material:f,receiveShadow:!0,children:t.jsx("planeGeometry",{args:[I,M,1,1]})}),y.west&&t.jsx("mesh",{"rotation-x":-Math.PI/2,position:[-n/2+M/2,.055,0],material:f,receiveShadow:!0,children:t.jsx("planeGeometry",{args:[M,F,1,1]})}),y.east&&t.jsx("mesh",{"rotation-x":-Math.PI/2,position:[n/2-M/2,.055,0],material:f,receiveShadow:!0,children:t.jsx("planeGeometry",{args:[M,F,1,1]})}),r?t.jsx("mesh",{ref:c,geometry:P,"rotation-x":-Math.PI/2,position:[C,.1,B],children:t.jsx("primitive",{ref:l,object:G,attach:"material"})}):t.jsx("water",{ref:a,args:[P,D],"rotation-x":-Math.PI/2,position:[C,.1,B]})]})}const Gl=25,zl=90,Ol=4,yo={north:!0,south:!0,east:!0,west:!0};function Ul(e,s,n){const o=S.TILE_CONSTANTS.GRID_CELL_SIZE*(e.size||1)/2;return s>e.position.x-o+.001&&s<e.position.x+o-.001&&n>e.position.z-o+.001&&n<e.position.z+o-.001}function Wl(e,s){const n=S.TILE_CONSTANTS.GRID_CELL_SIZE*(e.size||1),i=n/2,o=Math.max(.08,n*.06),r=Math.max(.12,S.TILE_CONSTANTS.HEIGHT_STEP*.25),a=s??[];if(a.length===0)return yo;const l=(c,d)=>{for(const g of a)if(g.id!==e.id&&!(Math.abs(g.position.y-e.position.y)>r)&&Ul(g,c,d))return!0;return!1};return{north:!l(e.position.x,e.position.z-i-o),south:!l(e.position.x,e.position.z+i+o),west:!l(e.position.x-i-o,e.position.z),east:!l(e.position.x+i+o,e.position.z)}}const Hl=new Set(["sand","snowfield"]);function $l({tile:e,tiles:s}){if(!e.objectType||e.objectType==="none"||Hl.has(e.objectType))return null;const n=u.useRef(null),i=u.useRef(!0),o=u.useRef(0),r=S.TILE_CONSTANTS.GRID_CELL_SIZE*(e.size||1),a=[e.position.x,e.position.y,e.position.z],l=u.useMemo(()=>e.objectType==="water"?Wl(e,s):yo,[e,s]);return ae.useFrame((c,d)=>{o.current+=d;const g=i.current?.3:.8;if(o.current<g)return;o.current=0;const p=c.camera.position,m=e.position,f=p.x-m.x,y=p.y-m.y,M=p.z-m.z,_=Math.sqrt(f*f+y*y+M*M),A=Ot.weightFromDistance(_,Gl,zl,Ol)>0;A!==i.current&&(i.current=A,n.current&&(n.current.visible=A))}),t.jsx("group",{ref:n,position:a,children:t.jsxs(u.Suspense,{fallback:null,children:[e.objectType==="water"&&t.jsx(vo,{size:r,shore:l,center:a}),e.objectType==="grass"&&t.jsx(As,{width:r,density:e.objectConfig?.grassDensity??90,...e.objectConfig?.terrainColor?{groundColor:e.objectConfig.terrainColor}:{},...e.objectConfig?.terrainAccentColor?{groundAccentColor:e.objectConfig.terrainAccentColor}:{},...e.objectConfig?.terrainColor?{bladeBottomColor:e.objectConfig.terrainColor}:{},...e.objectConfig?.terrainAccentColor?{bladeTipColor:e.objectConfig.terrainAccentColor}:{},position:[0,.05,0]})]})})}const Zl={grass:.05,sand:.065,snowfield:.055,water:.055};function Vl(e){return e-Math.floor(e)}function tt(...e){const s=e.reduce((n,i,o)=>n+i*(o*19.19+7.13),0);return Vl(Math.sin(s)*43758.5453123)}function Nt(e){return e.shape??"box"}function sn(e,s){return e.materialId??s}function ms(e,s,n){const i=Math.cos(n),o=Math.sin(n);return[e*i+s*o,s*i-e*o]}function Bs(e){const s=(e.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE,n=Math.max(4,Math.min(8,(e.size||1)*4)),i=Math.max(e.position.y,S.TILE_CONSTANTS.HEIGHT_STEP),o=i/n,r=s/n,a=Math.max(n*4,Math.ceil(i/.08)),l=e.rotation??0;return{tileSize:s,stepCount:n,totalHeight:i,stepHeight:o,stepDepth:r,colliderSlices:a,rotation:l}}function Js(e){const s=(e.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE,n=Math.max(12,Math.min(24,Math.ceil(s/.25))),i=Math.max(e.position.y,S.TILE_CONSTANTS.HEIGHT_STEP),o=i/n,r=s/n,a=e.rotation??0;return{tileSize:s,rampSlices:n,totalHeight:i,sliceHeight:o,sliceDepth:r,rotation:a}}function fs(e){const n=(e.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE/2,i=e.objectType?Zl[e.objectType]??0:0;return{id:e.id,topY:e.position.y+i,minX:e.position.x-n,maxX:e.position.x+n,minZ:e.position.z-n,maxZ:e.position.z+n,centerX:e.position.x,centerZ:e.position.z,segments:e.size||1}}function So(e,s,n,i){let o=0;for(const r of e)r.id!==s&&n>r.minX+.001&&n<r.maxX-.001&&i>r.minZ+.001&&i<r.maxZ-.001&&(o=Math.max(o,r.topY));return o}function Yl(e,s,n,i,o,r,a,l){const c=(d,g)=>{e.push(d[0],d[1],d[2]),s.push(g.r,g.g,g.b)};c(n,a),c(i,a),c(o,l),c(n,a),c(o,l),c(r,l)}function It(e,s,n,i,o){e.push(s[0],s[1],s[2],n[0],n[1],n[2],i[0],i[1],i[2],s[0],s[1],s[2],i[0],i[1],i[2],o[0],o[1],o[2])}function Xl(e,s,n){const i=[],o=[],r=[],a=s.map(fs),l=e.map(fs),c=new b.Color("#7b6a58"),d=new b.Color("#433930"),g=S.TILE_CONSTANTS.GRID_CELL_SIZE,p=(f,y,M,_,j,A,w,x,T,C)=>{const B=So(a,f.id,A,w);if(f.topY<=B+.02)return;const I=f.topY-B,F=.72+tt(C,f.centerX,f.centerZ)*.16,R=.42+tt(C,f.topY)*.08,D=n.clone().lerp(c,.28+Math.min(I,2)*.08).multiplyScalar(F),E=n.clone().lerp(d,.7).multiplyScalar(R);if(Yl(i,o,[y,f.topY,M],[_,f.topY,j],[_,B,j],[y,B,M],D,E),I<S.TILE_CONSTANTS.HEIGHT_STEP*.95)return;const P=tt(C,B,I);if(P<.58)return;const G=(y+_)*.5,z=(M+j)*.5,L=.12+Math.min(I,2.5)*.06,h=.08+P*.08;r.push({position:[G+x*(.18+P*.24),B+L*.65,z+T*(.18+P*.24)],rotation:[P*Math.PI*1.7,P*Math.PI*2.9,P*Math.PI*.9],scale:[L+h*.6,L*.9+h*.45,L+h]})};for(const f of l){if(f.topY<=.02)continue;const M=-(f.segments*g)/2;for(let _=0;_<f.segments;_++){const j=M+_*g,A=j+g,w=j+g*.5;p(f,f.maxX,f.centerZ+j,f.maxX,f.centerZ+A,f.maxX+.02,f.centerZ+w,1,0,tt(f.centerX,f.centerZ,_,1)),p(f,f.minX,f.centerZ+A,f.minX,f.centerZ+j,f.minX-.02,f.centerZ+w,-1,0,tt(f.centerX,f.centerZ,_,2)),p(f,f.centerX+A,f.minZ,f.centerX+j,f.minZ,f.centerX+w,f.minZ-.02,0,-1,tt(f.centerX,f.centerZ,_,3)),p(f,f.centerX+j,f.maxZ,f.centerX+A,f.maxZ,f.centerX+w,f.maxZ+.02,0,1,tt(f.centerX,f.centerZ,_,4))}}const m=new b.BufferGeometry;return i.length>0&&(m.setAttribute("position",new b.Float32BufferAttribute(i,3)),m.setAttribute("color",new b.Float32BufferAttribute(o,3)),m.computeVertexNormals(),m.computeBoundingBox(),m.computeBoundingSphere()),{sideGeometry:m,rocks:r}}function ql(e,s){const n=s.map(fs),{tileSize:i,totalHeight:o,rotation:r}=Bs(e),[a,l]=ms(0,i/2+.04,r);return So(n,e.id,e.position.x+a,e.position.z+l)+.02<o}function Kl(e,s){const n=new b.BufferGeometry,i=[],{tileSize:o,stepCount:r,stepHeight:a,stepDepth:l,totalHeight:c}=Bs(e),d=o/2;for(let g=0;g<r;g++){const p=-d+g*l,m=p+l,f=a*(g+1),y=a*g;It(i,[-d,f,p],[-d,f,m],[d,f,m],[d,f,p]),It(i,[-d,y,p],[-d,f,p],[d,f,p],[d,y,p]),It(i,[-d,0,p],[-d,0,m],[-d,f,m],[-d,f,p]),It(i,[d,0,m],[d,0,p],[d,f,p],[d,f,m])}return s&&It(i,[-d,0,d],[d,0,d],[d,c,d],[-d,c,d]),n.setAttribute("position",new b.Float32BufferAttribute(i,3)),n.computeVertexNormals(),n.computeBoundingBox(),n.computeBoundingSphere(),n}function Jl({tile:e,material:s,supportTiles:n}){const i=e.rotation??0,o=u.useMemo(()=>ql(e,n),[n,e]),r=u.useMemo(()=>Kl(e,o),[e,o]);return u.useEffect(()=>()=>{r.dispose()},[r]),t.jsx("mesh",{position:[e.position.x,0,e.position.z],rotation:[0,i,0],geometry:r,material:s,castShadow:!0,receiveShadow:!0})}function Ql({batch:e,geometry:s,dummy:n}){const i=u.useRef(null);return u.useLayoutEffect(()=>{const o=i.current;if(!o)return;const r=S.TILE_CONSTANTS.GRID_CELL_SIZE;o.count=e.tiles.length;for(let a=0;a<e.tiles.length;a++){const l=e.tiles[a];if(!l)continue;const c=l.size||1,d=r*c;n.position.set(l.position.x,l.position.y+.001,l.position.z),n.rotation.set(0,l.rotation??0,0),n.scale.set(d,1,d),n.updateMatrix(),o.setMatrixAt(a,n.matrix)}o.instanceMatrix.needsUpdate=!0,e.tiles.length>0&&(o.computeBoundingBox(),o.computeBoundingSphere())},[e.tiles,n]),t.jsx("instancedMesh",{ref:i,args:[s,e.material,Math.max(1,e.tiles.length)],castShadow:!0,receiveShadow:!0,frustumCulled:!0})}function Mo({tileGroup:e,meshes:s,isEditMode:n=!1,selectedTileId:i=null,onTileClick:o}){const r=u.useRef(new Je),a=u.useRef(null),l=u.useMemo(()=>e.tiles.filter(h=>Nt(h)==="box"),[e.tiles]),c=u.useMemo(()=>e.tiles.filter(h=>Nt(h)==="stairs"),[e.tiles]),d=u.useMemo(()=>e.tiles.filter(h=>Nt(h)==="ramp"),[e.tiles]),g=u.useMemo(()=>e.tiles.filter(h=>Nt(h)==="round"),[e.tiles]),p=u.useMemo(()=>{const h=r.current,k=s.get(e.floorMeshId);if(!k){a.current?.dispose();const U=S.getDefaultToonMode()?new b.MeshToonMaterial({color:"#888888",gradientMap:S.getToonGradient(4)}):new b.MeshStandardMaterial({color:"#888888"});return a.current=U,U}return a.current?.dispose(),a.current=null,h.getMaterial(k)},[e.floorMeshId,s]),m=u.useMemo(()=>{const h=r.current,k=new Map;k.set(e.floorMeshId,p);for(const U of e.tiles){if(!U.materialId||k.has(U.materialId))continue;const W=s.get(U.materialId);k.set(U.materialId,W?h.getMaterial(W):p)}return k},[p,s,e.floorMeshId,e.tiles]),f=u.useMemo(()=>{const h=new Map;for(const k of l){const U=sn(k,e.floorMeshId),W=h.get(U)??[];W.push(k),h.set(U,W)}return Array.from(h.entries()).map(([k,U])=>({materialId:k,tiles:U,material:m.get(k)??p}))},[l,p,m,e.floorMeshId]),y=u.useMemo(()=>{const h=s.get(e.floorMeshId);return new b.Color(h?.color||"#8a806f")},[e.floorMeshId,s]),M=u.useMemo(()=>Xl(l,e.tiles,y),[l,e.tiles,y]),_=u.useMemo(()=>S.getDefaultToonMode()?new b.MeshToonMaterial({vertexColors:!0,side:b.DoubleSide,gradientMap:S.getToonGradient(4)}):new b.MeshStandardMaterial({vertexColors:!0,roughness:.98,metalness:.02,side:b.DoubleSide}),[]),j=u.useMemo(()=>new b.DodecahedronGeometry(1,0),[]),A=u.useMemo(()=>{const h=new b.BufferGeometry,k=new Float32Array([-.5,0,-.5,.5,0,-.5,-.5,0,.5,.5,0,.5,-.5,1,.5,.5,1,.5]),U=[0,1,3,0,3,2,0,1,5,0,5,4,0,2,4,1,5,3,2,3,5,2,5,4];return h.setAttribute("position",new b.BufferAttribute(k,3)),h.setIndex(U),h.computeVertexNormals(),h},[]),w=u.useMemo(()=>S.getDefaultToonMode()?new b.MeshToonMaterial({color:"#71695f",gradientMap:S.getToonGradient(3)}):new b.MeshStandardMaterial({color:"#71695f",roughness:1,metalness:.02}),[]),x=u.useMemo(()=>{const h=new b.PlaneGeometry(1,1,1,1);return h.rotateX(-Math.PI/2),h},[]),T=u.useMemo(()=>new b.Object3D,[]),C=u.useRef(null),B=u.useMemo(()=>new b.BoxGeometry(1,1,1),[]),I=u.useMemo(()=>S.getDefaultToonMode()?new b.MeshToonMaterial({color:"#60a5fa",transparent:!0,opacity:.14,emissive:new b.Color("#2563eb"),emissiveIntensity:.08,gradientMap:S.getToonGradient(3),wireframe:!0,depthWrite:!1}):new b.MeshStandardMaterial({color:"#60a5fa",transparent:!0,opacity:.14,emissive:new b.Color("#2563eb"),emissiveIntensity:.08,wireframe:!0,depthWrite:!1}),[]),F=u.useMemo(()=>S.getDefaultToonMode()?new b.MeshToonMaterial({color:"#bae6fd",transparent:!0,opacity:.28,emissive:new b.Color("#60a5fa"),emissiveIntensity:.18,gradientMap:S.getToonGradient(3),wireframe:!0,depthWrite:!1}):new b.MeshStandardMaterial({color:"#bae6fd",transparent:!0,opacity:.28,emissive:new b.Color("#60a5fa"),emissiveIntensity:.18,wireframe:!0,depthWrite:!1}),[]),R=u.useMemo(()=>e.tiles.filter(h=>h.objectType==="sand"),[e.tiles]),D=u.useMemo(()=>R.map(h=>({position:[h.position.x,h.position.y,h.position.z],size:S.TILE_CONSTANTS.GRID_CELL_SIZE*(h.size||1),...h.objectConfig?.terrainColor?{color:h.objectConfig.terrainColor}:{},...h.objectConfig?.terrainAccentColor?{accentColor:h.objectConfig.terrainAccentColor}:{}})),[R]),E=u.useMemo(()=>e.tiles.filter(h=>h.objectType==="snowfield"),[e.tiles]),P=u.useMemo(()=>E.map(h=>({position:[h.position.x,h.position.y,h.position.z],size:S.TILE_CONSTANTS.GRID_CELL_SIZE*(h.size||1),...h.objectConfig?.terrainColor?{color:h.objectConfig.terrainColor}:{},...h.objectConfig?.terrainAccentColor?{accentColor:h.objectConfig.terrainAccentColor}:{}})),[E]),G=u.useMemo(()=>e.tiles.filter(h=>h.objectType&&h.objectType!=="none"&&h.objectType!=="sand"&&h.objectType!=="snowfield"),[e.tiles]),z=u.useMemo(()=>e.tiles.filter(h=>h.objectType==="water"),[e.tiles]),L=u.useMemo(()=>{const h=[];for(const k of e.tiles){const U=Nt(k),W=(k.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE,Z=k.rotation??0;if(U==="stairs"){const{tileSize:ee,totalHeight:te,colliderSlices:X,rotation:Q}=Bs(k),se=te/X,q=ee/X;for(let ie=0;ie<X;ie++){const ue=se*(ie+1),O=-ee/2+q*ie+q/2,[me,fe]=ms(0,O,Q);h.push({key:`${k.id}-stair-collider-${ie}`,position:[k.position.x+me,ue/2,k.position.z+fe],rotation:[0,Q,0],args:[ee/2,ue/2,q/2]})}continue}if(U==="ramp"){const{tileSize:ee,rampSlices:te,sliceHeight:X,sliceDepth:Q,rotation:se}=Js(k);for(let q=0;q<te;q++){const ie=X*(q+1),ue=-ee/2+Q*q+Q/2,[O,me]=ms(0,ue,se);h.push({key:`${k.id}-ramp-${q}`,position:[k.position.x+O,ie/2,k.position.z+me],rotation:[0,se,0],args:[ee/2,ie/2,Q/2]})}continue}if(U==="round"){const ee=k.position.y>.02,te=ee?k.position.y:.04,X=ee?te/2:-.02,Q=W/2,se=Q*.34;h.push({key:`${k.id}-core`,position:[k.position.x,X,k.position.z],rotation:[0,0,0],args:[Q*.46,te/2,Q*.46]});for(let q=0;q<4;q++)h.push({key:`${k.id}-ring-${q}`,position:[k.position.x,X,k.position.z],rotation:[0,Math.PI/4*q,0],args:[Q*.82,te/2,se]});continue}const Y=k.position.y>.02,$=Y?k.position.y*.5:.02,J=Y?k.position.y*.5:-.02;h.push({key:k.id,position:[k.position.x,J,k.position.z],rotation:[0,Z,0],args:[W/2,$,W/2]})}return h},[e.tiles]);return u.useLayoutEffect(()=>{const h=C.current;if(h&&M.rocks.length>0){h.count=M.rocks.length;for(let k=0;k<M.rocks.length;k++){const U=M.rocks[k];T.position.set(U.position[0],U.position[1],U.position[2]),T.rotation.set(U.rotation[0],U.rotation[1],U.rotation[2]),T.scale.set(U.scale[0],U.scale[1],U.scale[2]),T.updateMatrix(),h.setMatrixAt(k,T.matrix)}h.instanceMatrix.needsUpdate=!0}},[M.rocks,T]),u.useEffect(()=>{if(e.tiles.length===0)return;const h=st.MinimapSystem.getInstance(),k=new b.Box3,U=new b.Vector3;e.tiles.forEach(Y=>{const J=(Y.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE/2;U.set(Y.position.x-J,Y.position.y,Y.position.z-J),k.expandByPoint(U),U.set(Y.position.x+J,Y.position.y,Y.position.z+J),k.expandByPoint(U)});const W=new b.Vector3,Z=new b.Vector3;return k.getCenter(W),k.getSize(Z),h.addMarker(`tile-group-${e.id}`,"ground",e.name||"Tiles",W,Z),()=>{h.removeMarker(`tile-group-${e.id}`)}},[e]),u.useEffect(()=>()=>{r.current.dispose(),a.current?.dispose(),a.current=null,x.dispose(),B.dispose(),I.dispose(),F.dispose()},[x,B,I,F]),u.useEffect(()=>()=>{M.sideGeometry.dispose()},[M.sideGeometry]),u.useEffect(()=>()=>{_.dispose(),j.dispose(),A.dispose(),w.dispose()},[A,j,w,_]),t.jsx(st.WorldProps,{type:"ground",children:t.jsxs(t.Fragment,{children:[L.length>0&&t.jsx(ot.RigidBody,{type:"fixed",colliders:!1,children:L.map(h=>t.jsx(ot.CuboidCollider,{position:h.position,rotation:h.rotation,args:h.args},`${e.id}-collider-${h.key}`))}),n&&e.tiles.map(h=>{const k=h.id===i,U=(h.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE,W=Math.max(.22,h.position.y+.22);return t.jsx("group",{position:[h.position.x,W/2,h.position.z],scale:[U*.82,W,U*.82],onClick:()=>o?.(h.id),children:t.jsx("mesh",{geometry:B,material:k?F:I})},h.id)}),f.map(h=>t.jsx(Ql,{batch:h,geometry:x,dummy:T},`${e.id}-box-${h.materialId}`)),g.map(h=>{const k=(h.size||1)*S.TILE_CONSTANTS.GRID_CELL_SIZE,U=h.position.y>.02,W=U?h.position.y:.04,Z=U?W/2:-.02,Y=sn(h,e.floorMeshId);return t.jsx("mesh",{position:[h.position.x,Z,h.position.z],material:m.get(Y)??p,castShadow:!0,receiveShadow:!0,children:t.jsx("cylinderGeometry",{args:[k/2,k/2,W,28,1,!1]})},`${h.id}-round`)}),c.map(h=>t.jsx(Jl,{tile:h,material:m.get(sn(h,e.floorMeshId))??p,supportTiles:e.tiles},`${h.id}-stairs`)),d.map(h=>{const{tileSize:k,totalHeight:U,rotation:W}=Js(h),Z=sn(h,e.floorMeshId);return t.jsx("mesh",{position:[h.position.x,0,h.position.z],rotation:[0,W,0],scale:[k,U,k],geometry:A,material:m.get(Z)??p,castShadow:!0,receiveShadow:!0},`${h.id}-ramp`)}),M.sideGeometry.getAttribute("position")&&t.jsx("mesh",{geometry:M.sideGeometry,material:_,castShadow:!0,receiveShadow:!0,frustumCulled:!1}),M.rocks.length>0&&t.jsx("instancedMesh",{ref:C,args:[j,w,Math.max(1,M.rocks.length)],castShadow:!0,receiveShadow:!0}),G.map(h=>t.jsx($l,{tile:h,tiles:z},`${h.id}-object`)),D.length>0&&t.jsx(ho,{entries:D}),P.length>0&&t.jsx(bo,{entries:P})]})})}const Fe={id:"default",color:"#000000"};function jo(e){return e.materialId?`material:${e.materialId}`:`type:${e.wallGroupId}`}function Qs(e,s,n,i,o){if(n.materialId){const d=e.getMaterial(s.get(n.materialId)??Fe);return[d,d,d,d,d,d]}const r=i.get(n.wallGroupId)??o,a=r.frontMeshId?s.get(r.frontMeshId):Fe,l=r.backMeshId?s.get(r.backMeshId):Fe,c=r.sideMeshId?s.get(r.sideMeshId):Fe;return[e.getMaterial(c??Fe),e.getMaterial(c??Fe),e.getMaterial(c??Fe),e.getMaterial(c??Fe),e.getMaterial(a??Fe),e.getMaterial(l??Fe)]}function ec(e,s,n,i){const o=new Map;for(const r of e.walls){const a=jo(r),l=o.get(a)??[];l.push(r),o.set(a,l)}return Array.from(o.entries()).map(([r,a])=>{const l=a[0];return{key:r,walls:a,materials:l?Qs(i,n,l,s,e):Qs(i,n,{wallGroupId:e.id},s,e)}})}function tc({batch:e,geometry:s,height:n,onWallClick:i}){const o=u.useRef(null),r=e.walls.length,[a,l]=u.useState(()=>Math.max(1,r)),c=u.useMemo(()=>new b.Object3D,[]);u.useEffect(()=>{r<=a||l(Math.max(r,Math.ceil(a*1.5)))},[r,a]),u.useLayoutEffect(()=>{const g=o.current;if(g){g.count=r;for(let p=0;p<r;p++){const m=e.walls[p];m&&(c.position.set(m.position.x,m.position.y+n/2,m.position.z),c.rotation.set(0,m.rotation.y,0),c.updateMatrix(),g.setMatrixAt(p,c.matrix))}g.instanceMatrix.needsUpdate=!0,r>0&&(g.computeBoundingBox(),g.computeBoundingSphere())}},[e.walls,r,c,n,a]);const d=g=>{g.stopPropagation();const p=g.instanceId!==void 0?e.walls[g.instanceId]:void 0;p&&i?.(p.id)};return t.jsx("instancedMesh",{ref:o,args:[s,e.materials,a],castShadow:!0,receiveShadow:!0,...i?{onClick:d}:{}})}function wo({wallGroup:e,wallGroups:s,meshes:n,isEditMode:i=!1,selectedWallId:o=null,onWallClick:r}){const a=u.useRef(new Je),l=S.TILE_CONSTANTS.WALL_SIZES.WIDTH,c=S.TILE_CONSTANTS.WALL_SIZES.HEIGHT,d=S.TILE_CONSTANTS.WALL_SIZES.THICKNESS,g=u.useMemo(()=>{const f=new b.BoxGeometry(l,c,d);return f.translate(0,0,l/2),f},[l,c,d]),p=u.useMemo(()=>ec(e,s??new Map([[e.id,e]]),n,a.current),[e,s,n]);u.useEffect(()=>()=>{a.current.dispose(),g.dispose()},[g]);const m=u.useMemo(()=>{if(i)return[];const f=l/2;return e.walls.map(y=>{const M=Math.sin(y.rotation.y),_=Math.cos(y.rotation.y);return{id:y.id,position:[y.position.x+M*f,y.position.y+c/2,y.position.z+_*f],rotation:[0,y.rotation.y,0]}})},[e.walls,l,c,i]);return t.jsxs(t.Fragment,{children:[!i&&m.length>0&&t.jsx(ot.RigidBody,{type:"fixed",colliders:!1,children:m.map(f=>t.jsx(ot.CuboidCollider,{position:f.position,rotation:f.rotation,args:[l/2,c/2,d/2]},f.id))}),i&&e.walls.map(f=>{const y=f.id===o;return t.jsx("group",{position:[f.position.x,f.position.y+c+.5,f.position.z],onClick:()=>r?.(f.id),children:t.jsxs("mesh",{scale:y?1.28:1,children:[t.jsx("sphereGeometry",{args:[.22,16,16]}),t.jsx("meshStandardMaterial",{color:y?"#bae6fd":"#7dd3fc",emissive:y?"#60a5fa":"#2f8dbd",emissiveIntensity:y?.5:.22,transparent:!0,opacity:y?.94:.78})]})},f.id)}),p.map(f=>t.jsx(tc,{batch:f,geometry:g,height:c,...r?{onWallClick:r}:{}},`${e.id}-${f.key}`))]})}const nc={sakura:[],flag:[],fire:[],billboard:[],model:[]};function ye(e,s){return s<=0?[]:e.length<=s?e:e.slice(0,s)}function sc(e){const s=e.tiles.find(n=>n.objectType&&n.objectType!=="none")?.objectType??"none";return s==="water"?ft:s==="sand"?ht:s==="snowfield"?gt:mt}function ic(e){if(!e||e.length===0)return nc;const s={sakura:[],flag:[],fire:[],billboard:[],model:[]};for(const n of e)n.type==="sakura"?s.sakura.push({position:[n.position.x,n.position.y,n.position.z],size:n.config?.size??S.TILE_CONSTANTS.GRID_CELL_SIZE,...n.config?.primaryColor?{blossomColor:n.config.primaryColor}:{},...n.config?.secondaryColor?{barkColor:n.config.secondaryColor}:{}}):n.type==="flag"?s.flag.push(n):n.type==="fire"?s.fire.push({position:[n.position.x,n.position.y,n.position.z],rotation:n.rotation??0,intensity:n.config?.fireIntensity??1.5,width:n.config?.fireWidth??1,height:n.config?.fireHeight??1.5,color:n.config?.fireColor??"#ffffff"}):n.type==="billboard"?s.billboard.push(n):n.type==="model"&&s.model.push(n);return s}const _o=u.memo(function({onWallClick:s,onTileClick:n,onBlockClick:i,onWallDelete:o,onTileDelete:r,onBlockDelete:a}){const l=S.useBuildingStore(O=>O.meshes),c=S.useBuildingStore(O=>O.wallGroups),d=S.useBuildingStore(O=>O.tileGroups),g=S.useBuildingStore(O=>O.blocks),p=S.useBuildingStore(O=>O.editMode),m=S.useBuildingStore(O=>O.selectedWallId),f=S.useBuildingStore(O=>O.selectedTileId),y=S.useBuildingStore(O=>O.selectedBlockId),M=S.useBuildingStore(O=>O.showGrid),_=S.useBuildingStore(O=>O.gridSize),j=S.useBuildingStore(O=>O.showSnow),A=S.useBuildingStore(O=>O.objects),w=ge(O=>O.drawMirror),x=_e(O=>O.active),T=_e(O=>O.version),C=Ze(O=>O.initialized),B=Ze(O=>O.visibleWallGroupIds),I=Ze(O=>O.visibleTileGroupIds),F=Ze(O=>O.visibleBlockIds),R=Ze(O=>O.visibleObjectIds),D=x&&w.version>0&&w.version===T,E=D?Ne(w,yn):Number.MAX_SAFE_INTEGER,P=D?Ne(w,mt):Number.MAX_SAFE_INTEGER,G=D?Ne(w,ft):Number.MAX_SAFE_INTEGER,z=D?Ne(w,ht):Number.MAX_SAFE_INTEGER,L=D?Ne(w,gt):Number.MAX_SAFE_INTEGER,h=D?Ne(w,Sn):Number.MAX_SAFE_INTEGER,k=D?Ne(w,Mn):Number.MAX_SAFE_INTEGER,U=D?Ne(w,jn):Number.MAX_SAFE_INTEGER,W=D?Ne(w,wn):Number.MAX_SAFE_INTEGER,Z=D?Ne(w,Cn):Number.MAX_SAFE_INTEGER,Y=D?Ne(w,_n):Number.MAX_SAFE_INTEGER,$=u.useMemo(()=>{const O=Array.from(c.values()),me=C?O.filter(fe=>B.has(fe.id)):O;return ye(me,E)},[c,C,B,E]),J=u.useMemo(()=>{const O=Array.from(d.values()),me=C?O.filter(le=>I.has(le.id)):O,fe=[],xe=[],Me=[],Ie=[];for(const le of me){const Qe=sc(le);Qe===ft?xe.push(le):Qe===ht?Me.push(le):Qe===gt?Ie.push(le):fe.push(le)}return[...ye(fe,P),...ye(xe,G),...ye(Me,z),...ye(Ie,L)]},[d,C,I,P,G,z,L]),ee=u.useMemo(()=>{const O=C?A.filter(le=>R.has(le.id)):A,me=[],fe=[],xe=[],Me=[],Ie=[];for(const le of O)le.type==="sakura"?me.push(le):le.type==="flag"?fe.push(le):le.type==="fire"?xe.push(le):le.type==="billboard"?Me.push(le):le.type==="model"&&Ie.push(le);return[...ye(me,h),...ye(fe,k),...ye(xe,U),...ye(Me,W),...ye(Ie,Z)]},[A,C,R,h,k,U,W,Z]),te=u.useMemo(()=>{const O=g??[],me=C?O.filter(fe=>F.has(fe.id)):O;return ye(me,Y)},[g,C,F,Y]),X=u.useMemo(()=>ic(ee),[ee]),Q=ye(X.sakura,h),se=ye(X.flag,k),q=ye(X.fire,U),ie=ye(X.billboard,W),ue=ye(X.model,Z);return t.jsx(u.Suspense,{fallback:null,children:t.jsxs("group",{name:"building-system",children:[M&&t.jsx(Vi,{size:_}),t.jsx(hl,{}),t.jsx(gl,{}),t.jsx(Kr,{}),$.map(O=>t.jsx(wo,{wallGroup:O,wallGroups:c,meshes:l,isEditMode:p==="wall",selectedWallId:m,...s?{onWallClick:s}:{},...o?{onWallDelete:o}:{}},O.id)),J.map(O=>t.jsx(Mo,{tileGroup:O,meshes:l,isEditMode:p==="tile",selectedTileId:f,...n?{onTileClick:n}:{},...r?{onTileDelete:r}:{}},O.id)),te.length>0&&t.jsx(Zi,{blocks:te,meshes:l,isEditMode:p==="block",selectedBlockId:y,...i||a?{onBlockClick:i??a}:{}}),Q.length>0&&t.jsx(u.Suspense,{fallback:null,children:t.jsx(po,{trees:Q})}),se.length>0&&t.jsx(u.Suspense,{fallback:null,children:t.jsx(Ka,{flags:se})}),q.length>0&&t.jsx(u.Suspense,{fallback:null,children:t.jsx(Ga,{fires:q})}),ie.map(O=>t.jsx("group",{position:[O.position.x,O.position.y,O.position.z],rotation:[0,O.rotation??0,0],children:t.jsx(u.Suspense,{fallback:null,children:t.jsx(Ki,{...O.config?.billboardText?{text:O.config.billboardText}:{},...O.config?.billboardImageUrl?{imageUrl:O.config.billboardImageUrl}:{},...O.config?.billboardColor?{color:O.config.billboardColor}:{}})})},O.id)),ue.map(O=>t.jsx("group",{position:[O.position.x,O.position.y,O.position.z],rotation:[0,O.rotation??0,0],children:t.jsx(u.Suspense,{fallback:null,children:t.jsx(tl,{...O.config?.modelUrl?{url:O.config.modelUrl}:{},...O.config?.modelLabel?{label:O.config.modelLabel}:{},...O.config?.modelFallbackKind?{fallbackKind:O.config.modelFallbackKind}:{},...O.config?.modelScale?{scale:O.config.modelScale}:{},...O.config?.modelColor?{color:O.config.modelColor}:{}})})},O.id)),j&&t.jsx(Ns,{})]})})});function oc({part:e}){return t.jsxs("mesh",{position:e.position||[0,0,0],rotation:e.rotation||[0,0,0],scale:e.scale||[1,1,1],children:[t.jsx("boxGeometry",{args:[.5,.5,.5]}),t.jsx("meshStandardMaterial",{color:e.color||"#cccccc",transparent:!0,opacity:.6})]})}function rc({part:e}){const s=Ge.useGLTF(e.url),n=u.useMemo(()=>{const i=gs.SkeletonUtils.clone(s.scene);return i&&S.getDefaultToonMode()&&S.applyToonToScene(i),i},[s]);return n?t.jsx("primitive",{object:n,position:e.position||[0,0,0],rotation:e.rotation||[0,0,0],scale:e.scale||[1,1,1]}):null}function ac({part:e,instanceId:s}){return!!e.url&&e.url.trim()!==""?t.jsx(rc,{part:e,instanceId:s}):t.jsx(oc,{part:e,instanceId:s})}const lc=.3,cc=u.memo(function({instance:s,isEditMode:n,onClick:i}){const o=u.useRef(null),r=u.useRef(null),a=u.useRef(0),l=oe(u.useCallback(j=>j.templates.get(s.templateId),[s.templateId])),c=oe(u.useCallback(j=>s.currentClothingSetId?j.clothingSets.get(s.currentClothingSetId):void 0,[s.currentClothingSetId])),d=oe(j=>j.advanceNavigation),g=oe(j=>j.updateNavigationPosition),p=s.navigation?.state==="moving";u.useEffect(()=>{a.current=s.navigation?.currentIndex??0},[s.navigation?.waypoints]),ae.useFrame((j,A)=>{if(!p||!s.navigation)return;const w=r.current;if(!w)return;const{waypoints:x,speed:T}=s.navigation,C=a.current;if(C>=x.length)return;const B=x[C];if(!B)return;const I=w.translation(),F=B[0]-I.x,R=B[2]-I.z,D=Math.sqrt(F*F+R*R);if(D<lc){a.current=C+1,C+1>=x.length&&g(s.id,[B[0],B[1],B[2]]),d(s.id);return}const E=Math.min(T*A,D),P=I.x+F/D*E,G=I.z+R/D*E;if(w.setNextKinematicTranslation({x:P,y:I.y,z:G}),o.current&&D>.01){const z=Math.atan2(F,R);o.current.rotation.y=z}});const m=u.useCallback(j=>{j.stopPropagation(),document.body.style.cursor="pointer";const A=o.current?.__handlers;A?.pointerover&&A.pointerover()},[]),f=u.useCallback(()=>{document.body.style.cursor="default"},[]);u.useEffect(()=>{if(!s.events||s.events.length===0)return;const j=o.current;if(!j)return;const A=()=>{s.events?.find(x=>x.type==="onHover")},w=()=>{const x=s.events?.find(T=>T.type==="onClick");x&&x.action};return j.__handlers={pointerover:A,click:w},()=>{delete j.__handlers}},[s.events]);const y=u.useMemo(()=>{if(!l)return[];const j=[...l.baseParts];if(c&&j.push(...c.parts),l.accessoryParts&&j.push(...l.accessoryParts),s.customParts)for(const A of s.customParts){const w=j.findIndex(x=>x.type===A.type);w>=0?j[w]={...j[w],...A}:j.push(A)}return j},[l,c,s.customParts]);if(!l)return null;const M=l.fullModelUrl||s.metadata?.modelUrl;if(M)return t.jsx(S.PhysicsEntity,{ref:r,url:M,isActive:!1,componentType:"character",name:`npc-${s.id}`,position:s.position,rotation:s.rotation,currentAnimation:s.currentAnimation||"idle",userData:{instanceId:s.id,templateId:s.templateId,nameTag:s.metadata?.nameTag},onCollisionEnter:()=>{i&&i()},children:n&&t.jsxs("mesh",{position:[0,2.5,0],children:[t.jsx("boxGeometry",{args:[.5,.5,.5]}),t.jsx("meshStandardMaterial",{color:"#00ff00",transparent:!0,opacity:.6})]})});const _=p?"kinematicPosition":"fixed";return t.jsx(ot.RigidBody,{ref:r,type:_,position:s.position,rotation:s.rotation,colliders:"cuboid",children:t.jsxs("group",{ref:o,scale:s.scale,...i?{onClick:j=>{j.stopPropagation(),i()}}:{},onPointerEnter:m,onPointerLeave:f,children:[y.map(j=>t.jsx(ac,{part:j,instanceId:s.id},j.id)),n&&t.jsxs("mesh",{position:[0,2.5,0],children:[t.jsx("boxGeometry",{args:[.5,.5,.5]}),t.jsx("meshStandardMaterial",{color:"#00ff00",transparent:!0,opacity:.6})]})]})})}),uc=30,dc=120,pc=4;function Co(){const{gl:e}=ae.useThree(),s=oe(p=>p.instances),n=oe(p=>p.selectedTemplateId),i=oe(p=>p.createInstanceFromTemplate),o=oe(p=>p.setSelectedInstance),r=S.useBuildingStore(p=>p.editMode),a=S.useBuildingStore(p=>p.hoverPosition),l=r==="npc",[c,d]=u.useState(()=>new Set),g=u.useRef(0);return ae.useFrame((p,m)=>{if(g.current+=m,g.current<.5)return;g.current=0;const f=p.camera.position,y=new Set;s.forEach(M=>{const[_,j,A]=M.position,w=_-f.x,x=j-f.y,T=A-f.z,C=Math.sqrt(w*w+x*x+T*T);Ot.weightFromDistance(C,uc,dc,pc)>.01&&y.add(M.id)}),(y.size!==c.size||[...y].some(M=>!c.has(M)))&&d(y)}),u.useEffect(()=>{if(!l||!n||!a)return;const p=()=>{a&&i(n,[a.x,a.y,a.z])};return e.domElement.addEventListener("click",p),()=>e.domElement.removeEventListener("click",p)},[l,n,a,e,i]),t.jsx("group",{name:"npc-system",children:Array.from(s.values()).map(p=>!l&&!c.has(p.id)?null:t.jsx(cc,{instance:p,isEditMode:l,onClick:()=>{l&&o(p.id)}},p.id))})}const ei=new b.Vector2,mc=new b.Plane(new b.Vector3(0,1,0),0),is=new b.Vector3;let on=0;function ti(e){return e.replace(/[^a-zA-Z0-9_-]/g,"")}function Es(e,s,n){return e!=="sand"&&e!=="snowfield"?null:{id:["terrain-block",e,ti(s),ti(n)].join("-"),color:s,material:"STANDARD",roughness:e==="snowfield"?.78:.94}}function fc(e){return e==="sand"?{color:"#b89b66",accentColor:"#e0c27a"}:e==="snowfield"?{color:"#dcecff",accentColor:"#ffffff"}:null}function To(e,s){let n=null,i=-1/0;for(const r of e)for(const a of r.tiles){if(a.objectType!=="sand"&&a.objectType!=="snowfield")continue;const c=(a.size??1)*S.TILE_CONSTANTS.GRID_CELL_SIZE*.5,d=s.x>=a.position.x-c&&s.x<=a.position.x+c,g=s.z>=a.position.z-c&&s.z<=a.position.z+c;!d||!g||a.position.y<i||(n=a,i=a.position.y)}if(!n)return null;const o=fc(n.objectType??"none");return o?Es(n.objectType??"none",n.objectConfig?.terrainColor??o.color,n.objectConfig?.terrainAccentColor??o.accentColor):null}function No(){const{camera:e,raycaster:s}=ae.useThree(),n=u.useRef({x:0,y:0}),i=S.useBuildingStore(C=>C.snapPosition),o=S.useBuildingStore(C=>C.addWall),r=S.useBuildingStore(C=>C.addTile),a=S.useBuildingStore(C=>C.addBlock),l=S.useBuildingStore(C=>C.addObject),c=S.useBuildingStore(C=>C.setSelectedWallId),d=S.useBuildingStore(C=>C.setSelectedTileId),g=S.useBuildingStore(C=>C.setSelectedBlockId),p=S.useBuildingStore(C=>C.setHoverPosition),m=u.useCallback(()=>(ei.set(n.current.x,n.current.y),s.setFromCamera(ei,e),s.ray.intersectPlane(mc,is)?i({x:is.x,y:0,z:is.z}):null),[e,s,i]),f=u.useCallback(()=>{const C=m();if(!C)return null;const B=S.useBuildingStore.getState().getSupportHeightAt(C);return{...C,y:B}},[m]),y=u.useCallback(C=>{const B=C.target;n.current.x=C.clientX/B.clientWidth*2-1,n.current.y=-(C.clientY/B.clientHeight)*2+1;const I=S.useBuildingStore.getState().editMode;p(I==="tile"||I==="block"?f():I==="wall"||I==="npc"||I==="object"?m():null)},[m,f,p]),M=u.useCallback(()=>{const{editMode:C,selectedWallGroupId:B,currentWallRotation:I,checkWallPosition:F,hoverPosition:R}=S.useBuildingStore.getState();if(C!=="wall"||!B||!R||F(R,I))return;const D={x:0,y:I,z:0};o(B,{id:`wall-${++on}-${Date.now()}`,position:R,rotation:D,wallGroupId:B})},[o]),_=u.useCallback(()=>{const{editMode:C,selectedTileGroupId:B,checkTilePosition:I,getSupportHeightAt:F,currentTileMultiplier:R,currentTileHeight:D,currentTileShape:E,currentTileRotation:P,hoverPosition:G}=S.useBuildingStore.getState();if(C!=="tile"||!B||!G)return;const z=S.TILE_CONSTANTS.HEIGHT_STEP,L=F(G),h=E==="box"||E==="round"?L+D*z:Math.max(1,D)*z,k={...G,y:h};I(k)||r(B,{id:`tile-${++on}-${Date.now()}`,position:k,tileGroupId:B,size:R,rotation:P,shape:E})},[r]),j=u.useCallback(()=>{const{editMode:C,checkBlockPosition:B,getSupportHeightAt:I,currentTileMultiplier:F,currentTileHeight:R,selectedTileObjectType:D,currentTerrainColor:E,currentTerrainAccentColor:P,tileGroups:G,meshes:z,addMesh:L,hoverPosition:h}=S.useBuildingStore.getState();if(C!=="block"||!h)return;const k=S.TILE_CONSTANTS.HEIGHT_STEP,U=I(h),W=Math.max(1,Math.round(F)),Z={...h,y:U+R*k},Y=To(G.values(),h)??Es(D,E,P);Y&&!z.has(Y.id)&&L(Y);const $={id:`block-${++on}-${Date.now()}`,position:Z,size:{x:W,y:1,z:W},materialId:Y?.id??"default-block"};B($)||a($)},[a]),A=u.useCallback(()=>{const{editMode:C,selectedPlacedObjectType:B,hoverPosition:I,tileGroups:F,currentObjectRotation:R,currentObjectPrimaryColor:D,currentObjectSecondaryColor:E,currentFlagWidth:P,currentFlagHeight:G,currentFlagStyle:z,currentFlagImageUrl:L,currentFireIntensity:h,currentFireWidth:k,currentFireHeight:U,currentFireColor:W,currentBillboardText:Z,currentBillboardColor:Y,currentBillboardImageUrl:$,selectedModelObjectId:J,currentModelUrl:ee,currentModelScale:te,currentModelColor:X}=S.useBuildingStore.getState();if(C!=="object"||B==="none"||!I)return;let Q=0;const se=S.TILE_CONSTANTS.GRID_CELL_SIZE;for(const ie of F.values())for(const ue of ie.tiles){const O=(ue.size||1)*se/2;Math.abs(ue.position.x-I.x)<O&&Math.abs(ue.position.z-I.z)<O&&(Q=Math.max(Q,ue.position.y))}const q=B==="sakura"?{size:S.useBuildingStore.getState().currentTileMultiplier*se,primaryColor:D,secondaryColor:E}:B==="flag"?{flagWidth:P,flagHeight:G,flagStyle:z,...L?{flagTexture:L}:{}}:B==="fire"?{fireIntensity:h,fireWidth:k,fireHeight:U,fireColor:W}:B==="billboard"?{billboardText:Z,billboardColor:Y,...$?{billboardImageUrl:$}:{}}:B==="model"?(()=>{const ie=Dt(J),ue=ee||ie?.modelUrl;return{modelId:ie?.id??J,modelLabel:ie?.label??J,modelFallbackKind:ie?.fallbackKind??"generic",modelScale:te||ie?.defaultScale||1,modelColor:X||ie?.defaultColor||"#9b7653",...ue?{modelUrl:ue}:{}}})():void 0;l({id:`obj-${++on}-${Date.now()}`,type:B,position:{...I,y:Q},...R!==0?{rotation:R}:{},...q?{config:q}:{}})},[l]),w=u.useCallback(C=>{const{editMode:B}=S.useBuildingStore.getState();B==="wall"&&c(C)},[c]),x=u.useCallback(C=>{const{editMode:B}=S.useBuildingStore.getState();B==="tile"&&d(C)},[d]),T=u.useCallback(C=>{const{editMode:B}=S.useBuildingStore.getState();B==="block"&&g(C)},[g]);return{updateMousePosition:y,placeWall:M,placeTile:_,placeBlock:j,placeObject:A,handleWallClick:w,handleTileClick:x,handleBlockClick:T,getGroundPosition:m}}const hc=1,gc=4,os=8,bc=128,xc=64,vc=1,yc=180,Io=64;function rs(){return{pipeline:null,bindGroupLayout:null,uniformBuffer:null,visibleBuffer:null,readBuffer:null,bindGroup:null,count:0,spatialBuffer:null,metaBuffer:null}}function as(e){e?.destroy&&e.destroy()}function ni(e){as(e.uniformBuffer),as(e.visibleBuffer),as(e.readBuffer)}function Sc(e,s,n,i){const o=e,r=o.createShaderModule({code:`
|
|
680
|
+
struct Params {
|
|
681
|
+
viewProj : mat4x4<f32>,
|
|
682
|
+
camera : vec4<f32>,
|
|
683
|
+
misc : vec4<f32>,
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
@group(0) @binding(0) var<storage, read> spatial : array<vec4<f32>>;
|
|
687
|
+
@group(0) @binding(1) var<storage, read> meta : array<vec4<i32>>;
|
|
688
|
+
@group(0) @binding(2) var<storage, read_write> visible : array<u32>;
|
|
689
|
+
@group(0) @binding(3) var<uniform> params : Params;
|
|
690
|
+
|
|
691
|
+
@compute @workgroup_size(${Io})
|
|
692
|
+
fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
|
|
693
|
+
let i = gid.x;
|
|
694
|
+
if (f32(i) >= params.misc.x) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
let s = spatial[i];
|
|
699
|
+
let world = vec4<f32>(s.x, s.y, s.z, 1.0);
|
|
700
|
+
let clip = params.viewProj * world;
|
|
701
|
+
let w = clip.w;
|
|
702
|
+
if (w <= 0.0) {
|
|
703
|
+
visible[i] = 0u;
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
let inflate = s.w / max(abs(w), 0.0001);
|
|
708
|
+
let ndc = clip.xyz / w;
|
|
709
|
+
let inFrustum =
|
|
710
|
+
ndc.x >= (-1.0 - inflate) &&
|
|
711
|
+
ndc.x <= ( 1.0 + inflate) &&
|
|
712
|
+
ndc.y >= (-1.0 - inflate) &&
|
|
713
|
+
ndc.y <= ( 1.0 + inflate) &&
|
|
714
|
+
ndc.z >= (-inflate) &&
|
|
715
|
+
ndc.z <= ( 1.0 + inflate);
|
|
716
|
+
|
|
717
|
+
let dx = s.x - params.camera.x;
|
|
718
|
+
let dy = s.y - params.camera.y;
|
|
719
|
+
let dz = s.z - params.camera.z;
|
|
720
|
+
let limit = params.camera.w + s.w;
|
|
721
|
+
let inRange = dx * dx + dy * dy + dz * dz <= limit * limit;
|
|
722
|
+
|
|
723
|
+
visible[i] = select(0u, 1u, inFrustum && inRange);
|
|
724
|
+
}
|
|
725
|
+
`}),a=o.createComputePipeline({layout:"auto",compute:{module:r,entryPoint:"main"}}),l=a.getBindGroupLayout(0),c=e.createBuffer({label:"building-cull-uniforms",size:96,usage:xc|os}),d=e.createBuffer({label:"building-cull-visible",size:Math.max(4,i*4),usage:bc|gc|os}),g=e.createBuffer({label:"building-cull-readback",size:Math.max(4,i*4),usage:os|hc}),p=o.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:n}},{binding:2,resource:{buffer:d}},{binding:3,resource:{buffer:c}}]});return{pipeline:a,bindGroupLayout:l,uniformBuffer:c,visibleBuffer:d,readBuffer:g,bindGroup:p,count:i,spatialBuffer:s,metaBuffer:n}}function Ao(){const e=ae.useThree(l=>l.gl),s=ge(l=>l.snapshot),n=ge(l=>l.uploadResources),i=_e(l=>l.setResult),o=_e(l=>l.reset),r=u.useRef({resources:rs(),busy:!1,lastRunAt:0,readbackFlags:null}),a=u.useMemo(()=>({viewProj:new b.Matrix4,uniform:new Float32Array(24)}),[]);return u.useEffect(()=>o,[o]),u.useEffect(()=>{const l=r.current.resources;(l.count!==s.ids.length||l.spatialBuffer!==n.spatialBuffer||l.metaBuffer!==n.metaBuffer)&&(ni(l),r.current.resources=rs())},[s.ids.length,n]),ae.useFrame(l=>{if(s.version===0||s.ids.length===0||n.backend!=="webgpu")return;const c=Nn(e);if(!c||!n.spatialBuffer||!n.metaBuffer||r.current.busy)return;const d=performance.now();if(d-r.current.lastRunAt<yc)return;r.current.lastRunAt=d,r.current.resources.pipeline||(r.current.resources=Sc(c,n.spatialBuffer,n.metaBuffer,s.ids.length));const g=r.current.resources,p=a.uniform;if(a.viewProj.multiplyMatrices(l.camera.projectionMatrix,l.camera.matrixWorldInverse),p.set(a.viewProj.elements,0),p[16]=l.camera.position.x,p[17]=l.camera.position.y,p[18]=l.camera.position.z,p[19]=Le,p[20]=s.ids.length,p[21]=0,p[22]=0,p[23]=0,!g.uniformBuffer||!g.visibleBuffer||!g.readBuffer||!g.bindGroup||!g.pipeline)return;c.queue.writeBuffer(g.uniformBuffer,0,p);const m=c,f=m.createCommandEncoder(),y=f.beginComputePass();y.setPipeline(g.pipeline),y.setBindGroup(0,g.bindGroup),y.dispatchWorkgroups(Math.max(1,Math.ceil(s.ids.length/Io))),y.end(),f.copyBufferToBuffer(g.visibleBuffer,0,g.readBuffer,0,Math.max(4,s.ids.length*4)),m.queue.submit([f.finish()]),r.current.busy=!0,Promise.resolve(g.readBuffer?.mapAsync?.(vc)).then(()=>{const M=g.readBuffer?.getMappedRange?.();if(!M)return;const _=s.ids.length,j=new Uint32Array(M,0,_);(!r.current.readbackFlags||r.current.readbackFlags.length<_)&&(r.current.readbackFlags=new Uint32Array(_));const A=r.current.readbackFlags;A.set(j),g.readBuffer?.unmap?.();const w=Fi(s,A);i(w)}).catch(()=>{o()}).finally(()=>{r.current.busy=!1})}),u.useEffect(()=>()=>{ni(r.current.resources),r.current.resources=rs(),o()},[o]),null}function Bo(){const e=ge(i=>i.snapshot),s=ge(i=>i.setGpuMirror),n=u.useRef(ge.getState().gpuMirror);return u.useEffect(()=>{const i=Oi(e,n.current);n.current=i,s(i)},[e,s]),null}function Eo(){const e=ae.useThree(o=>o.gl),s=ge(o=>o.gpuMirror),n=ge(o=>o.setUploadResources),i=u.useRef(Gt());return u.useEffect(()=>{if(s.version===0)return;const o=Nn(e);o&&(i.current=Hi(o,i.current,s),n(i.current))},[e,s,n]),u.useEffect(()=>()=>{Wi(i.current),i.current=Gt(),n(i.current)},[n]),null}function ko(){const e=ae.useThree(o=>o.gl),s=ge(o=>o.drawMirror),n=ge(o=>o.setUploadResources),i=u.useRef(ge.getState().uploadResources??Gt());return u.useEffect(()=>{i.current=ge.getState().uploadResources}),u.useEffect(()=>{if(s.version===0)return;const o=Nn(e);o&&(i.current=$i(o,i.current,s),n(i.current))},[e,s,n]),null}function Ro(){const e=_e(o=>o.version),s=_e(o=>o.clusterCounts),n=ge(o=>o.setDrawMirror),i=u.useRef(ge.getState().drawMirror);return u.useEffect(()=>{if(e===0||s.length===0)return;const o=Gi(e,s,i.current);i.current=o,n(o)},[e,s,n]),null}function Po(){const e=S.useBuildingStore(c=>c.wallGroups),s=S.useBuildingStore(c=>c.tileGroups),n=S.useBuildingStore(c=>c.blocks),i=S.useBuildingStore(c=>c.objects),o=ge(c=>c.setSnapshot),r=ge(c=>c.reset),a=u.useRef(1),l=u.useMemo(()=>pa({wallGroups:Array.from(e.values()),tileGroups:Array.from(s.values()),blocks:n??[],objects:i,version:a.current++}),[e,s,n,i]);return u.useEffect(()=>{o(l)},[l,o]),u.useEffect(()=>r,[r]),null}function rn(e,s,n,i,o,r,a,l,c,d){for(const g of s){const p=n.get(g);if(!p)continue;const m=p.centerX-a.x,f=p.centerY-a.y,y=p.centerZ-a.z,M=c+p.radius*p.radius;m*m+f*f+y*y>M||(l.center.set(p.centerX,p.centerY,p.centerZ),l.radius=p.radius,r.intersectsSphere(l)&&(aa(p,i,a,o,d)||e.add(g)))}}function Do(){const e=ge(j=>j.snapshot),s=S.useBuildingStore(j=>j.wallGroups),n=S.useBuildingStore(j=>j.tileGroups),i=S.useBuildingStore(j=>j.blocks),o=S.useBuildingStore(j=>j.objects),r=_e(j=>j.active),a=_e(j=>j.version),l=_e(j=>j.visibleTileGroupIds),c=_e(j=>j.visibleWallGroupIds),d=_e(j=>j.visibleBlockIds),g=_e(j=>j.visibleObjectIds),p=Ze(j=>j.setVisible),m=Ze(j=>j.reset),f=u.useMemo(()=>oa(Array.from(s.values()),Array.from(n.values()),o,i??[]),[s,n,o,i]),y=u.useRef(0),M=u.useRef(new Map),_=u.useMemo(()=>({frustum:new b.Frustum,matrix:new b.Matrix4,camera:new b.Vector3,forward:new b.Vector3,sphere:new b.Sphere,targetDir:new b.Vector3,occDir:new b.Vector3,cross:new b.Vector3}),[]);return u.useEffect(()=>{M.current.clear()},[f]),u.useEffect(()=>{M.current.clear()},[r,a]),u.useEffect(()=>m,[m]),ae.useFrame((j,A)=>{if(e.ids.length===0||(y.current+=Math.max(0,A),y.current<Jr))return;y.current=0,_.matrix.multiplyMatrices(j.camera.projectionMatrix,j.camera.matrixWorldInverse),_.frustum.setFromProjectionMatrix(_.matrix),_.camera.copy(j.camera.position),j.camera.getWorldDirection(_.forward);const w=na(_.camera.x,_.camera.z,_.forward.x,_.forward.z),x=M.current.get(w);if(x){p(x);return}const T=r&&a===e.version,C=T?new Set(l):Bt(f.tileBuckets,_.camera.x,_.camera.z,Le),B=T?new Set(c):Bt(f.wallBuckets,_.camera.x,_.camera.z,Le),I=T?new Set(g):Bt(f.objectBuckets,_.camera.x,_.camera.z,Le),F=T?new Set(d):Bt(f.blockBuckets,_.camera.x,_.camera.z,Le),R=ra(f,_.camera.x,_.camera.z,Le),D=new Set,E=new Set,P=new Set,G=new Set,z=Le*Le;rn(D,C,f.tileById,"tile",R,_.frustum,_.camera,_.sphere,z,_),rn(E,B,f.wallById,"wall",R,_.frustum,_.camera,_.sphere,z,_),rn(G,I,f.objectById,"object",R,_.frustum,_.camera,_.sphere,z,_),rn(P,F,f.blockById,"block",R,_.frustum,_.camera,_.sphere,z,_);const L={tileIds:D,wallIds:E,blockIds:P,objectIds:G};if(M.current.set(w,L),M.current.size>96){const h=M.current.keys().next().value;h&&M.current.delete(h)}p({tileIds:L.tileIds,wallIds:L.wallIds,blockIds:L.blockIds,objectIds:L.objectIds})}),null}const Mc=9,jc=150;function wc(){const{gl:e}=ae.useThree(),{updateMousePosition:s,placeWall:n,placeTile:i,placeBlock:o,placeObject:r,handleWallClick:a,handleTileClick:l,handleBlockClick:c}=No(),d=S.useBuildingStore(T=>T.editMode),g=d!=="none",p=S.useBuildingStore(T=>T.setHoverPosition),m=S.useBuildingStore(T=>T.setWallRotation),f=S.useBuildingStore(T=>T.setTileRotation),y=S.useBuildingStore(T=>T.setObjectRotation),M=S.useBuildingStore(T=>T.setTileHeight),_=S.useBuildingStore(T=>T.initialized),j=S.useBuildingStore(T=>T.initializeDefaults),A=u.useRef({x:0,y:0}),w=u.useRef(0),x=u.useCallback(T=>{T&&(T.mouseButtons={LEFT:-1,MIDDLE:b.MOUSE.DOLLY,RIGHT:b.MOUSE.ROTATE})},[]);return u.useEffect(()=>{_||j()},[_,j]),u.useEffect(()=>{if(d!=="wall"&&d!=="tile"&&d!=="block"&&d!=="object")return;const T=C=>{const B=I=>{d==="wall"?m(I):d==="tile"?f(I):d==="object"&&y(I)};switch(C.key){case"ArrowUp":B(0);break;case"ArrowRight":B(Math.PI/2);break;case"ArrowDown":B(Math.PI);break;case"ArrowLeft":B(Math.PI*1.5);break}if(d==="tile"||d==="block"){if(C.code==="KeyQ"||C.key==="q"||C.key==="Q"){const I=S.useBuildingStore.getState().currentTileHeight;M(I-1)}else if(C.code==="KeyE"||C.key==="e"||C.key==="E"){const I=S.useBuildingStore.getState().currentTileHeight;M(I+1)}}};return window.addEventListener("keydown",T),()=>window.removeEventListener("keydown",T)},[d,f,m,y,M]),u.useEffect(()=>{const T=e.domElement,C=F=>{F.button===0&&(A.current.x=F.clientX,A.current.y=F.clientY)},B=F=>s(F),I=F=>{if(F.button!==0)return;const R=F.clientX-A.current.x,D=F.clientY-A.current.y;if(R*R+D*D>Mc)return;const E=performance.now();if(E-w.current<jc)return;w.current=E;const P=S.useBuildingStore.getState().editMode;P!=="npc"&&(P==="wall"?n():P==="tile"?i():P==="block"?o():P==="object"&&r())};return T.addEventListener("mousedown",C),T.addEventListener("mousemove",B),T.addEventListener("mouseup",I),()=>{T.removeEventListener("mousedown",C),T.removeEventListener("mousemove",B),T.removeEventListener("mouseup",I),p(null)}},[e,s,n,i,o,r,p]),t.jsxs(t.Fragment,{children:[t.jsx(Po,{}),t.jsx(Bo,{}),t.jsx(Eo,{}),t.jsx(Ao,{}),t.jsx(Ro,{}),t.jsx(ko,{}),t.jsx(Do,{}),g&&t.jsx(Ge.OrbitControls,{ref:x,enablePan:!0,enableZoom:!0,enableRotate:!0,maxPolarAngle:Math.PI/2.5,minDistance:5,maxDistance:100}),t.jsx(_o,{onWallClick:a,onTileClick:l,onBlockClick:c,onWallDelete:a,onTileDelete:l,onBlockDelete:c}),t.jsx(Co,{})]})}const si=[{type:"none",label:"None"},{type:"water",label:"Water"},{type:"grass",label:"Grass"},{type:"sand",label:"Sand"},{type:"snowfield",label:"Snowfield"}],ii=[{type:"box",label:"Box"},{type:"stairs",label:"Stairs"},{type:"round",label:"Round"},{type:"ramp",label:"Ramp"}];function hs(e){return`${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function _c({onClose:e}){const{setEditMode:s,editMode:n,isInEditMode:i,currentTileMultiplier:o,setTileMultiplier:r,currentTileHeight:a,setTileHeight:l,currentTileShape:c,setTileShape:d,currentTileRotation:g,setTileRotation:p,currentWallRotation:m,setWallRotation:f,wallCategories:y,tileCategories:M,selectedWallCategoryId:_,selectedTileCategoryId:j,selectedWallGroupId:A,selectedTileGroupId:w,selectedWallId:x,selectedTileId:T,setCurrentWallMaterialId:C,setCurrentTileMaterialId:B,setSelectedWallCategory:I,setSelectedTileCategory:F,wallGroups:R,tileGroups:D,meshes:E,updateMesh:P,addMesh:G,updateWall:z,moveWallToGroup:L,updateTile:h,addWallGroup:k,addTileGroup:U,selectedTileObjectType:W,setSelectedTileObjectType:Z,selectedPlacedObjectType:Y,setSelectedPlacedObjectType:$,currentObjectRotation:J,setObjectRotation:ee,selectedModelObjectId:te,setSelectedModelObjectId:X,currentModelUrl:Q,setModelUrl:se,currentModelScale:q,setModelScale:ie,currentModelColor:ue,setModelColor:O}=S.useBuildingStore(dn.useShallow(N=>({setEditMode:N.setEditMode,editMode:N.editMode,isInEditMode:N.isInEditMode,currentTileMultiplier:N.currentTileMultiplier,setTileMultiplier:N.setTileMultiplier,currentTileHeight:N.currentTileHeight,setTileHeight:N.setTileHeight,currentTileShape:N.currentTileShape,setTileShape:N.setTileShape,currentTileRotation:N.currentTileRotation,setTileRotation:N.setTileRotation,currentWallRotation:N.currentWallRotation,setWallRotation:N.setWallRotation,wallCategories:N.wallCategories,tileCategories:N.tileCategories,selectedWallCategoryId:N.selectedWallCategoryId,selectedTileCategoryId:N.selectedTileCategoryId,selectedWallGroupId:N.selectedWallGroupId,selectedTileGroupId:N.selectedTileGroupId,selectedWallId:N.selectedWallId,selectedTileId:N.selectedTileId,setCurrentWallMaterialId:N.setCurrentWallMaterialId,setCurrentTileMaterialId:N.setCurrentTileMaterialId,setSelectedWallCategory:N.setSelectedWallCategory,setSelectedTileCategory:N.setSelectedTileCategory,wallGroups:N.wallGroups,tileGroups:N.tileGroups,meshes:N.meshes,updateMesh:N.updateMesh,addMesh:N.addMesh,updateWall:N.updateWall,moveWallToGroup:N.moveWallToGroup,updateTile:N.updateTile,addWallGroup:N.addWallGroup,addTileGroup:N.addTileGroup,selectedTileObjectType:N.selectedTileObjectType,setSelectedTileObjectType:N.setSelectedTileObjectType,selectedPlacedObjectType:N.selectedPlacedObjectType,setSelectedPlacedObjectType:N.setSelectedPlacedObjectType,currentObjectRotation:N.currentObjectRotation,setObjectRotation:N.setObjectRotation,selectedModelObjectId:N.selectedModelObjectId,setSelectedModelObjectId:N.setSelectedModelObjectId,currentModelUrl:N.currentModelUrl,setModelUrl:N.setModelUrl,currentModelScale:N.currentModelScale,setModelScale:N.setModelScale,currentModelColor:N.currentModelColor,setModelColor:N.setModelColor}))),me=Xo.useAuthStore(N=>N.isLoggedIn),fe=i(),{templates:xe,selectedTemplateId:Me,setSelectedTemplate:Ie,initializeDefaults:le,selectedInstanceId:Qe}=oe(dn.useShallow(N=>({templates:N.templates,selectedTemplateId:N.selectedTemplateId,setSelectedTemplate:N.setSelectedTemplate,initializeDefaults:N.initializeDefaults,selectedInstanceId:N.selectedInstanceId}))),[Ae,bt]=u.useState(!1),[Oe,at]=u.useState(""),[Ce,He]=u.useState("#808080"),[Te,lt]=u.useState(""),In=u.useMemo(()=>Array.from(M.values()),[M]),An=u.useMemo(()=>Array.from(y.values()),[y]),Bn=u.useMemo(()=>Array.from(xe.values()),[xe]),En=u.useMemo(()=>si.find(N=>N.type===W)?.label??W,[W]),kn=u.useMemo(()=>ii.find(N=>N.type===c)?.label??c,[c]),Wt=u.useMemo(()=>Dt(te)??it[0],[te]),xt=u.useCallback((N,H)=>{const de=N?E.get(N):void 0,{mapTextureUrl:ve,textureUrl:vt,...Zt}=de??{},yt={...Zt,id:H,color:Ce,material:"STANDARD",...Te?{mapTextureUrl:Te,textureUrl:Te}:{}};return E.has(H)?P(H,yt):G(yt),H},[G,Ce,Te,E,P]),et=u.useCallback(N=>Array.from(R.values()).find(H=>H.walls.some(de=>de.id===N)),[R]),Ht=x?et(x)?.id:A,Rn=u.useCallback(()=>{s("none"),e?.()},[s,e]),$t=u.useCallback(()=>bt(N=>!N),[]);return u.useEffect(()=>{le()},[le]),u.useEffect(()=>{if(n==="wall"&&A){const N=x?et(x):R.get(A),de=(x?N?.walls.find(ve=>ve.id===x):void 0)?.materialId??N?.frontMeshId;if(de){const ve=E.get(de);ve&&(He(ve.color||"#808080"),lt(ve.mapTextureUrl||""))}}else if(n==="tile"&&w){const N=D.get(w);if(N&&N.floorMeshId){const H=E.get(N.floorMeshId);H&&(He(H.color||"#808080"),lt(H.mapTextureUrl||""))}}},[n,A,w,x,et,R,D,E]),me?t.jsxs(t.Fragment,{children:[fe&&t.jsx("div",{className:"building-edit-mode-overlay"}),t.jsx("div",{className:"building-ui-container",children:fe?t.jsxs("div",{className:"building-ui-panel",children:[t.jsxs("div",{className:"building-ui-header",children:[t.jsx("span",{className:"building-ui-title",children:"Building Mode"}),t.jsx("button",{onClick:Rn,className:"building-ui-close",children:"×"})]}),t.jsxs("div",{className:"building-ui-mode-group",children:[t.jsx("button",{onClick:()=>s("wall"),className:`building-ui-mode-button ${n==="wall"?"active":""}`,children:"Wall Mode"}),t.jsx("button",{onClick:()=>s("tile"),className:`building-ui-mode-button ${n==="tile"?"active":""}`,children:"Tile Mode"}),t.jsx("button",{onClick:()=>s("block"),className:`building-ui-mode-button ${n==="block"?"active":""}`,children:"Block Mode"}),t.jsx("button",{onClick:()=>s("npc"),className:`building-ui-mode-button ${n==="npc"?"active":""}`,children:"NPC Mode"}),t.jsx("button",{onClick:()=>{$("model"),s("object")},className:`building-ui-mode-button ${n==="object"?"active":""}`,children:"Object Mode"})]}),n==="tile"&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Category:"}),t.jsx("select",{value:j||"",onChange:N=>F(N.target.value),className:"building-ui-select",children:In.map(N=>t.jsx("option",{value:N.id,children:N.name},N.id))})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Type:"}),t.jsx("select",{value:w||"",onChange:N=>S.useBuildingStore.setState({selectedTileGroupId:N.target.value}),className:"building-ui-select",children:j&&M.get(j)?.tileGroupIds.map(N=>{const H=D.get(N);return H?t.jsx("option",{value:H.id,children:H.name},H.id):null})})]}),t.jsxs("button",{onClick:$t,className:"building-ui-custom-toggle",children:[Ae?"Hide":"Show"," Custom Settings"]}),Ae&&t.jsxs("div",{className:"building-ui-custom-settings",children:[t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Name:"}),t.jsx("input",{type:"text",value:Oe,onChange:N=>at(N.target.value),placeholder:"Custom Floor Name",className:"building-ui-input"})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Color:"}),t.jsxs("div",{className:"building-ui-color-input",children:[t.jsx("input",{type:"color",value:Ce,onChange:N=>He(N.target.value),className:"building-ui-color-picker"}),t.jsx("input",{type:"text",value:Ce,onChange:N=>He(N.target.value),className:"building-ui-input",style:{width:"100px"}})]})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Texture URL:"}),t.jsx("input",{type:"text",value:Te,onChange:N=>lt(N.target.value),placeholder:"https://...",className:"building-ui-input"})]}),t.jsx("button",{onClick:()=>{if(w){const N=D.get(w);if(N&&N.floorMeshId){const H=T?xt(N.floorMeshId,`custom-tile-mesh-${T}`):xt(N.floorMeshId,hs("custom-placement-tile-mesh"));if(T){h(N.id,T,{materialId:H});return}B(H)}}},className:"building-ui-apply-button",children:"Apply Changes"}),t.jsx("button",{onClick:()=>{if(Oe){const N=`custom-tile-${Date.now()}`,H=`custom-floor-mesh-${Date.now()}`;if(G({id:H,color:Ce,material:"STANDARD",...Te?{mapTextureUrl:Te}:{},roughness:.6}),U({id:N,name:Oe,floorMeshId:H,tiles:[]}),j){const de=M.get(j);de&&S.useBuildingStore.getState().updateTileCategory(j,{tileGroupIds:[...de.tileGroupIds,N]})}S.useBuildingStore.setState({selectedTileGroupId:N}),at("")}},className:"building-ui-create-button",children:"Create New Type"})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Tile Size:"}),t.jsxs("div",{className:"building-ui-size-buttons",children:[t.jsx("button",{onClick:()=>r(1),className:`building-ui-size-button ${o===1?"active":""}`,children:"1x1"}),t.jsx("button",{onClick:()=>r(2),className:`building-ui-size-button ${o===2?"active":""}`,children:"2x2"}),t.jsx("button",{onClick:()=>r(3),className:`building-ui-size-button ${o===3?"active":""}`,children:"3x3"}),t.jsx("button",{onClick:()=>r(4),className:`building-ui-size-button ${o===4?"active":""}`,children:"4x4"})]})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Tile Height:"}),t.jsx("div",{className:"building-ui-size-buttons",children:[0,1,2,3,4].map(N=>t.jsx("button",{onClick:()=>l(N),className:`building-ui-size-button ${a===N?"active":""}`,children:N},N))})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Tile Shape:"}),t.jsx("div",{className:"building-ui-size-buttons",children:ii.map(N=>t.jsx("button",{onClick:()=>d(N.type),className:`building-ui-size-button ${c===N.type?"active":""}`,children:N.label},N.type))})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Tile Rotation:"}),t.jsx("div",{className:"building-ui-size-buttons",children:[0,Math.PI/2,Math.PI,Math.PI*1.5].map((N,H)=>t.jsx("button",{onClick:()=>ee(N),className:`building-ui-size-button ${Math.abs(J-N)<1e-4?"active":""}`,children:H*90},N))})]}),t.jsxs("div",{className:"building-ui-object-group",children:[t.jsx("span",{className:"building-ui-label",children:"Tile Object:"}),t.jsx("div",{className:"building-ui-object-buttons",children:si.map(N=>t.jsx("button",{onClick:()=>Z(N.type),className:`building-ui-object-button ${W===N.type?"active":""}`,children:N.label},N.type))})]}),t.jsxs("div",{className:"building-ui-info",children:[t.jsxs("p",{children:["Category: ",M.get(j||"")?.name]}),t.jsxs("p",{children:["Type: ",D.get(w||"")?.name]}),t.jsxs("p",{children:["Size: ",o,"x",o," (",o*4,"m)"]}),t.jsxs("p",{children:["Height: ",a]}),t.jsxs("p",{children:["Shape: ",kn]}),t.jsxs("p",{children:["Object: ",En]}),t.jsx("p",{children:"Click to place tiles"}),t.jsx("p",{children:"Amber = Occupied, Blue = Available"})]})]}),n==="block"&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Block Size:"}),t.jsx("div",{className:"building-ui-size-buttons",children:[1,2,3,4].map(N=>t.jsxs("button",{onClick:()=>r(N),className:`building-ui-size-button ${o===N?"active":""}`,children:[N,"x",N]},N))})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Layer Offset:"}),t.jsx("div",{className:"building-ui-size-buttons",children:[0,1,2,3,4].map(N=>t.jsx("button",{onClick:()=>l(N),className:`building-ui-size-button ${a===N?"active":""}`,children:N},N))})]}),t.jsxs("div",{className:"building-ui-info",children:[t.jsxs("p",{children:["Size: ",o,"x",o]}),t.jsxs("p",{children:["Layer offset: ",a]}),t.jsx("p",{children:"Click to place voxel blocks"}),t.jsx("p",{children:"Click highlighted blocks to delete"})]})]}),n==="object"&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Object:"}),t.jsx("select",{value:te,onChange:N=>{const H=Dt(N.target.value);X(N.target.value),H&&($("model"),ie(H.defaultScale),O(H.defaultColor),se(H.modelUrl??""))},className:"building-ui-select",children:it.map(N=>t.jsx("option",{value:N.id,children:N.label},N.id))})]}),t.jsxs("div",{className:"building-ui-object-group",children:[t.jsx("span",{className:"building-ui-label",children:"Basic Objects:"}),t.jsx("div",{className:"building-ui-object-buttons",children:it.map(N=>t.jsx("button",{onClick:()=>{$("model"),X(N.id),ie(N.defaultScale),O(N.defaultColor),se(N.modelUrl??"")},className:`building-ui-object-button ${te===N.id?"active":""}`,children:N.label},N.id))})]}),t.jsxs("div",{className:"building-ui-size-group",children:[t.jsx("span",{className:"building-ui-label",children:"Object Rotation:"}),t.jsx("div",{className:"building-ui-size-buttons",children:[0,Math.PI/2,Math.PI,Math.PI*1.5].map((N,H)=>t.jsx("button",{onClick:()=>p(N),className:`building-ui-size-button ${Math.abs(g-N)<1e-4?"active":""}`,children:H*90},N))})]}),t.jsxs("div",{className:"building-ui-custom-settings",children:[t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"GLB URL:"}),t.jsx("input",{type:"text",value:Q,onChange:N=>{$("model"),se(N.target.value)},placeholder:"gltf/props/door.glb",className:"building-ui-input"})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Scale:"}),t.jsx("input",{type:"number",min:"0.1",max:"10",step:"0.1",value:q,onChange:N=>ie(Number(N.target.value)||1),className:"building-ui-input"})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Color:"}),t.jsxs("div",{className:"building-ui-color-input",children:[t.jsx("input",{type:"color",value:ue,onChange:N=>O(N.target.value),className:"building-ui-color-picker"}),t.jsx("input",{type:"text",value:ue,onChange:N=>O(N.target.value),className:"building-ui-input",style:{width:"100px"}})]})]})]}),t.jsxs("div",{className:"building-ui-info",children:[t.jsxs("p",{children:["Type: ",Y==="model"?Wt?.label:"None"]}),t.jsxs("p",{children:["Fallback: ",Wt?.fallbackKind??"generic"]}),t.jsx("p",{children:"GLB URL이 비어 있으면 기본 프리미티브로 표시됩니다."}),t.jsx("p",{children:"Click to place objects"})]})]}),n==="wall"&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Category:"}),t.jsx("select",{value:_||"",onChange:N=>I(N.target.value),className:"building-ui-select",children:An.map(N=>t.jsx("option",{value:N.id,children:N.name},N.id))})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Type:"}),t.jsx("select",{value:Ht||"",onChange:N=>{const H=N.target.value;if(x){L(x,H);return}S.useBuildingStore.setState({selectedWallGroupId:H})},className:"building-ui-select",children:_&&y.get(_)?.wallGroupIds.map(N=>{const H=R.get(N);return H?t.jsx("option",{value:H.id,children:H.name},H.id):null})})]}),t.jsxs("button",{onClick:$t,className:"building-ui-custom-toggle",children:[Ae?"Hide":"Show"," Custom Settings"]}),Ae&&t.jsxs("div",{className:"building-ui-custom-settings",children:[t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Name:"}),t.jsx("input",{type:"text",value:Oe,onChange:N=>at(N.target.value),placeholder:"Custom Wall Name",className:"building-ui-input"})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Color:"}),t.jsxs("div",{className:"building-ui-color-input",children:[t.jsx("input",{type:"color",value:Ce,onChange:N=>He(N.target.value),className:"building-ui-color-picker"}),t.jsx("input",{type:"text",value:Ce,onChange:N=>He(N.target.value),className:"building-ui-input",style:{width:"100px"}})]})]}),t.jsxs("div",{className:"building-ui-input-group",children:[t.jsx("span",{className:"building-ui-label",children:"Texture URL:"}),t.jsx("input",{type:"text",value:Te,onChange:N=>lt(N.target.value),placeholder:"https://...",className:"building-ui-input"})]}),t.jsx("button",{onClick:()=>{if(A){const N=x?et(x):R.get(A);if(!N)return;const de=(x?N.walls.find(vt=>vt.id===x):void 0)?.materialId??N.frontMeshId,ve=xt(de,x?`custom-wall-mesh-${x}`:hs("custom-placement-wall-mesh"));if(x){z(N.id,x,{materialId:ve});return}C(ve)}},className:"building-ui-apply-button",children:"Apply Changes"}),t.jsx("button",{onClick:()=>{if(Oe){const N=`custom-wall-${Date.now()}`,H=`custom-mesh-${Date.now()}`;if(G({id:H,color:Ce,material:"STANDARD",...Te?{mapTextureUrl:Te}:{},roughness:.7}),k({id:N,name:Oe,frontMeshId:H,backMeshId:H,sideMeshId:H,walls:[]}),_){const de=y.get(_);de&&S.useBuildingStore.getState().updateWallCategory(_,{wallGroupIds:[...de.wallGroupIds,N]})}S.useBuildingStore.setState({selectedWallGroupId:N}),at("")}},className:"building-ui-create-button",children:"Create New Type"})]}),t.jsxs("div",{className:"building-ui-direction-group",children:[t.jsx("span",{className:"building-ui-label",children:"Wall Direction:"}),t.jsxs("div",{className:"building-ui-direction-buttons",children:[t.jsx("button",{onClick:()=>f(0),className:`building-ui-direction-button ${m===0?"active":""}`,title:"North",children:"↑"}),t.jsx("button",{onClick:()=>f(Math.PI/2),className:`building-ui-direction-button ${m===Math.PI/2?"active":""}`,title:"East",children:"→"}),t.jsx("button",{onClick:()=>f(Math.PI),className:`building-ui-direction-button ${m===Math.PI?"active":""}`,title:"South",children:"↓"}),t.jsx("button",{onClick:()=>f(Math.PI*1.5),className:`building-ui-direction-button ${m===Math.PI*1.5?"active":""}`,title:"West",children:"←"})]})]}),t.jsxs("div",{className:"building-ui-info",children:[t.jsxs("p",{children:["Category: ",y.get(_||"")?.name]}),t.jsxs("p",{children:["Type: ",R.get(A||"")?.name]}),t.jsx("p",{children:"Use arrow keys to rotate"}),t.jsx("p",{children:"Click to place walls"}),t.jsx("p",{children:"Amber = Occupied, Blue = Available"}),t.jsx("p",{children:"Click highlighted markers to delete"})]})]}),n==="npc"&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"캐릭터:"}),t.jsx("select",{value:Me||"",onChange:N=>Ie(N.target.value),className:"building-ui-select",children:Bn.map(N=>t.jsx("option",{value:N.id,children:N.name},N.id))})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"옷:"}),t.jsxs("div",{className:"building-ui-clothing-buttons",children:[["rabbit-outfit","basic-suit","formal-suit"].map(N=>{const H=oe.getState().clothingSets.get(N);return H?t.jsx("button",{onClick:()=>oe.getState().setSelectedClothingSet(H.id),className:`building-ui-clothing-button ${oe.getState().selectedClothingSetId===H.id?"active":""}`,children:H.name},H.id):null}),t.jsx("button",{onClick:()=>oe.getState().setSelectedClothingSet(""),className:`building-ui-clothing-button ${oe.getState().selectedClothingSetId?"":"active"}`,children:"없음"})]})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"모자:"}),t.jsxs("div",{className:"building-ui-clothing-buttons",children:[["hat-set-a","hat-set-b","hat-set-c"].map(N=>{const H=oe.getState().clothingSets.get(N);return H?t.jsx("button",{onClick:()=>{oe.getState().setPreviewAccessory("hat",H.id);const de=oe.getState().selectedInstanceId,ve=H.parts[0];de&&ve&&oe.getState().updateInstancePart(de,ve.id,ve)},className:`building-ui-clothing-button ${oe.getState().previewAccessories.hat===H.id?"active":""}`,children:H.name},H.id):null}),t.jsx("button",{onClick:()=>oe.getState().setPreviewAccessory("hat",""),className:`building-ui-clothing-button ${oe.getState().previewAccessories.hat?"":"active"}`,children:"없음"})]})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"안경:"}),t.jsxs("div",{className:"building-ui-clothing-buttons",children:[["glasses-set-a","glasses-set-b"].map(N=>{const H=oe.getState().clothingSets.get(N);return H?t.jsx("button",{onClick:()=>oe.getState().setPreviewAccessory("glasses",H.id),className:`building-ui-clothing-button ${oe.getState().previewAccessories.glasses===H.id?"active":""}`,children:H.name},H.id):null}),t.jsx("button",{onClick:()=>oe.getState().setPreviewAccessory("glasses",""),className:`building-ui-clothing-button ${oe.getState().previewAccessories.glasses?"":"active"}`,children:"없음"})]})]}),t.jsxs("div",{className:"building-ui-category-group",children:[t.jsx("span",{className:"building-ui-label",children:"Selected Instance:"}),t.jsx("span",{className:"building-ui-info-value",children:Qe||"None"})]}),Me&&xe.get(Me)&&t.jsxs("div",{className:"building-ui-info",children:[t.jsxs("p",{children:["현재 선택: ",xe.get(Me)?.name]}),t.jsx("p",{children:"클릭하여 NPC 배치"}),t.jsx("p",{children:"배치된 NPC를 클릭하여 선택"})]})]})]}):null})]}):null}const Cc="gaesup.building",Tc="building.square",Nc="building.placement",Ic="building",Ac="building.store";function Fo(e={}){const s=e.id??Cc,n=e.gridExtensionId??Tc,i=e.placementExtensionId??Nc,o=e.saveExtensionId??Ic,r=e.storeServiceId??Ac;return{id:s,name:"GaeSup Building",version:"0.1.0",runtime:"client",capabilities:["building","grid","placement"],setup:l=>{l.grid.register(n,S.buildingGridAdapter,s),l.placement.register(i,{adapter:S.buildingPlacementAdapter,createEngine:S.createBuildingPlacementEngine,toEntries:S.buildingGroupsToPlacementEntries,blockToEntry:S.blockToPlacementEntry,tileToEntry:S.tileToPlacementEntry,wallToEntry:S.wallToPlacementEntry},s),l.save.register(o,{key:o,serialize:()=>S.useBuildingStore.getState().serialize(),hydrate:c=>S.useBuildingStore.getState().hydrate(c)},s),l.services.register(r,{useStore:S.useBuildingStore,getState:S.useBuildingStore.getState,setState:S.useBuildingStore.setState},s),l.events.emit("building:ready",{pluginId:s,gridExtensionId:n,placementExtensionId:i,saveExtensionId:o,storeServiceId:r})},dispose(l){l.grid.remove(n),l.placement.remove(i),l.save.remove(o),l.services.remove(r)}}}const Bc=Fo();function Ec(){const e=u.useMemo(()=>({frustum:new b.Frustum,matrix:new b.Matrix4,camPos:new b.Vector3}),[]);return ae.useFrame((s,n)=>{const i=s.camera;zt().size()!==0&&(e.matrix.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),e.frustum.setFromProjectionMatrix(e.matrix),e.camPos.copy(i.position),zt().tick({elapsedTime:s.clock.elapsedTime,delta:n,cameraPosition:e.camPos,frustum:e.frustum}))}),null}exports.AnimationDebugPanel=ci;exports.AnimationPanel=ui;exports.Billboard=Ki;exports.BlockSystem=Zi;exports.BuildingController=wc;exports.BuildingGpuCullingDriver=Ao;exports.BuildingGpuMirrorDriver=Bo;exports.BuildingGpuUploadDriver=Eo;exports.BuildingIndirectArgsUploadDriver=ko;exports.BuildingIndirectDrawDriver=Ro;exports.BuildingRenderStateDriver=Po;exports.BuildingSystem=_o;exports.BuildingUI=_c;exports.BuildingVisibilityDriver=Do;exports.CameraDebugPanel=ri;exports.CameraPanel=li;exports.CameraPresets=ai;exports.DEFAULT_BUILDING_OBJECT_CATALOG=it;exports.DRAW_CLUSTER_BILLBOARD=wn;exports.DRAW_CLUSTER_BLOCK=_n;exports.DRAW_CLUSTER_COUNT=Tn;exports.DRAW_CLUSTER_DESCRIPTORS=Li;exports.DRAW_CLUSTER_FIRE=jn;exports.DRAW_CLUSTER_FLAG=Mn;exports.DRAW_CLUSTER_GRASS=ws;exports.DRAW_CLUSTER_MODEL=Cn;exports.DRAW_CLUSTER_SAKURA=Sn;exports.DRAW_CLUSTER_SAND=ht;exports.DRAW_CLUSTER_SNOWFIELD=gt;exports.DRAW_CLUSTER_TILE=mt;exports.DRAW_CLUSTER_WALL=yn;exports.DRAW_CLUSTER_WATER=ft;exports.Editor=Ur;exports.EditorLayout=bi;exports.FACE_STYLE_LABEL=Sr;exports.GPU_META_STRIDE=Lt;exports.GPU_SPATIAL_STRIDE=Ft;exports.GameplayEventPanel=kr;exports.Grass=As;exports.GrassDriver=Ec;exports.GridHelper=Vi;exports.HAIR_STYLE_LABEL=yr;exports.INDIRECT_DRAW_STRIDE=ke;exports.MotionController=di;exports.MotionDebugPanel=pi;exports.MotionPanel=mi;exports.NPCSystem=Co;exports.OUTFIT_SLOT_LABEL=gi;exports.Ocean=vo;exports.PerformancePanel=fi;exports.ResizablePanel=cn;exports.Sakura=ol;exports.SakuraBatch=po;exports.Sand=xl;exports.SandBatch=ho;exports.Snow=Ns;exports.Snowfield=yl;exports.SnowfieldBatch=bo;exports.StudioPanel=Lr;exports.TileSystem=Mo;exports.VehiclePanel=hi;exports.WallSystem=wo;exports.autoDetectProfile=ls;exports.buildBuildingGpuMirror=Oi;exports.buildBuildingIndirectDrawMirror=Gi;exports.buildingPlugin=Bc;exports.classifyTier=yi;exports.createBuildingGpuUploadPlan=Ui;exports.createBuildingIndirectDrawUploadPlan=zi;exports.createBuildingPlugin=Fo;exports.createCustomMeshId=hs;exports.createEditorCommandStack=Zr;exports.createEditorShell=$r;exports.createEditorSlice=xs;exports.createEmptyBuildingGpuUploadResources=Gt;exports.createEmptyBuildingIndirectDrawMirror=_s;exports.createEmptyGpuMirror=Cs;exports.createTerrainBlockMaterial=Es;exports.destroyBuildingGpuUploadResources=Wi;exports.detectCapabilities=vi;exports.editorSlice=Wr;exports.findTerrainBlockMaterial=To;exports.getDefaultBuildingObject=Dt;exports.getDrawClusterForSnapshotEntry=Di;exports.getGrassManager=zt;exports.getIndirectInstanceCount=Ne;exports.getWallMaterialKey=jo;exports.getWebGPUDeviceFromRenderer=Nn;exports.index=Ba;exports.parseBuildingGpuVisibilityFlags=Fi;exports.profileForTier=vn;exports.syncBuildingGpuBuffers=Hi;exports.syncBuildingIndirectArgsBuffer=$i;exports.useBuildingEditor=No;exports.useBuildingGpuCullingStore=_e;exports.useBuildingRenderStateStore=ge;exports.useBuildingVisibilityStore=Ze;exports.useCharacterStore=an;exports.useEditor=Hr;exports.useEditorStore=xi;exports.useNPCStore=oe;exports.usePerfStore=Si;
|