blockymodel-web 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/dist/blockymodel-web.js +2717 -0
  3. package/dist/blockymodel-web.js.map +1 -0
  4. package/dist/blockymodel-web.umd.cjs +122 -0
  5. package/dist/blockymodel-web.umd.cjs.map +1 -0
  6. package/dist/editor/Editor.d.ts +94 -0
  7. package/dist/editor/Editor.d.ts.map +1 -0
  8. package/dist/editor/History.d.ts +52 -0
  9. package/dist/editor/History.d.ts.map +1 -0
  10. package/dist/editor/SelectionManager.d.ts +57 -0
  11. package/dist/editor/SelectionManager.d.ts.map +1 -0
  12. package/dist/editor/Serializer.d.ts +44 -0
  13. package/dist/editor/Serializer.d.ts.map +1 -0
  14. package/dist/editor/TransformManager.d.ts +73 -0
  15. package/dist/editor/TransformManager.d.ts.map +1 -0
  16. package/dist/editor/commands/AddNodeCommand.d.ts +24 -0
  17. package/dist/editor/commands/AddNodeCommand.d.ts.map +1 -0
  18. package/dist/editor/commands/Command.d.ts +50 -0
  19. package/dist/editor/commands/Command.d.ts.map +1 -0
  20. package/dist/editor/commands/RemoveNodeCommand.d.ts +28 -0
  21. package/dist/editor/commands/RemoveNodeCommand.d.ts.map +1 -0
  22. package/dist/editor/commands/SetPositionCommand.d.ts +24 -0
  23. package/dist/editor/commands/SetPositionCommand.d.ts.map +1 -0
  24. package/dist/editor/commands/SetPropertyCommand.d.ts +41 -0
  25. package/dist/editor/commands/SetPropertyCommand.d.ts.map +1 -0
  26. package/dist/editor/commands/SetRotationCommand.d.ts +24 -0
  27. package/dist/editor/commands/SetRotationCommand.d.ts.map +1 -0
  28. package/dist/editor/commands/SetScaleCommand.d.ts +24 -0
  29. package/dist/editor/commands/SetScaleCommand.d.ts.map +1 -0
  30. package/dist/editor/index.d.ts +15 -0
  31. package/dist/editor/index.d.ts.map +1 -0
  32. package/dist/index.d.ts +21 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/loaders/BlockyModelLoader.d.ts +48 -0
  35. package/dist/loaders/BlockyModelLoader.d.ts.map +1 -0
  36. package/dist/types/blockymodel.d.ts +72 -0
  37. package/dist/types/blockymodel.d.ts.map +1 -0
  38. package/dist/ui/HierarchyPanel.d.ts +73 -0
  39. package/dist/ui/HierarchyPanel.d.ts.map +1 -0
  40. package/dist/ui/PropertyPanel.d.ts +59 -0
  41. package/dist/ui/PropertyPanel.d.ts.map +1 -0
  42. package/dist/ui/UVEditor.d.ts +56 -0
  43. package/dist/ui/UVEditor.d.ts.map +1 -0
  44. package/dist/ui/index.d.ts +4 -0
  45. package/dist/ui/index.d.ts.map +1 -0
  46. package/dist/viewer/ViewerController.d.ts +71 -0
  47. package/dist/viewer/ViewerController.d.ts.map +1 -0
  48. package/package.json +63 -0
  49. package/src/editor/Editor.ts +196 -0
  50. package/src/editor/History.ts +123 -0
  51. package/src/editor/SelectionManager.ts +183 -0
  52. package/src/editor/Serializer.ts +212 -0
  53. package/src/editor/TransformManager.ts +270 -0
  54. package/src/editor/commands/AddNodeCommand.ts +53 -0
  55. package/src/editor/commands/Command.ts +63 -0
  56. package/src/editor/commands/RemoveNodeCommand.ts +59 -0
  57. package/src/editor/commands/SetPositionCommand.ts +51 -0
  58. package/src/editor/commands/SetPropertyCommand.ts +100 -0
  59. package/src/editor/commands/SetRotationCommand.ts +51 -0
  60. package/src/editor/commands/SetScaleCommand.ts +51 -0
  61. package/src/editor/index.ts +19 -0
  62. package/src/index.ts +49 -0
  63. package/src/loaders/BlockyModelLoader.ts +281 -0
  64. package/src/main.ts +290 -0
  65. package/src/styles.css +597 -0
  66. package/src/types/blockymodel.ts +82 -0
  67. package/src/ui/HierarchyPanel.ts +343 -0
  68. package/src/ui/PropertyPanel.ts +434 -0
  69. package/src/ui/UVEditor.ts +336 -0
  70. package/src/ui/index.ts +4 -0
  71. package/src/viewer/ViewerController.ts +295 -0
@@ -0,0 +1,122 @@
1
+ (function(p,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],s):(p=typeof globalThis<"u"?globalThis:p||self,s(p.BlockyModelWeb={},p.THREE))})(this,(function(p,s){"use strict";var Me=Object.defineProperty;var Se=(p,s,B)=>s in p?Me(p,s,{enumerable:!0,configurable:!0,writable:!0,value:B}):p[s]=B;var h=(p,s,B)=>Se(p,typeof s!="symbol"?s+"":s,B);function B(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const i=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const c=B(s),At=4491519,Yt=.3;class gt{constructor(t){h(this,"editor");h(this,"raycaster");h(this,"mouse");h(this,"selected",null);h(this,"highlightedMaterials",new Map);h(this,"eventListeners",new Map);this.editor=t,this.raycaster=new c.Raycaster,this.mouse=new c.Vector2,this.handleClick=this.handleClick.bind(this),this.editor.domElement.addEventListener("click",this.handleClick)}handleClick(t){if(t.target!==this.editor.renderer.domElement)return;const e=this.editor.domElement.getBoundingClientRect();this.mouse.x=(t.clientX-e.left)/e.width*2-1,this.mouse.y=-((t.clientY-e.top)/e.height)*2+1,this.raycaster.setFromCamera(this.mouse,this.editor.camera);const i=this.editor.getModel();if(!i){this.deselect();return}const o=[];i.traverse(n=>{n instanceof c.Mesh&&n.visible&&(this.isTransformControlPart(n)||o.push(n))});const a=this.raycaster.intersectObjects(o,!1);if(a.length>0){let n=a[0].object;for(;n.parent&&!n.userData.id&&n.parent!==i;)n=n.parent;this.select(n)}else this.deselect()}isTransformControlPart(t){let e=t;for(;e;){if(e.type==="TransformControlsGizmo"||e.type==="TransformControlsPlane")return!0;e=e.parent}return!1}select(t){t!==this.selected&&(this.removeHighlight(),this.selected=t,t&&this.applyHighlight(t),this.emit("selectionChanged",t))}deselect(){this.select(null)}getSelected(){return this.selected}applyHighlight(t){t.traverse(e=>{if(e instanceof c.Mesh){const i=e.material;i.emissive&&(this.highlightedMaterials.set(e,{emissive:i.emissive.clone(),emissiveIntensity:i.emissiveIntensity}),i.emissive.setHex(At),i.emissiveIntensity=Yt)}})}removeHighlight(){this.highlightedMaterials.forEach((t,e)=>{const i=e.material;i.emissive&&(i.emissive.copy(t.emissive),i.emissiveIntensity=t.emissiveIntensity)}),this.highlightedMaterials.clear()}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}emit(t,...e){var i;(i=this.eventListeners.get(t))==null||i.forEach(o=>o(e[0]))}dispose(){this.editor.domElement.removeEventListener("click",this.handleClick),this.removeHighlight(),this.eventListeners.clear()}}const V=new s.Raycaster,_=new s.Vector3,U=new s.Vector3,g=new s.Quaternion,bt={X:new s.Vector3(1,0,0),Y:new s.Vector3(0,1,0),Z:new s.Vector3(0,0,1)},ct={type:"change"},wt={type:"mouseDown",mode:null},_t={type:"mouseUp",mode:null},xt={type:"objectChange"};class Nt extends s.Controls{constructor(t,e=null){super(void 0,e);const i=new Zt(this);this._root=i;const o=new Gt;this._gizmo=o,i.add(o);const a=new Qt;this._plane=a,i.add(a);const n=this;function l(w,I){let z=I;Object.defineProperty(n,w,{get:function(){return z!==void 0?z:I},set:function(Y){z!==Y&&(z=Y,a[w]=Y,o[w]=Y,n.dispatchEvent({type:w+"-changed",value:Y}),n.dispatchEvent(ct))}}),n[w]=I,a[w]=I,o[w]=I}l("camera",t),l("object",void 0),l("enabled",!0),l("axis",null),l("mode","translate"),l("translationSnap",null),l("rotationSnap",null),l("scaleSnap",null),l("space","world"),l("size",1),l("dragging",!1),l("showX",!0),l("showY",!0),l("showZ",!0),l("minX",-1/0),l("maxX",1/0),l("minY",-1/0),l("maxY",1/0),l("minZ",-1/0),l("maxZ",1/0);const d=new s.Vector3,u=new s.Vector3,y=new s.Quaternion,x=new s.Quaternion,D=new s.Vector3,yt=new s.Quaternion,Z=new s.Vector3,L=new s.Vector3,O=new s.Vector3,S=0,v=new s.Vector3;l("worldPosition",d),l("worldPositionStart",u),l("worldQuaternion",y),l("worldQuaternionStart",x),l("cameraPosition",D),l("cameraQuaternion",yt),l("pointStart",Z),l("pointEnd",L),l("rotationAxis",O),l("rotationAngle",S),l("eye",v),this._offset=new s.Vector3,this._startNorm=new s.Vector3,this._endNorm=new s.Vector3,this._cameraScale=new s.Vector3,this._parentPosition=new s.Vector3,this._parentQuaternion=new s.Quaternion,this._parentQuaternionInv=new s.Quaternion,this._parentScale=new s.Vector3,this._worldScaleStart=new s.Vector3,this._worldQuaternionInv=new s.Quaternion,this._worldScale=new s.Vector3,this._positionStart=new s.Vector3,this._quaternionStart=new s.Quaternion,this._scaleStart=new s.Vector3,this._getPointer=Ut.bind(this),this._onPointerDown=Ft.bind(this),this._onPointerHover=Vt.bind(this),this._onPointerMove=Xt.bind(this),this._onPointerUp=Bt.bind(this),e!==null&&this.connect()}connect(){this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointermove",this._onPointerHover),this.domElement.addEventListener("pointerup",this._onPointerUp),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointermove",this._onPointerHover),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.domElement.style.touchAction="auto"}getHelper(){return this._root}pointerHover(t){if(this.object===void 0||this.dragging===!0)return;t!==null&&V.setFromCamera(t,this.camera);const e=dt(this._gizmo.picker[this.mode],V);e?this.axis=e.object.name:this.axis=null}pointerDown(t){if(!(this.object===void 0||this.dragging===!0||t!=null&&t.button!==0)&&this.axis!==null){t!==null&&V.setFromCamera(t,this.camera);const e=dt(this._plane,V,!0);e&&(this.object.updateMatrixWorld(),this.object.parent.updateMatrixWorld(),this._positionStart.copy(this.object.position),this._quaternionStart.copy(this.object.quaternion),this._scaleStart.copy(this.object.scale),this.object.matrixWorld.decompose(this.worldPositionStart,this.worldQuaternionStart,this._worldScaleStart),this.pointStart.copy(e.point).sub(this.worldPositionStart)),this.dragging=!0,wt.mode=this.mode,this.dispatchEvent(wt)}}pointerMove(t){const e=this.axis,i=this.mode,o=this.object;let a=this.space;if(i==="scale"?a="local":(e==="E"||e==="XYZE"||e==="XYZ")&&(a="world"),o===void 0||e===null||this.dragging===!1||t!==null&&t.button!==-1)return;t!==null&&V.setFromCamera(t,this.camera);const n=dt(this._plane,V,!0);if(n){if(this.pointEnd.copy(n.point).sub(this.worldPositionStart),i==="translate")this._offset.copy(this.pointEnd).sub(this.pointStart),a==="local"&&e!=="XYZ"&&this._offset.applyQuaternion(this._worldQuaternionInv),e.indexOf("X")===-1&&(this._offset.x=0),e.indexOf("Y")===-1&&(this._offset.y=0),e.indexOf("Z")===-1&&(this._offset.z=0),a==="local"&&e!=="XYZ"?this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale):this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale),o.position.copy(this._offset).add(this._positionStart),this.translationSnap&&(a==="local"&&(o.position.applyQuaternion(g.copy(this._quaternionStart).invert()),e.search("X")!==-1&&(o.position.x=Math.round(o.position.x/this.translationSnap)*this.translationSnap),e.search("Y")!==-1&&(o.position.y=Math.round(o.position.y/this.translationSnap)*this.translationSnap),e.search("Z")!==-1&&(o.position.z=Math.round(o.position.z/this.translationSnap)*this.translationSnap),o.position.applyQuaternion(this._quaternionStart)),a==="world"&&(o.parent&&o.position.add(_.setFromMatrixPosition(o.parent.matrixWorld)),e.search("X")!==-1&&(o.position.x=Math.round(o.position.x/this.translationSnap)*this.translationSnap),e.search("Y")!==-1&&(o.position.y=Math.round(o.position.y/this.translationSnap)*this.translationSnap),e.search("Z")!==-1&&(o.position.z=Math.round(o.position.z/this.translationSnap)*this.translationSnap),o.parent&&o.position.sub(_.setFromMatrixPosition(o.parent.matrixWorld)))),o.position.x=Math.max(this.minX,Math.min(this.maxX,o.position.x)),o.position.y=Math.max(this.minY,Math.min(this.maxY,o.position.y)),o.position.z=Math.max(this.minZ,Math.min(this.maxZ,o.position.z));else if(i==="scale"){if(e.search("XYZ")!==-1){let l=this.pointEnd.length()/this.pointStart.length();this.pointEnd.dot(this.pointStart)<0&&(l*=-1),U.set(l,l,l)}else _.copy(this.pointStart),U.copy(this.pointEnd),_.applyQuaternion(this._worldQuaternionInv),U.applyQuaternion(this._worldQuaternionInv),U.divide(_),e.search("X")===-1&&(U.x=1),e.search("Y")===-1&&(U.y=1),e.search("Z")===-1&&(U.z=1);o.scale.copy(this._scaleStart).multiply(U),this.scaleSnap&&(e.search("X")!==-1&&(o.scale.x=Math.round(o.scale.x/this.scaleSnap)*this.scaleSnap||this.scaleSnap),e.search("Y")!==-1&&(o.scale.y=Math.round(o.scale.y/this.scaleSnap)*this.scaleSnap||this.scaleSnap),e.search("Z")!==-1&&(o.scale.z=Math.round(o.scale.z/this.scaleSnap)*this.scaleSnap||this.scaleSnap))}else if(i==="rotate"){this._offset.copy(this.pointEnd).sub(this.pointStart);const l=20/this.worldPosition.distanceTo(_.setFromMatrixPosition(this.camera.matrixWorld));let d=!1;e==="XYZE"?(this.rotationAxis.copy(this._offset).cross(this.eye).normalize(),this.rotationAngle=this._offset.dot(_.copy(this.rotationAxis).cross(this.eye))*l):(e==="X"||e==="Y"||e==="Z")&&(this.rotationAxis.copy(bt[e]),_.copy(bt[e]),a==="local"&&_.applyQuaternion(this.worldQuaternion),_.cross(this.eye),_.length()===0?d=!0:this.rotationAngle=this._offset.dot(_.normalize())*l),(e==="E"||d)&&(this.rotationAxis.copy(this.eye),this.rotationAngle=this.pointEnd.angleTo(this.pointStart),this._startNorm.copy(this.pointStart).normalize(),this._endNorm.copy(this.pointEnd).normalize(),this.rotationAngle*=this._endNorm.cross(this._startNorm).dot(this.eye)<0?1:-1),this.rotationSnap&&(this.rotationAngle=Math.round(this.rotationAngle/this.rotationSnap)*this.rotationSnap),a==="local"&&e!=="E"&&e!=="XYZE"?(o.quaternion.copy(this._quaternionStart),o.quaternion.multiply(g.setFromAxisAngle(this.rotationAxis,this.rotationAngle)).normalize()):(this.rotationAxis.applyQuaternion(this._parentQuaternionInv),o.quaternion.copy(g.setFromAxisAngle(this.rotationAxis,this.rotationAngle)),o.quaternion.multiply(this._quaternionStart).normalize())}this.dispatchEvent(ct),this.dispatchEvent(xt)}}pointerUp(t){t!==null&&t.button!==0||(this.dragging&&this.axis!==null&&(_t.mode=this.mode,this.dispatchEvent(_t)),this.dragging=!1,this.axis=null)}dispose(){this.disconnect(),this._root.dispose()}attach(t){return this.object=t,this._root.visible=!0,this}detach(){return this.object=void 0,this.axis=null,this._root.visible=!1,this}reset(){this.enabled&&this.dragging&&(this.object.position.copy(this._positionStart),this.object.quaternion.copy(this._quaternionStart),this.object.scale.copy(this._scaleStart),this.dispatchEvent(ct),this.dispatchEvent(xt),this.pointStart.copy(this.pointEnd))}getRaycaster(){return V}getMode(){return this.mode}setMode(t){this.mode=t}setTranslationSnap(t){this.translationSnap=t}setRotationSnap(t){this.rotationSnap=t}setScaleSnap(t){this.scaleSnap=t}setSize(t){this.size=t}setSpace(t){this.space=t}}function Ut(r){if(this.domElement.ownerDocument.pointerLockElement)return{x:0,y:0,button:r.button};{const t=this.domElement.getBoundingClientRect();return{x:(r.clientX-t.left)/t.width*2-1,y:-(r.clientY-t.top)/t.height*2+1,button:r.button}}}function Vt(r){if(this.enabled)switch(r.pointerType){case"mouse":case"pen":this.pointerHover(this._getPointer(r));break}}function Ft(r){this.enabled&&(document.pointerLockElement||this.domElement.setPointerCapture(r.pointerId),this.domElement.addEventListener("pointermove",this._onPointerMove),this.pointerHover(this._getPointer(r)),this.pointerDown(this._getPointer(r)))}function Xt(r){this.enabled&&this.pointerMove(this._getPointer(r))}function Bt(r){this.enabled&&(this.domElement.releasePointerCapture(r.pointerId),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.pointerUp(this._getPointer(r)))}function dt(r,t,e){const i=t.intersectObject(r,!0);for(let o=0;o<i.length;o++)if(i[o].object.visible||e)return i[o];return!1}const R=new s.Euler,f=new s.Vector3(0,1,0),Mt=new s.Vector3(0,0,0),St=new s.Matrix4,H=new s.Quaternion,tt=new s.Quaternion,j=new s.Vector3,vt=new s.Matrix4,Q=new s.Vector3(1,0,0),F=new s.Vector3(0,1,0),T=new s.Vector3(0,0,1),et=new s.Vector3,q=new s.Vector3,W=new s.Vector3;class Zt extends s.Object3D{constructor(t){super(),this.isTransformControlsRoot=!0,this.controls=t,this.visible=!1}updateMatrixWorld(t){const e=this.controls;e.object!==void 0&&(e.object.updateMatrixWorld(),e.object.parent===null?console.error("TransformControls: The attached 3D object must be a part of the scene graph."):e.object.parent.matrixWorld.decompose(e._parentPosition,e._parentQuaternion,e._parentScale),e.object.matrixWorld.decompose(e.worldPosition,e.worldQuaternion,e._worldScale),e._parentQuaternionInv.copy(e._parentQuaternion).invert(),e._worldQuaternionInv.copy(e.worldQuaternion).invert()),e.camera.updateMatrixWorld(),e.camera.matrixWorld.decompose(e.cameraPosition,e.cameraQuaternion,e._cameraScale),e.camera.isOrthographicCamera?e.camera.getWorldDirection(e.eye).negate():e.eye.copy(e.cameraPosition).sub(e.worldPosition).normalize(),super.updateMatrixWorld(t)}dispose(){this.traverse(function(t){t.geometry&&t.geometry.dispose(),t.material&&t.material.dispose()})}}class Gt extends s.Object3D{constructor(){super(),this.isTransformControlsGizmo=!0,this.type="TransformControlsGizmo";const t=new s.MeshBasicMaterial({depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1,transparent:!0}),e=new s.LineBasicMaterial({depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1,transparent:!0}),i=t.clone();i.opacity=.15;const o=e.clone();o.opacity=.5;const a=t.clone();a.color.setHex(16711680);const n=t.clone();n.color.setHex(65280);const l=t.clone();l.color.setHex(255);const d=t.clone();d.color.setHex(16711680),d.opacity=.5;const u=t.clone();u.color.setHex(65280),u.opacity=.5;const y=t.clone();y.color.setHex(255),y.opacity=.5;const x=t.clone();x.opacity=.25;const D=t.clone();D.color.setHex(16776960),D.opacity=.25,t.clone().color.setHex(16776960);const Z=t.clone();Z.color.setHex(7895160);const L=new s.CylinderGeometry(0,.04,.1,12);L.translate(0,.05,0);const O=new s.BoxGeometry(.08,.08,.08);O.translate(0,.04,0);const S=new s.BufferGeometry;S.setAttribute("position",new s.Float32BufferAttribute([0,0,0,1,0,0],3));const v=new s.CylinderGeometry(.0075,.0075,.5,3);v.translate(0,.25,0);function w(C,at){const k=new s.TorusGeometry(C,.0075,3,64,at*Math.PI*2);return k.rotateY(Math.PI/2),k.rotateX(Math.PI/2),k}function I(){const C=new s.BufferGeometry;return C.setAttribute("position",new s.Float32BufferAttribute([0,0,0,1,1,1],3)),C}const z={X:[[new s.Mesh(L,a),[.5,0,0],[0,0,-Math.PI/2]],[new s.Mesh(L,a),[-.5,0,0],[0,0,Math.PI/2]],[new s.Mesh(v,a),[0,0,0],[0,0,-Math.PI/2]]],Y:[[new s.Mesh(L,n),[0,.5,0]],[new s.Mesh(L,n),[0,-.5,0],[Math.PI,0,0]],[new s.Mesh(v,n)]],Z:[[new s.Mesh(L,l),[0,0,.5],[Math.PI/2,0,0]],[new s.Mesh(L,l),[0,0,-.5],[-Math.PI/2,0,0]],[new s.Mesh(v,l),null,[Math.PI/2,0,0]]],XYZ:[[new s.Mesh(new s.OctahedronGeometry(.1,0),x.clone()),[0,0,0]]],XY:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),y.clone()),[.15,.15,0]]],YZ:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),d.clone()),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),u.clone()),[.15,0,.15],[-Math.PI/2,0,0]]]},Y={X:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[.3,0,0],[0,0,-Math.PI/2]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[-.3,0,0],[0,0,Math.PI/2]]],Y:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,.3,0]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,-.3,0],[0,0,Math.PI]]],Z:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,0,.3],[Math.PI/2,0,0]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,0,-.3],[-Math.PI/2,0,0]]],XYZ:[[new s.Mesh(new s.OctahedronGeometry(.2,0),i)]],XY:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[.15,.15,0]]],YZ:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[.15,0,.15],[-Math.PI/2,0,0]]]},nt={START:[[new s.Mesh(new s.OctahedronGeometry(.01,2),o),null,null,null,"helper"]],END:[[new s.Mesh(new s.OctahedronGeometry(.01,2),o),null,null,null,"helper"]],DELTA:[[new s.Line(I(),o),null,null,null,"helper"]],X:[[new s.Line(S,o.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new s.Line(S,o.clone()),[0,-1e3,0],[0,0,Math.PI/2],[1e6,1,1],"helper"]],Z:[[new s.Line(S,o.clone()),[0,0,-1e3],[0,-Math.PI/2,0],[1e6,1,1],"helper"]]},fe={XYZE:[[new s.Mesh(w(.5,1),Z),null,[0,Math.PI/2,0]]],X:[[new s.Mesh(w(.5,.5),a)]],Y:[[new s.Mesh(w(.5,.5),n),null,[0,0,-Math.PI/2]]],Z:[[new s.Mesh(w(.5,.5),l),null,[0,Math.PI/2,0]]],E:[[new s.Mesh(w(.75,1),D),null,[0,Math.PI/2,0]]]},ye={AXIS:[[new s.Line(S,o.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]]},ge={XYZE:[[new s.Mesh(new s.SphereGeometry(.25,10,8),i)]],X:[[new s.Mesh(new s.TorusGeometry(.5,.1,4,24),i),[0,0,0],[0,-Math.PI/2,-Math.PI/2]]],Y:[[new s.Mesh(new s.TorusGeometry(.5,.1,4,24),i),[0,0,0],[Math.PI/2,0,0]]],Z:[[new s.Mesh(new s.TorusGeometry(.5,.1,4,24),i),[0,0,0],[0,0,-Math.PI/2]]],E:[[new s.Mesh(new s.TorusGeometry(.75,.1,2,24),i)]]},be={X:[[new s.Mesh(O,a),[.5,0,0],[0,0,-Math.PI/2]],[new s.Mesh(v,a),[0,0,0],[0,0,-Math.PI/2]],[new s.Mesh(O,a),[-.5,0,0],[0,0,Math.PI/2]]],Y:[[new s.Mesh(O,n),[0,.5,0]],[new s.Mesh(v,n)],[new s.Mesh(O,n),[0,-.5,0],[0,0,Math.PI]]],Z:[[new s.Mesh(O,l),[0,0,.5],[Math.PI/2,0,0]],[new s.Mesh(v,l),[0,0,0],[Math.PI/2,0,0]],[new s.Mesh(O,l),[0,0,-.5],[-Math.PI/2,0,0]]],XY:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),y),[.15,.15,0]]],YZ:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),d),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new s.Mesh(new s.BoxGeometry(.15,.15,.01),u),[.15,0,.15],[-Math.PI/2,0,0]]],XYZ:[[new s.Mesh(new s.BoxGeometry(.1,.1,.1),x.clone())]]},we={X:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[.3,0,0],[0,0,-Math.PI/2]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[-.3,0,0],[0,0,Math.PI/2]]],Y:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,.3,0]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,-.3,0],[0,0,Math.PI]]],Z:[[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,0,.3],[Math.PI/2,0,0]],[new s.Mesh(new s.CylinderGeometry(.2,0,.6,4),i),[0,0,-.3],[-Math.PI/2,0,0]]],XY:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[.15,.15,0]]],YZ:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new s.Mesh(new s.BoxGeometry(.2,.2,.01),i),[.15,0,.15],[-Math.PI/2,0,0]]],XYZ:[[new s.Mesh(new s.BoxGeometry(.2,.2,.2),i),[0,0,0]]]},_e={X:[[new s.Line(S,o.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new s.Line(S,o.clone()),[0,-1e3,0],[0,0,Math.PI/2],[1e6,1,1],"helper"]],Z:[[new s.Line(S,o.clone()),[0,0,-1e3],[0,-Math.PI/2,0],[1e6,1,1],"helper"]]};function N(C){const at=new s.Object3D;for(const k in C)for(let G=C[k].length;G--;){const P=C[k][G][0].clone(),rt=C[k][G][1],ht=C[k][G][2],lt=C[k][G][3],xe=C[k][G][4];P.name=k,P.tag=xe,rt&&P.position.set(rt[0],rt[1],rt[2]),ht&&P.rotation.set(ht[0],ht[1],ht[2]),lt&&P.scale.set(lt[0],lt[1],lt[2]),P.updateMatrix();const jt=P.geometry.clone();jt.applyMatrix4(P.matrix),P.geometry=jt,P.renderOrder=1/0,P.position.set(0,0,0),P.rotation.set(0,0,0),P.scale.set(1,1,1),at.add(P)}return at}this.gizmo={},this.picker={},this.helper={},this.add(this.gizmo.translate=N(z)),this.add(this.gizmo.rotate=N(fe)),this.add(this.gizmo.scale=N(be)),this.add(this.picker.translate=N(Y)),this.add(this.picker.rotate=N(ge)),this.add(this.picker.scale=N(we)),this.add(this.helper.translate=N(nt)),this.add(this.helper.rotate=N(ye)),this.add(this.helper.scale=N(_e)),this.picker.translate.visible=!1,this.picker.rotate.visible=!1,this.picker.scale.visible=!1}updateMatrixWorld(t){const i=(this.mode==="scale"?"local":this.space)==="local"?this.worldQuaternion:tt;this.gizmo.translate.visible=this.mode==="translate",this.gizmo.rotate.visible=this.mode==="rotate",this.gizmo.scale.visible=this.mode==="scale",this.helper.translate.visible=this.mode==="translate",this.helper.rotate.visible=this.mode==="rotate",this.helper.scale.visible=this.mode==="scale";let o=[];o=o.concat(this.picker[this.mode].children),o=o.concat(this.gizmo[this.mode].children),o=o.concat(this.helper[this.mode].children);for(let a=0;a<o.length;a++){const n=o[a];n.visible=!0,n.rotation.set(0,0,0),n.position.copy(this.worldPosition);let l;if(this.camera.isOrthographicCamera?l=(this.camera.top-this.camera.bottom)/this.camera.zoom:l=this.worldPosition.distanceTo(this.cameraPosition)*Math.min(1.9*Math.tan(Math.PI*this.camera.fov/360)/this.camera.zoom,7),n.scale.set(1,1,1).multiplyScalar(l*this.size/4),n.tag==="helper"){n.visible=!1,n.name==="AXIS"?(n.visible=!!this.axis,this.axis==="X"&&(g.setFromEuler(R.set(0,0,0)),n.quaternion.copy(i).multiply(g),Math.abs(f.copy(Q).applyQuaternion(i).dot(this.eye))>.9&&(n.visible=!1)),this.axis==="Y"&&(g.setFromEuler(R.set(0,0,Math.PI/2)),n.quaternion.copy(i).multiply(g),Math.abs(f.copy(F).applyQuaternion(i).dot(this.eye))>.9&&(n.visible=!1)),this.axis==="Z"&&(g.setFromEuler(R.set(0,Math.PI/2,0)),n.quaternion.copy(i).multiply(g),Math.abs(f.copy(T).applyQuaternion(i).dot(this.eye))>.9&&(n.visible=!1)),this.axis==="XYZE"&&(g.setFromEuler(R.set(0,Math.PI/2,0)),f.copy(this.rotationAxis),n.quaternion.setFromRotationMatrix(St.lookAt(Mt,f,F)),n.quaternion.multiply(g),n.visible=this.dragging),this.axis==="E"&&(n.visible=!1)):n.name==="START"?(n.position.copy(this.worldPositionStart),n.visible=this.dragging):n.name==="END"?(n.position.copy(this.worldPosition),n.visible=this.dragging):n.name==="DELTA"?(n.position.copy(this.worldPositionStart),n.quaternion.copy(this.worldQuaternionStart),_.set(1e-10,1e-10,1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1),_.applyQuaternion(this.worldQuaternionStart.clone().invert()),n.scale.copy(_),n.visible=this.dragging):(n.quaternion.copy(i),this.dragging?n.position.copy(this.worldPositionStart):n.position.copy(this.worldPosition),this.axis&&(n.visible=this.axis.search(n.name)!==-1));continue}n.quaternion.copy(i),this.mode==="translate"||this.mode==="scale"?(n.name==="X"&&Math.abs(f.copy(Q).applyQuaternion(i).dot(this.eye))>.99&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),n.name==="Y"&&Math.abs(f.copy(F).applyQuaternion(i).dot(this.eye))>.99&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),n.name==="Z"&&Math.abs(f.copy(T).applyQuaternion(i).dot(this.eye))>.99&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),n.name==="XY"&&Math.abs(f.copy(T).applyQuaternion(i).dot(this.eye))<.2&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),n.name==="YZ"&&Math.abs(f.copy(Q).applyQuaternion(i).dot(this.eye))<.2&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),n.name==="XZ"&&Math.abs(f.copy(F).applyQuaternion(i).dot(this.eye))<.2&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1)):this.mode==="rotate"&&(H.copy(i),f.copy(this.eye).applyQuaternion(g.copy(i).invert()),n.name.search("E")!==-1&&n.quaternion.setFromRotationMatrix(St.lookAt(this.eye,Mt,F)),n.name==="X"&&(g.setFromAxisAngle(Q,Math.atan2(-f.y,f.z)),g.multiplyQuaternions(H,g),n.quaternion.copy(g)),n.name==="Y"&&(g.setFromAxisAngle(F,Math.atan2(f.x,f.z)),g.multiplyQuaternions(H,g),n.quaternion.copy(g)),n.name==="Z"&&(g.setFromAxisAngle(T,Math.atan2(f.y,f.x)),g.multiplyQuaternions(H,g),n.quaternion.copy(g))),n.visible=n.visible&&(n.name.indexOf("X")===-1||this.showX),n.visible=n.visible&&(n.name.indexOf("Y")===-1||this.showY),n.visible=n.visible&&(n.name.indexOf("Z")===-1||this.showZ),n.visible=n.visible&&(n.name.indexOf("E")===-1||this.showX&&this.showY&&this.showZ),n.material._color=n.material._color||n.material.color.clone(),n.material._opacity=n.material._opacity||n.material.opacity,n.material.color.copy(n.material._color),n.material.opacity=n.material._opacity,this.enabled&&this.axis&&(n.name===this.axis||this.axis.split("").some(function(d){return n.name===d}))&&(n.material.color.setHex(16776960),n.material.opacity=1)}super.updateMatrixWorld(t)}}class Qt extends s.Mesh{constructor(){super(new s.PlaneGeometry(1e5,1e5,2,2),new s.MeshBasicMaterial({visible:!1,wireframe:!0,side:s.DoubleSide,transparent:!0,opacity:.1,toneMapped:!1})),this.isTransformControlsPlane=!0,this.type="TransformControlsPlane"}updateMatrixWorld(t){let e=this.space;switch(this.position.copy(this.worldPosition),this.mode==="scale"&&(e="local"),et.copy(Q).applyQuaternion(e==="local"?this.worldQuaternion:tt),q.copy(F).applyQuaternion(e==="local"?this.worldQuaternion:tt),W.copy(T).applyQuaternion(e==="local"?this.worldQuaternion:tt),f.copy(q),this.mode){case"translate":case"scale":switch(this.axis){case"X":f.copy(this.eye).cross(et),j.copy(et).cross(f);break;case"Y":f.copy(this.eye).cross(q),j.copy(q).cross(f);break;case"Z":f.copy(this.eye).cross(W),j.copy(W).cross(f);break;case"XY":j.copy(W);break;case"YZ":j.copy(et);break;case"XZ":f.copy(W),j.copy(q);break;case"XYZ":case"E":j.set(0,0,0);break}break;case"rotate":default:j.set(0,0,0)}j.length()===0?this.quaternion.copy(this.cameraQuaternion):(vt.lookAt(_.set(0,0,0),j,f),this.quaternion.setFromRotationMatrix(vt)),super.updateMatrixWorld(t)}}class X{constructor(t,e=!1){h(this,"object");h(this,"updatable");h(this,"timestamp");this.object=t,this.updatable=e,this.timestamp=Date.now()}}class K extends X{constructor(e,i,o){super(e,!0);h(this,"type","SetPosition");h(this,"updatable",!0);h(this,"newPosition");h(this,"oldPosition");this.newPosition=i.clone(),this.oldPosition=o.clone()}execute(){this.object.position.copy(this.newPosition)}undo(){this.object.position.copy(this.oldPosition)}update(e){e instanceof K&&this.newPosition.copy(e.newPosition)}getNewPosition(){return this.newPosition.clone()}getOldPosition(){return this.oldPosition.clone()}}class $ extends X{constructor(e,i,o){super(e,!0);h(this,"type","SetRotation");h(this,"updatable",!0);h(this,"newRotation");h(this,"oldRotation");this.newRotation=i.clone(),this.oldRotation=o.clone()}execute(){this.object.rotation.copy(this.newRotation)}undo(){this.object.rotation.copy(this.oldRotation)}update(e){e instanceof $&&this.newRotation.copy(e.newRotation)}getNewRotation(){return this.newRotation.clone()}getOldRotation(){return this.oldRotation.clone()}}class J extends X{constructor(e,i,o){super(e,!0);h(this,"type","SetScale");h(this,"updatable",!0);h(this,"newScale");h(this,"oldScale");this.newScale=i.clone(),this.oldScale=o.clone()}execute(){this.object.scale.copy(this.newScale)}undo(){this.object.scale.copy(this.oldScale)}update(e){e instanceof J&&this.newScale.copy(e.newScale)}getNewScale(){return this.newScale.clone()}getOldScale(){return this.oldScale.clone()}}class Pt{constructor(t){h(this,"editor");h(this,"controls");h(this,"mode","translate");h(this,"eventListeners",new Map);h(this,"transformStartPosition",null);h(this,"transformStartRotation",null);h(this,"transformStartScale",null);h(this,"isTransforming",!1);this.editor=t,this.controls=new Nt(this.editor.camera,this.editor.renderer.domElement),this.controls.setSize(.75),this.editor.scene.add(this.controls.getHelper()),this.handleDraggingChanged=this.handleDraggingChanged.bind(this),this.handleObjectChange=this.handleObjectChange.bind(this),this.controls.addEventListener("dragging-changed",this.handleDraggingChanged),this.controls.addEventListener("objectChange",this.handleObjectChange),this.handleKeyDown=this.handleKeyDown.bind(this),document.addEventListener("keydown",this.handleKeyDown)}handleDraggingChanged(t){const e=t.value;this.editor.controls.enabled=!e,e?(this.captureStartState(),this.isTransforming=!0):this.isTransforming&&(this.createCommand(),this.isTransforming=!1)}captureStartState(){const t=this.controls.object;t&&(this.transformStartPosition=t.position.clone(),this.transformStartRotation=t.rotation.clone(),this.transformStartScale=t.scale.clone())}createCommand(){const t=this.controls.object;if(!t)return;let e=null;switch(this.mode){case"translate":this.transformStartPosition&&!t.position.equals(this.transformStartPosition)&&(e=new K(t,t.position.clone(),this.transformStartPosition.clone()));break;case"rotate":this.transformStartRotation&&(t.rotation.x!==this.transformStartRotation.x||t.rotation.y!==this.transformStartRotation.y||t.rotation.z!==this.transformStartRotation.z)&&(e=new $(t,t.rotation.clone(),this.transformStartRotation.clone()));break;case"scale":this.transformStartScale&&!t.scale.equals(this.transformStartScale)&&(e=new J(t,t.scale.clone(),this.transformStartScale.clone()));break}e&&this.emit("objectChanged",t,e),this.transformStartPosition=null,this.transformStartRotation=null,this.transformStartScale=null}handleObjectChange(){const t=this.controls.object;t&&this.emit("objectChanging",t)}handleKeyDown(t){if(!(t.target instanceof HTMLInputElement||t.target instanceof HTMLTextAreaElement))switch(t.key.toLowerCase()){case"g":this.setMode("translate");break;case"r":!t.ctrlKey&&!t.metaKey&&this.setMode("rotate");break;case"s":!t.ctrlKey&&!t.metaKey&&this.setMode("scale");break;case"escape":this.isTransforming&&this.cancelTransform();break}}cancelTransform(){const t=this.controls.object;t&&(this.transformStartPosition&&t.position.copy(this.transformStartPosition),this.transformStartRotation&&t.rotation.copy(this.transformStartRotation),this.transformStartScale&&t.scale.copy(this.transformStartScale),this.isTransforming=!1,this.transformStartPosition=null,this.transformStartRotation=null,this.transformStartScale=null)}attach(t){const e=this.controls.getHelper();t?(this.controls.attach(t),e.visible=!0):(this.controls.detach(),e.visible=!1)}setMode(t){this.mode=t,this.controls.setMode(t),this.emit("modeChanged",t)}getMode(){return this.mode}getControls(){return this.controls}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}emit(t,...e){var i;(i=this.eventListeners.get(t))==null||i.forEach(o=>o(...e))}dispose(){document.removeEventListener("keydown",this.handleKeyDown),this.controls.removeEventListener("dragging-changed",this.handleDraggingChanged),this.controls.removeEventListener("objectChange",this.handleObjectChange),this.controls.dispose(),this.editor.scene.remove(this.controls.getHelper()),this.eventListeners.clear()}}const Tt=500;class It{constructor(){h(this,"undoStack",[]);h(this,"redoStack",[]);h(this,"eventListeners",new Map)}execute(t){t.execute();const e=this.undoStack[this.undoStack.length-1];e&&e.updatable&&t.updatable&&e.type===t.type&&e.object===t.object&&t.timestamp-e.timestamp<Tt?e.update&&e.update(t):this.undoStack.push(t),this.redoStack=[],this.emit("historyChanged")}undo(){const t=this.undoStack.pop();t&&(t.undo(),this.redoStack.push(t),this.emit("historyChanged"))}redo(){const t=this.redoStack.pop();t&&(t.execute(),this.undoStack.push(t),this.emit("historyChanged"))}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[],this.emit("historyChanged")}getUndoCount(){return this.undoStack.length}getRedoCount(){return this.redoStack.length}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}emit(t){var e;(e=this.eventListeners.get(t))==null||e.forEach(i=>i())}}class qt{constructor(t){h(this,"scene");h(this,"camera");h(this,"renderer");h(this,"controls");h(this,"domElement");h(this,"selection");h(this,"transform");h(this,"history");h(this,"currentModel",null);h(this,"eventListeners",new Map);this.scene=t.scene,this.camera=t.camera,this.renderer=t.renderer,this.controls=t.controls,this.domElement=t.domElement,this.history=new It,this.selection=new gt(this),this.transform=new Pt(this),this.selection.on("selectionChanged",e=>{this.emit("selectionChanged",e),this.transform.attach(e)}),this.transform.on("objectChanged",(...e)=>{const i=e[0],o=e[1];this.history.execute(o),this.emit("objectChanged",i)}),this.history.on("historyChanged",()=>{this.emit("historyChanged")}),this.transform.on("modeChanged",(...e)=>{const i=e[0];this.emit("modeChanged",i)})}setModel(t){this.currentModel=t,this.selection.deselect(),this.history.clear(),this.emit("modelLoaded",t)}getModel(){return this.currentModel}getSelected(){return this.selection.getSelected()}select(t){this.selection.select(t)}execute(t){this.history.execute(t),this.emit("objectChanged",this.getSelected())}undo(){this.history.undo(),this.emit("objectChanged",this.getSelected())}redo(){this.history.redo(),this.emit("objectChanged",this.getSelected())}canUndo(){return this.history.canUndo()}canRedo(){return this.history.canRedo()}setTransformMode(t){this.transform.setMode(t)}getTransformMode(){return this.transform.getMode()}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}off(t,e){var i;(i=this.eventListeners.get(t))==null||i.delete(e)}emit(t,...e){var i;(i=this.eventListeners.get(t))==null||i.forEach(o=>o(...e))}dispose(){this.selection.dispose(),this.transform.dispose(),this.eventListeners.clear()}}function Wt(){return`node_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,8)}`}class Kt{serialize(t){const e={format:t.userData.format||"prop",lod:t.userData.lod||"auto",nodes:[]};for(const i of t.children)this.shouldSerialize(i)&&e.nodes.push(this.serializeNode(i));return e}shouldSerialize(t){return!(t.type==="TransformControlsGizmo"||t.type==="TransformControlsPlane"||t.type==="GridHelper"||t.type==="AxesHelper")}serializeNode(t){const e={id:t.userData.id||t.name||Wt(),name:t.name||"Unnamed",position:this.serializePosition(t.position),orientation:this.serializeQuaternion(t.quaternion),shape:this.serializeShape(t),children:[]};for(const i of t.children)this.shouldSerialize(i)&&e.children.push(this.serializeNode(i));return e}serializePosition(t){return{x:parseFloat(t.x.toFixed(4)),y:parseFloat(t.y.toFixed(4)),z:parseFloat(t.z.toFixed(4))}}serializeQuaternion(t){return{w:parseFloat(t.w.toFixed(6)),x:parseFloat(t.x.toFixed(6)),y:parseFloat(t.y.toFixed(6)),z:parseFloat(t.z.toFixed(6))}}serializeShape(t){const e=t.userData.shapeType||"none",i={type:e,offset:t.userData.offset||{x:0,y:0,z:0},stretch:t.userData.stretch||{x:1,y:1,z:1},settings:{size:t.userData.originalSize||{x:1,y:1,z:1},isPiece:t.userData.isPiece||!1,isStaticBox:t.userData.isStaticBox||!1},textureLayout:t.userData.textureLayout||this.getDefaultTextureLayout(),unwrapMode:t.userData.unwrapMode||"custom",visible:t.visible!==!1,doubleSided:t.userData.doubleSided||!1,shadingMode:t.userData.shadingMode||"standard"};if(t instanceof c.Mesh){const o=t.geometry;if(o instanceof c.BoxGeometry){const n=o.parameters;t.userData.originalSize||(i.settings.size={x:n.width,y:n.height,z:n.depth})}const a=t.material;a&&(i.doubleSided=a.side===c.DoubleSide,a.emissiveIntensity>.5?i.shadingMode="fullbright":a.flatShading?i.shadingMode="flat":a.metalness>.5&&(i.shadingMode="reflective"))}return e==="quad"&&t.userData.normal&&(i.settings.normal=t.userData.normal),i}getDefaultTextureLayout(){const t={offset:{x:0,y:0},mirror:{x:!1,y:!1},angle:0};return{front:{...t},back:{...t},left:{...t},right:{...t},top:{...t},bottom:{...t}}}toJSON(t){const e=this.serialize(t);return JSON.stringify(e,null,2)}download(t,e="model.blockymodel"){const i=this.toJSON(t),o=new Blob([i],{type:"application/json"}),a=URL.createObjectURL(o),n=document.createElement("a");n.href=a,n.download=e.endsWith(".blockymodel")?e:`${e}.blockymodel`,n.click(),URL.revokeObjectURL(a)}}class A extends X{constructor(e,i,o,a){super(e,!0);h(this,"type","SetProperty");h(this,"updatable",!0);h(this,"propertyPath");h(this,"newValue");h(this,"oldValue");this.propertyPath=i,this.newValue=this.cloneValue(o),this.oldValue=this.cloneValue(a)}cloneValue(e){return e==null?e:typeof e=="object"?JSON.parse(JSON.stringify(e)):e}getProperty(e,i){const o=i.split(".");let a=e;for(const n of o){if(a==null)return;a=a[n]}return a}setProperty(e,i,o){const a=i.split(".");let n=e;for(let l=0;l<a.length-1;l++)n[a[l]]===void 0&&(n[a[l]]={}),n=n[a[l]];n[a[a.length-1]]=o}execute(){this.setProperty(this.object,this.propertyPath,this.cloneValue(this.newValue))}undo(){this.setProperty(this.object,this.propertyPath,this.cloneValue(this.oldValue))}update(e){e instanceof A&&e.propertyPath===this.propertyPath&&(this.newValue=e.newValue)}getPropertyPath(){return this.propertyPath}getNewValue(){return this.cloneValue(this.newValue)}getOldValue(){return this.cloneValue(this.oldValue)}}class it extends X{constructor(e,i,o){super(e,!1);h(this,"type","AddNode");h(this,"updatable",!1);h(this,"parent");h(this,"child");h(this,"index");this.parent=e,this.child=i,this.index=o??e.children.length}execute(){if(this.parent.add(this.child),this.index<this.parent.children.length-1){const e=this.parent.children;e.splice(e.indexOf(this.child),1),e.splice(this.index,0,this.child)}}undo(){this.parent.remove(this.child)}getChild(){return this.child}getParent(){return this.parent}}class Dt extends X{constructor(e){super(e,!1);h(this,"type","RemoveNode");h(this,"updatable",!1);h(this,"parent");h(this,"child");h(this,"index");if(!e.parent)throw new Error("Cannot remove node without parent");this.parent=e.parent,this.child=e,this.index=this.parent.children.indexOf(e)}execute(){this.parent.remove(this.child)}undo(){if(this.parent.add(this.child),this.index<this.parent.children.length){const e=this.parent.children;e.splice(e.indexOf(this.child),1),e.splice(this.index,0,this.child)}}getChild(){return this.child}getParent(){return this.parent}getIndex(){return this.index}}class $t{constructor(t,e){h(this,"editor");h(this,"container");h(this,"currentObject",null);h(this,"isUpdating",!1);h(this,"nameInput");h(this,"posInputs");h(this,"rotInputs");h(this,"scaleInputs");h(this,"sizeInputs");h(this,"offsetInputs");h(this,"visibleCheckbox");h(this,"doubleSidedCheckbox");h(this,"shadingModeSelect");h(this,"shapeTypeSpan");this.editor=t;const i=document.getElementById(e);if(!i)throw new Error(`Property panel container not found: ${e}`);this.container=i,this.buildUI(),this.setupEventListeners()}buildUI(){this.container.innerHTML=`
2
+ <div class="property-section" id="properties-transform">
3
+ <div class="section-header">Transform</div>
4
+ <div class="property-row">
5
+ <label>Name</label>
6
+ <input type="text" id="prop-name" class="prop-input prop-text" />
7
+ </div>
8
+ <div class="property-row">
9
+ <label>Position</label>
10
+ <div class="vec3-inputs">
11
+ <input type="number" id="prop-pos-x" class="prop-input" step="0.1" />
12
+ <input type="number" id="prop-pos-y" class="prop-input" step="0.1" />
13
+ <input type="number" id="prop-pos-z" class="prop-input" step="0.1" />
14
+ </div>
15
+ </div>
16
+ <div class="property-row">
17
+ <label>Rotation</label>
18
+ <div class="vec3-inputs">
19
+ <input type="number" id="prop-rot-x" class="prop-input" step="1" />
20
+ <input type="number" id="prop-rot-y" class="prop-input" step="1" />
21
+ <input type="number" id="prop-rot-z" class="prop-input" step="1" />
22
+ </div>
23
+ </div>
24
+ <div class="property-row">
25
+ <label>Scale</label>
26
+ <div class="vec3-inputs">
27
+ <input type="number" id="prop-scale-x" class="prop-input" step="0.1" min="0.01" />
28
+ <input type="number" id="prop-scale-y" class="prop-input" step="0.1" min="0.01" />
29
+ <input type="number" id="prop-scale-z" class="prop-input" step="0.1" min="0.01" />
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="property-section" id="properties-shape">
35
+ <div class="section-header">Shape</div>
36
+ <div class="property-row">
37
+ <label>Type</label>
38
+ <span id="prop-shape-type" class="prop-readonly">-</span>
39
+ </div>
40
+ <div class="property-row">
41
+ <label>Size</label>
42
+ <div class="vec3-inputs">
43
+ <input type="number" id="prop-size-x" class="prop-input" step="1" min="0" />
44
+ <input type="number" id="prop-size-y" class="prop-input" step="1" min="0" />
45
+ <input type="number" id="prop-size-z" class="prop-input" step="1" min="0" />
46
+ </div>
47
+ </div>
48
+ <div class="property-row">
49
+ <label>Offset</label>
50
+ <div class="vec3-inputs">
51
+ <input type="number" id="prop-offset-x" class="prop-input" step="0.5" />
52
+ <input type="number" id="prop-offset-y" class="prop-input" step="0.5" />
53
+ <input type="number" id="prop-offset-z" class="prop-input" step="0.5" />
54
+ </div>
55
+ </div>
56
+ <div class="property-row">
57
+ <label>Visible</label>
58
+ <input type="checkbox" id="prop-visible" class="prop-checkbox" />
59
+ </div>
60
+ <div class="property-row">
61
+ <label>Double Sided</label>
62
+ <input type="checkbox" id="prop-doublesided" class="prop-checkbox" />
63
+ </div>
64
+ <div class="property-row">
65
+ <label>Shading</label>
66
+ <select id="prop-shading" class="prop-select">
67
+ <option value="standard">Standard</option>
68
+ <option value="flat">Flat</option>
69
+ <option value="fullbright">Fullbright</option>
70
+ <option value="reflective">Reflective</option>
71
+ </select>
72
+ </div>
73
+ </div>
74
+
75
+ <div class="property-empty" id="properties-empty">
76
+ <p>Select an object to view properties</p>
77
+ </div>
78
+ `,this.nameInput=document.getElementById("prop-name"),this.posInputs={x:document.getElementById("prop-pos-x"),y:document.getElementById("prop-pos-y"),z:document.getElementById("prop-pos-z")},this.rotInputs={x:document.getElementById("prop-rot-x"),y:document.getElementById("prop-rot-y"),z:document.getElementById("prop-rot-z")},this.scaleInputs={x:document.getElementById("prop-scale-x"),y:document.getElementById("prop-scale-y"),z:document.getElementById("prop-scale-z")},this.sizeInputs={x:document.getElementById("prop-size-x"),y:document.getElementById("prop-size-y"),z:document.getElementById("prop-size-z")},this.offsetInputs={x:document.getElementById("prop-offset-x"),y:document.getElementById("prop-offset-y"),z:document.getElementById("prop-offset-z")},this.visibleCheckbox=document.getElementById("prop-visible"),this.doubleSidedCheckbox=document.getElementById("prop-doublesided"),this.shadingModeSelect=document.getElementById("prop-shading"),this.shapeTypeSpan=document.getElementById("prop-shape-type"),this.showEmpty()}setupEventListeners(){this.editor.on("selectionChanged",t=>{this.setObject(t)}),this.editor.on("objectChanged",()=>{this.currentObject&&this.updateFromObject()}),this.editor.transform.on("objectChanging",()=>{this.currentObject&&this.updateFromObject()}),this.nameInput.addEventListener("change",()=>{if(this.currentObject&&!this.isUpdating){const t=this.currentObject.name,e=this.nameInput.value;this.editor.execute(new A(this.currentObject,"name",e,t))}}),this.setupVec3Input(this.posInputs,t=>{if(this.currentObject&&!this.isUpdating){const e=this.currentObject.position.clone();this.editor.execute(new K(this.currentObject,t,e))}}),this.setupVec3Input(this.rotInputs,t=>{if(this.currentObject&&!this.isUpdating){const e=this.currentObject.rotation.clone(),i=new c.Euler(c.MathUtils.degToRad(t.x),c.MathUtils.degToRad(t.y),c.MathUtils.degToRad(t.z));this.editor.execute(new $(this.currentObject,i,e))}}),this.setupVec3Input(this.scaleInputs,t=>{if(this.currentObject&&!this.isUpdating){const e=this.currentObject.scale.clone();this.editor.execute(new J(this.currentObject,t,e))}}),this.setupVec3Input(this.sizeInputs,t=>{if(this.currentObject&&!this.isUpdating){const e=this.currentObject.userData.originalSize||{x:1,y:1,z:1};this.editor.execute(new A(this.currentObject,"userData.originalSize",{x:t.x,y:t.y,z:t.z},e)),this.rebuildGeometry()}}),this.setupVec3Input(this.offsetInputs,t=>{if(this.currentObject&&!this.isUpdating){const e=this.currentObject.userData.offset||{x:0,y:0,z:0};this.editor.execute(new A(this.currentObject,"userData.offset",{x:t.x,y:t.y,z:t.z},e)),this.rebuildGeometry()}}),this.visibleCheckbox.addEventListener("change",()=>{if(this.currentObject&&!this.isUpdating){const t=this.currentObject.visible,e=this.visibleCheckbox.checked;this.editor.execute(new A(this.currentObject,"visible",e,t))}}),this.doubleSidedCheckbox.addEventListener("change",()=>{if(this.currentObject&&!this.isUpdating&&this.currentObject instanceof c.Mesh){const t=this.currentObject.material,e=t.side===c.DoubleSide,i=this.doubleSidedCheckbox.checked;t.side=i?c.DoubleSide:c.FrontSide,this.currentObject.userData.doubleSided=i,this.editor.execute(new A(this.currentObject,"userData.doubleSided",i,e))}}),this.shadingModeSelect.addEventListener("change",()=>{if(this.currentObject&&!this.isUpdating){const t=this.currentObject.userData.shadingMode||"standard",e=this.shadingModeSelect.value;this.currentObject.userData.shadingMode=e,this.editor.execute(new A(this.currentObject,"userData.shadingMode",e,t))}})}setupVec3Input(t,e){const i=()=>{const o=new c.Vector3(parseFloat(t.x.value)||0,parseFloat(t.y.value)||0,parseFloat(t.z.value)||0);e(o)};t.x.addEventListener("change",i),t.y.addEventListener("change",i),t.z.addEventListener("change",i)}setObject(t){this.currentObject=t,t?(this.showProperties(),this.updateFromObject()):this.showEmpty()}updateFromObject(){var a,n,l,d,u,y;if(!this.currentObject)return;this.isUpdating=!0;const t=this.currentObject;this.nameInput.value=t.name||"",this.posInputs.x.value=t.position.x.toFixed(2),this.posInputs.y.value=t.position.y.toFixed(2),this.posInputs.z.value=t.position.z.toFixed(2),this.rotInputs.x.value=c.MathUtils.radToDeg(t.rotation.x).toFixed(1),this.rotInputs.y.value=c.MathUtils.radToDeg(t.rotation.y).toFixed(1),this.rotInputs.z.value=c.MathUtils.radToDeg(t.rotation.z).toFixed(1),this.scaleInputs.x.value=t.scale.x.toFixed(2),this.scaleInputs.y.value=t.scale.y.toFixed(2),this.scaleInputs.z.value=t.scale.z.toFixed(2);const e=t.userData.shapeType||"none";this.shapeTypeSpan.textContent=e;const i=t.userData.originalSize||{x:1,y:1,z:1};this.sizeInputs.x.value=((a=i.x)==null?void 0:a.toString())||"1",this.sizeInputs.y.value=((n=i.y)==null?void 0:n.toString())||"1",this.sizeInputs.z.value=((l=i.z)==null?void 0:l.toString())||"1";const o=t.userData.offset||{x:0,y:0,z:0};if(this.offsetInputs.x.value=((d=o.x)==null?void 0:d.toString())||"0",this.offsetInputs.y.value=((u=o.y)==null?void 0:u.toString())||"0",this.offsetInputs.z.value=((y=o.z)==null?void 0:y.toString())||"0",this.visibleCheckbox.checked=t.visible,t instanceof c.Mesh){const x=t.material;this.doubleSidedCheckbox.checked=x.side===c.DoubleSide}else this.doubleSidedCheckbox.checked=!1;this.shadingModeSelect.value=t.userData.shadingMode||"standard",this.isUpdating=!1}rebuildGeometry(){if(!this.currentObject||!(this.currentObject instanceof c.Mesh))return;const t=this.currentObject,e=t.userData.originalSize||{x:1,y:1,z:1},i=t.userData.offset||{x:0,y:0,z:0},o=t.userData.stretch||{x:1,y:1,z:1},a={x:e.x*o.x,y:e.y*o.y,z:e.z*o.z};t.geometry.dispose(),t.userData.shapeType==="box"&&(t.geometry=new c.BoxGeometry(a.x,a.y,a.z),t.geometry.translate(i.x,i.y,i.z))}showProperties(){const t=document.getElementById("properties-transform"),e=document.getElementById("properties-shape"),i=document.getElementById("properties-empty");t&&(t.style.display="block"),e&&(e.style.display="block"),i&&(i.style.display="none")}showEmpty(){const t=document.getElementById("properties-transform"),e=document.getElementById("properties-shape"),i=document.getElementById("properties-empty");t&&(t.style.display="none"),e&&(e.style.display="none"),i&&(i.style.display="block")}dispose(){this.container.innerHTML=""}}class Jt{constructor(t,e){h(this,"editor");h(this,"container");h(this,"treeContainer");h(this,"contextMenu",null);h(this,"contextTarget",null);this.editor=t;const i=document.getElementById(e);if(!i)throw new Error(`Hierarchy panel container not found: ${e}`);this.container=i,this.buildUI(),this.setupEventListeners()}buildUI(){this.container.innerHTML=`
79
+ <div class="hierarchy-tree" id="hierarchy-tree"></div>
80
+ `,this.treeContainer=document.getElementById("hierarchy-tree"),this.contextMenu=document.createElement("div"),this.contextMenu.className="context-menu",this.contextMenu.innerHTML=`
81
+ <div class="context-menu-item" data-action="add-box">Add Child Box</div>
82
+ <div class="context-menu-item" data-action="add-group">Add Child Group</div>
83
+ <div class="context-menu-separator"></div>
84
+ <div class="context-menu-item" data-action="duplicate">Duplicate</div>
85
+ <div class="context-menu-separator"></div>
86
+ <div class="context-menu-item context-menu-danger" data-action="delete">Delete</div>
87
+ `,this.contextMenu.style.display="none",document.body.appendChild(this.contextMenu)}setupEventListeners(){var t;this.editor.on("modelLoaded",()=>{this.refresh()}),this.editor.on("selectionChanged",()=>{this.updateSelection()}),this.editor.on("objectChanged",()=>{this.refresh()}),(t=this.contextMenu)==null||t.addEventListener("click",e=>{const o=e.target.dataset.action;o&&this.contextTarget&&this.handleContextAction(o,this.contextTarget),this.hideContextMenu()}),document.addEventListener("click",e=>{this.contextMenu&&!this.contextMenu.contains(e.target)&&this.hideContextMenu()}),document.addEventListener("keydown",e=>{if(e.key==="Delete"||e.key==="Backspace"){const i=this.editor.getSelected();i&&i.parent&&!(e.target instanceof HTMLInputElement)&&this.deleteNode(i)}})}refresh(){const t=this.editor.getModel();if(!t){this.treeContainer.innerHTML='<p class="hierarchy-empty">No model loaded</p>';return}this.treeContainer.innerHTML="",this.buildTree(t,this.treeContainer,0)}buildTree(t,e,i){const o=document.createElement("div");o.className="hierarchy-item",o.dataset.objectId=t.uuid;const a=document.createElement("span");a.className="hierarchy-indent",a.style.width=`${i*16}px`;const n=document.createElement("span");n.className="hierarchy-expander",t.children.length>0&&(n.textContent="▼",n.addEventListener("click",u=>{u.stopPropagation(),this.toggleExpand(o)}));const l=document.createElement("span");l.className="hierarchy-icon",l.textContent=this.getIcon(t);const d=document.createElement("span");if(d.className="hierarchy-label",d.textContent=t.name||`(${t.type})`,o.appendChild(a),o.appendChild(n),o.appendChild(l),o.appendChild(d),o.addEventListener("click",()=>{this.editor.select(t)}),o.addEventListener("contextmenu",u=>{u.preventDefault(),this.showContextMenu(u,t)}),e.appendChild(o),t.children.length>0){const u=document.createElement("div");u.className="hierarchy-children";for(const y of t.children)y.type==="TransformControlsGizmo"||y.type==="TransformControlsPlane"||this.buildTree(y,u,i+1);e.appendChild(u)}}getIcon(t){if(t instanceof c.Mesh){const e=t.userData.shapeType;return e==="box"?"📦":e==="quad"?"▫️":"🔷"}return t instanceof c.Group?"📁":"◯"}toggleExpand(t){const e=t.nextElementSibling;if(e!=null&&e.classList.contains("hierarchy-children")){const i=e.classList.toggle("collapsed"),o=t.querySelector(".hierarchy-expander");o&&(o.textContent=i?"▶":"▼")}}updateSelection(){this.treeContainer.querySelectorAll(".hierarchy-item.selected").forEach(e=>{e.classList.remove("selected")});const t=this.editor.getSelected();if(t){const e=this.treeContainer.querySelector(`[data-object-id="${t.uuid}"]`);e&&(e.classList.add("selected"),e.scrollIntoView({behavior:"smooth",block:"nearest"}))}}showContextMenu(t,e){if(!this.contextMenu)return;this.contextTarget=e,this.contextMenu.style.display="block",this.contextMenu.style.left=`${t.clientX}px`,this.contextMenu.style.top=`${t.clientY}px`;const i=this.contextMenu.getBoundingClientRect();i.right>window.innerWidth&&(this.contextMenu.style.left=`${window.innerWidth-i.width-10}px`),i.bottom>window.innerHeight&&(this.contextMenu.style.top=`${window.innerHeight-i.height-10}px`)}hideContextMenu(){this.contextMenu&&(this.contextMenu.style.display="none"),this.contextTarget=null}handleContextAction(t,e){switch(t){case"add-box":this.addChildBox(e);break;case"add-group":this.addChildGroup(e);break;case"duplicate":this.duplicateNode(e);break;case"delete":this.deleteNode(e);break}}addChildBox(t){const e=new c.BoxGeometry(10,10,10),i=new c.MeshStandardMaterial({color:8947848,roughness:.7}),o=new c.Mesh(e,i);o.name=`Box_${Date.now().toString(36)}`,o.userData.id=o.name,o.userData.shapeType="box",o.userData.originalSize={x:10,y:10,z:10},this.editor.execute(new it(t,o)),this.editor.select(o)}addChildGroup(t){const e=new c.Group;e.name=`Group_${Date.now().toString(36)}`,e.userData.id=e.name,e.userData.shapeType="none",this.editor.execute(new it(t,e)),this.editor.select(e)}duplicateNode(t){if(!t.parent)return;const e=t.clone(!0);e.name=`${t.name}_copy`,e.userData.id=e.name,e.position.x+=10,this.editor.execute(new it(t.parent,e)),this.editor.select(e)}deleteNode(t){if(!t.parent)return;const e=this.editor.getModel();t!==e&&(this.editor.execute(new Dt(t)),this.editor.select(null))}dispose(){this.contextMenu&&document.body.removeChild(this.contextMenu),this.container.innerHTML=""}}const E=["front","back","left","right","top","bottom"],Et={front:"Front (+Z)",back:"Back (-Z)",left:"Left (-X)",right:"Right (+X)",top:"Top (+Y)",bottom:"Bottom (-Y)"},pt={offset:{x:0,y:0},mirror:{x:!1,y:!1},angle:0};class Rt{constructor(t,e){h(this,"editor");h(this,"container");h(this,"currentObject",null);h(this,"isUpdating",!1);h(this,"faceInputs",new Map);this.editor=t;const i=document.getElementById(e);if(!i)throw new Error(`UV Editor container not found: ${e}`);this.container=i,this.buildUI(),this.setupEventListeners()}buildUI(){let t="";for(const e of E)t+=`
88
+ <div class="uv-face">
89
+ <div class="uv-face-header">${Et[e]}</div>
90
+ <div class="uv-face-row">
91
+ <label>Offset</label>
92
+ <input type="number" id="uv-${e}-offset-x" class="uv-input" step="1" placeholder="X" />
93
+ <input type="number" id="uv-${e}-offset-y" class="uv-input" step="1" placeholder="Y" />
94
+ </div>
95
+ <div class="uv-face-row">
96
+ <label>Mirror</label>
97
+ <label class="uv-checkbox-label">
98
+ <input type="checkbox" id="uv-${e}-mirror-x" class="uv-checkbox" /> X
99
+ </label>
100
+ <label class="uv-checkbox-label">
101
+ <input type="checkbox" id="uv-${e}-mirror-y" class="uv-checkbox" /> Y
102
+ </label>
103
+ </div>
104
+ <div class="uv-face-row">
105
+ <label>Rotation</label>
106
+ <select id="uv-${e}-angle" class="uv-select">
107
+ <option value="0">0°</option>
108
+ <option value="90">90°</option>
109
+ <option value="180">180°</option>
110
+ <option value="270">270°</option>
111
+ </select>
112
+ </div>
113
+ </div>
114
+ `;this.container.innerHTML=`
115
+ <div class="uv-editor-content" id="uv-editor-content">
116
+ ${t}
117
+ </div>
118
+ <div class="uv-editor-empty" id="uv-editor-empty">
119
+ <p>Select a box to edit UVs</p>
120
+ </div>
121
+ `;for(const e of E)this.faceInputs.set(e,{offsetX:document.getElementById(`uv-${e}-offset-x`),offsetY:document.getElementById(`uv-${e}-offset-y`),mirrorX:document.getElementById(`uv-${e}-mirror-x`),mirrorY:document.getElementById(`uv-${e}-mirror-y`),angle:document.getElementById(`uv-${e}-angle`)});this.showEmpty()}setupEventListeners(){this.editor.on("selectionChanged",t=>{this.setObject(t)}),this.editor.on("objectChanged",()=>{this.currentObject&&this.updateFromObject()});for(const t of E){const e=this.faceInputs.get(t);e.offsetX.addEventListener("change",()=>{this.handleFaceChange(t)}),e.offsetY.addEventListener("change",()=>{this.handleFaceChange(t)}),e.mirrorX.addEventListener("change",()=>{this.handleFaceChange(t)}),e.mirrorY.addEventListener("change",()=>{this.handleFaceChange(t)}),e.angle.addEventListener("change",()=>{this.handleFaceChange(t)})}}handleFaceChange(t){if(!this.currentObject||this.isUpdating)return;const e=this.faceInputs.get(t),i=this.getTextureLayout();i[t]||{...pt};const o={offset:{x:parseInt(e.offsetX.value)||0,y:parseInt(e.offsetY.value)||0},mirror:{x:e.mirrorX.checked,y:e.mirrorY.checked},angle:parseInt(e.angle.value)},a={...i,[t]:o};this.editor.execute(new A(this.currentObject,"userData.textureLayout",a,i)),this.applyTextureLayout(a)}getTextureLayout(){var t;return((t=this.currentObject)==null?void 0:t.userData.textureLayout)||{}}setObject(t){t&&t instanceof c.Mesh&&t.userData.shapeType==="box"?(this.currentObject=t,this.showContent(),this.updateFromObject()):(this.currentObject=null,this.showEmpty())}updateFromObject(){var e,i,o,a,n,l,d;if(!this.currentObject)return;this.isUpdating=!0;const t=this.getTextureLayout();for(const u of E){const y=this.faceInputs.get(u),x=t[u]||pt;y.offsetX.value=((i=(e=x.offset)==null?void 0:e.x)==null?void 0:i.toString())||"0",y.offsetY.value=((a=(o=x.offset)==null?void 0:o.y)==null?void 0:a.toString())||"0",y.mirrorX.checked=((n=x.mirror)==null?void 0:n.x)||!1,y.mirrorY.checked=((l=x.mirror)==null?void 0:l.y)||!1,y.angle.value=((d=x.angle)==null?void 0:d.toString())||"0"}this.isUpdating=!1}applyTextureLayout(t){var l,d,u,y;if(!this.currentObject||!(this.currentObject instanceof c.Mesh))return;const o=this.currentObject.geometry.getAttribute("uv");if(!o)return;const a={right:0,left:1,top:2,bottom:3,front:4,back:5},n=o.array;for(const x of E){const D=t[x]||pt,Z=a[x]*6,L=(((l=D.offset)==null?void 0:l.x)||0)/64,O=(((d=D.offset)==null?void 0:d.y)||0)/64;for(let S=0;S<6;S++){const v=(Z+S)*2;let w=n[v],I=n[v+1];if((u=D.mirror)!=null&&u.x&&(w=1-w),(y=D.mirror)!=null&&y.y&&(I=1-I),D.angle){const z=D.angle*Math.PI/180,Y=w-.5,nt=I-.5;w=Y*Math.cos(z)-nt*Math.sin(z)+.5,I=Y*Math.sin(z)+nt*Math.cos(z)+.5}n[v]=w+L,n[v+1]=I+O}}o.needsUpdate=!0}showContent(){const t=document.getElementById("uv-editor-content"),e=document.getElementById("uv-editor-empty");t&&(t.style.display="block"),e&&(e.style.display="none")}showEmpty(){const t=document.getElementById("uv-editor-content"),e=document.getElementById("uv-editor-empty");t&&(t.style.display="none"),e&&(e.style.display="block")}dispose(){this.container.innerHTML="",this.faceInputs.clear()}}const st={x:0,y:0,z:0},Ct={w:1,x:0,y:0,z:0},ut={x:1,y:1,z:1};class Lt extends c.Loader{constructor(t){super(t)}async load(t){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load model: ${e.statusText}`);const i=await e.json();return this.parse(i)}async loadFromFile(t){const e=await t.text(),i=JSON.parse(e);return this.parse(i)}parse(t){const e=new c.Group;e.name="BlockyModel",e.userData.format=t.format,e.userData.lod=t.lod;for(const i of t.nodes){const o=this.parseNode(i);e.add(o)}return e}parseNode(t){var a,n;const e=this.createNodeObject(t);e.name=t.name,e.userData.id=t.id,e.userData.isPiece=((n=(a=t.shape)==null?void 0:a.settings)==null?void 0:n.isPiece)??!1;const i=t.position??st;e.position.set(i.x,i.y,i.z);const o=t.orientation??Ct;e.quaternion.set(o.x,o.y,o.z,o.w);for(const l of t.children??[]){const d=this.parseNode(l);e.add(d)}return e}createNodeObject(t){const e=t.shape;if(!e||e.type==="none"||!e.visible){const i=new c.Group;return i.userData.shapeType=(e==null?void 0:e.type)??"none",i}return e.type==="box"?this.createBox(e):e.type==="quad"?this.createQuad(e):new c.Group}createBox(t){const e=t.settings.size??{x:1,y:1,z:1},i=t.stretch??ut,o=t.offset??st,a={x:e.x*i.x,y:e.y*i.y,z:e.z*i.z},n=new c.BoxGeometry(a.x,a.y,a.z);n.translate(o.x,o.y,o.z);const l=this.createMaterial(t),d=new c.Mesh(n,l);return d.userData.shapeType="box",d.userData.originalSize=e,d.userData.shadingMode=t.shadingMode,t.doubleSided&&(l.side=c.DoubleSide),d}createQuad(t){const e=t.settings.size??{x:1,y:1,z:0},i=t.stretch??ut,o=t.offset??st,a=t.settings.normal??"+Z";let n,l;switch(a){case"+X":case"-X":n=e.z*i.z,l=e.y*i.y;break;case"+Y":case"-Y":n=e.x*i.x,l=e.z*i.z;break;case"+Z":case"-Z":default:n=e.x*i.x,l=e.y*i.y;break}const d=new c.PlaneGeometry(n,l);switch(a){case"+X":d.rotateY(Math.PI/2);break;case"-X":d.rotateY(-Math.PI/2);break;case"+Y":d.rotateX(-Math.PI/2);break;case"-Y":d.rotateX(Math.PI/2);break;case"-Z":d.rotateY(Math.PI);break}d.translate(o.x,o.y,o.z);const u=this.createMaterial(t);u.side=t.doubleSided?c.DoubleSide:c.FrontSide;const y=new c.Mesh(d,u);return y.userData.shapeType="quad",y.userData.shadingMode=t.shadingMode,y}createMaterial(t){switch(t.shadingMode){case"fullbright":return new c.MeshStandardMaterial({color:8947848,emissive:8947848,emissiveIntensity:1,roughness:1,metalness:0});case"flat":return new c.MeshStandardMaterial({color:8947848,flatShading:!0,roughness:.9,metalness:0});case"reflective":return new c.MeshStandardMaterial({color:8947848,roughness:.1,metalness:.8});case"standard":default:return new c.MeshStandardMaterial({color:8947848,roughness:.7,metalness:0})}}}function Ht(r,t){t.magFilter=c.NearestFilter,t.minFilter=c.NearestFilter,t.colorSpace=c.SRGBColorSpace,r.traverse(e=>{if(e instanceof c.Mesh){const i=e.material;i.isMeshStandardMaterial&&(i.map=t,i.color.setHex(16777215),i.needsUpdate=!0)}})}const Ot={type:"change"},mt={type:"start"},zt={type:"end"},ot=new s.Ray,kt=new s.Plane,te=Math.cos(70*s.MathUtils.DEG2RAD),b=new s.Vector3,M=2*Math.PI,m={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},ft=1e-6;class ee extends s.Controls{constructor(t,e=null){super(t,e),this.state=m.NONE,this.enabled=!0,this.target=new s.Vector3,this.cursor=new s.Vector3,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minTargetRadius=0,this.maxTargetRadius=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:s.MOUSE.ROTATE,MIDDLE:s.MOUSE.DOLLY,RIGHT:s.MOUSE.PAN},this.touches={ONE:s.TOUCH.ROTATE,TWO:s.TOUCH.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this._lastPosition=new s.Vector3,this._lastQuaternion=new s.Quaternion,this._lastTargetPosition=new s.Vector3,this._quat=new s.Quaternion().setFromUnitVectors(t.up,new s.Vector3(0,1,0)),this._quatInverse=this._quat.clone().invert(),this._spherical=new s.Spherical,this._sphericalDelta=new s.Spherical,this._scale=1,this._panOffset=new s.Vector3,this._rotateStart=new s.Vector2,this._rotateEnd=new s.Vector2,this._rotateDelta=new s.Vector2,this._panStart=new s.Vector2,this._panEnd=new s.Vector2,this._panDelta=new s.Vector2,this._dollyStart=new s.Vector2,this._dollyEnd=new s.Vector2,this._dollyDelta=new s.Vector2,this._dollyDirection=new s.Vector3,this._mouse=new s.Vector2,this._performCursorZoom=!1,this._pointers=[],this._pointerPositions={},this._controlActive=!1,this._onPointerMove=se.bind(this),this._onPointerDown=ie.bind(this),this._onPointerUp=oe.bind(this),this._onContextMenu=de.bind(this),this._onMouseWheel=re.bind(this),this._onKeyDown=he.bind(this),this._onTouchStart=le.bind(this),this._onTouchMove=ce.bind(this),this._onMouseDown=ne.bind(this),this._onMouseMove=ae.bind(this),this._interceptControlDown=pe.bind(this),this._interceptControlUp=ue.bind(this),this.domElement!==null&&this.connect(),this.update()}connect(){this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointercancel",this._onPointerUp),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("wheel",this._onMouseWheel,{passive:!1}),this.domElement.getRootNode().addEventListener("keydown",this._interceptControlDown,{passive:!0,capture:!0}),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointercancel",this._onPointerUp),this.domElement.removeEventListener("wheel",this._onMouseWheel),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.stopListenToKeyEvents(),this.domElement.getRootNode().removeEventListener("keydown",this._interceptControlDown,{capture:!0}),this.domElement.style.touchAction="auto"}dispose(){this.disconnect()}getPolarAngle(){return this._spherical.phi}getAzimuthalAngle(){return this._spherical.theta}getDistance(){return this.object.position.distanceTo(this.target)}listenToKeyEvents(t){t.addEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=t}stopListenToKeyEvents(){this._domElementKeyEvents!==null&&(this._domElementKeyEvents.removeEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=null)}saveState(){this.target0.copy(this.target),this.position0.copy(this.object.position),this.zoom0=this.object.zoom}reset(){this.target.copy(this.target0),this.object.position.copy(this.position0),this.object.zoom=this.zoom0,this.object.updateProjectionMatrix(),this.dispatchEvent(Ot),this.update(),this.state=m.NONE}update(t=null){const e=this.object.position;b.copy(e).sub(this.target),b.applyQuaternion(this._quat),this._spherical.setFromVector3(b),this.autoRotate&&this.state===m.NONE&&this._rotateLeft(this._getAutoRotationAngle(t)),this.enableDamping?(this._spherical.theta+=this._sphericalDelta.theta*this.dampingFactor,this._spherical.phi+=this._sphericalDelta.phi*this.dampingFactor):(this._spherical.theta+=this._sphericalDelta.theta,this._spherical.phi+=this._sphericalDelta.phi);let i=this.minAzimuthAngle,o=this.maxAzimuthAngle;isFinite(i)&&isFinite(o)&&(i<-Math.PI?i+=M:i>Math.PI&&(i-=M),o<-Math.PI?o+=M:o>Math.PI&&(o-=M),i<=o?this._spherical.theta=Math.max(i,Math.min(o,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(i+o)/2?Math.max(i,this._spherical.theta):Math.min(o,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let a=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const n=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),a=n!=this._spherical.radius}if(b.setFromSpherical(this._spherical),b.applyQuaternion(this._quatInverse),e.copy(this.target).add(b),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let n=null;if(this.object.isPerspectiveCamera){const l=b.length();n=this._clampDistance(l*this._scale);const d=l-n;this.object.position.addScaledVector(this._dollyDirection,d),this.object.updateMatrixWorld(),a=!!d}else if(this.object.isOrthographicCamera){const l=new s.Vector3(this._mouse.x,this._mouse.y,0);l.unproject(this.object);const d=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),a=d!==this.object.zoom;const u=new s.Vector3(this._mouse.x,this._mouse.y,0);u.unproject(this.object),this.object.position.sub(u).add(l),this.object.updateMatrixWorld(),n=b.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;n!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(n).add(this.object.position):(ot.origin.copy(this.object.position),ot.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(ot.direction))<te?this.object.lookAt(this.target):(kt.setFromNormalAndCoplanarPoint(this.object.up,this.target),ot.intersectPlane(kt,this.target))))}else if(this.object.isOrthographicCamera){const n=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),n!==this.object.zoom&&(this.object.updateProjectionMatrix(),a=!0)}return this._scale=1,this._performCursorZoom=!1,a||this._lastPosition.distanceToSquared(this.object.position)>ft||8*(1-this._lastQuaternion.dot(this.object.quaternion))>ft||this._lastTargetPosition.distanceToSquared(this.target)>ft?(this.dispatchEvent(Ot),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(t){return t!==null?M/60*this.autoRotateSpeed*t:M/60/60*this.autoRotateSpeed}_getZoomScale(t){const e=Math.abs(t*.01);return Math.pow(.95,this.zoomSpeed*e)}_rotateLeft(t){this._sphericalDelta.theta-=t}_rotateUp(t){this._sphericalDelta.phi-=t}_panLeft(t,e){b.setFromMatrixColumn(e,0),b.multiplyScalar(-t),this._panOffset.add(b)}_panUp(t,e){this.screenSpacePanning===!0?b.setFromMatrixColumn(e,1):(b.setFromMatrixColumn(e,0),b.crossVectors(this.object.up,b)),b.multiplyScalar(t),this._panOffset.add(b)}_pan(t,e){const i=this.domElement;if(this.object.isPerspectiveCamera){const o=this.object.position;b.copy(o).sub(this.target);let a=b.length();a*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*t*a/i.clientHeight,this.object.matrix),this._panUp(2*e*a/i.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(t*(this.object.right-this.object.left)/this.object.zoom/i.clientWidth,this.object.matrix),this._panUp(e*(this.object.top-this.object.bottom)/this.object.zoom/i.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(t,e){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const i=this.domElement.getBoundingClientRect(),o=t-i.left,a=e-i.top,n=i.width,l=i.height;this._mouse.x=o/n*2-1,this._mouse.y=-(a/l)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(t){return Math.max(this.minDistance,Math.min(this.maxDistance,t))}_handleMouseDownRotate(t){this._rotateStart.set(t.clientX,t.clientY)}_handleMouseDownDolly(t){this._updateZoomParameters(t.clientX,t.clientX),this._dollyStart.set(t.clientX,t.clientY)}_handleMouseDownPan(t){this._panStart.set(t.clientX,t.clientY)}_handleMouseMoveRotate(t){this._rotateEnd.set(t.clientX,t.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(M*this._rotateDelta.x/e.clientHeight),this._rotateUp(M*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(t){this._dollyEnd.set(t.clientX,t.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(t){this._panEnd.set(t.clientX,t.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(t){this._updateZoomParameters(t.clientX,t.clientY),t.deltaY<0?this._dollyIn(this._getZoomScale(t.deltaY)):t.deltaY>0&&this._dollyOut(this._getZoomScale(t.deltaY)),this.update()}_handleKeyDown(t){let e=!1;switch(t.code){case this.keys.UP:t.ctrlKey||t.metaKey||t.shiftKey?this._rotateUp(M*this.rotateSpeed/this.domElement.clientHeight):this._pan(0,this.keyPanSpeed),e=!0;break;case this.keys.BOTTOM:t.ctrlKey||t.metaKey||t.shiftKey?this._rotateUp(-M*this.rotateSpeed/this.domElement.clientHeight):this._pan(0,-this.keyPanSpeed),e=!0;break;case this.keys.LEFT:t.ctrlKey||t.metaKey||t.shiftKey?this._rotateLeft(M*this.rotateSpeed/this.domElement.clientHeight):this._pan(this.keyPanSpeed,0),e=!0;break;case this.keys.RIGHT:t.ctrlKey||t.metaKey||t.shiftKey?this._rotateLeft(-M*this.rotateSpeed/this.domElement.clientHeight):this._pan(-this.keyPanSpeed,0),e=!0;break}e&&(t.preventDefault(),this.update())}_handleTouchStartRotate(t){if(this._pointers.length===1)this._rotateStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),i=.5*(t.pageX+e.x),o=.5*(t.pageY+e.y);this._rotateStart.set(i,o)}}_handleTouchStartPan(t){if(this._pointers.length===1)this._panStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),i=.5*(t.pageX+e.x),o=.5*(t.pageY+e.y);this._panStart.set(i,o)}}_handleTouchStartDolly(t){const e=this._getSecondPointerPosition(t),i=t.pageX-e.x,o=t.pageY-e.y,a=Math.sqrt(i*i+o*o);this._dollyStart.set(0,a)}_handleTouchStartDollyPan(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enablePan&&this._handleTouchStartPan(t)}_handleTouchStartDollyRotate(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enableRotate&&this._handleTouchStartRotate(t)}_handleTouchMoveRotate(t){if(this._pointers.length==1)this._rotateEnd.set(t.pageX,t.pageY);else{const i=this._getSecondPointerPosition(t),o=.5*(t.pageX+i.x),a=.5*(t.pageY+i.y);this._rotateEnd.set(o,a)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(M*this._rotateDelta.x/e.clientHeight),this._rotateUp(M*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(t){if(this._pointers.length===1)this._panEnd.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),i=.5*(t.pageX+e.x),o=.5*(t.pageY+e.y);this._panEnd.set(i,o)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(t){const e=this._getSecondPointerPosition(t),i=t.pageX-e.x,o=t.pageY-e.y,a=Math.sqrt(i*i+o*o);this._dollyEnd.set(0,a),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const n=(t.pageX+e.x)*.5,l=(t.pageY+e.y)*.5;this._updateZoomParameters(n,l)}_handleTouchMoveDollyPan(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enablePan&&this._handleTouchMovePan(t)}_handleTouchMoveDollyRotate(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enableRotate&&this._handleTouchMoveRotate(t)}_addPointer(t){this._pointers.push(t.pointerId)}_removePointer(t){delete this._pointerPositions[t.pointerId];for(let e=0;e<this._pointers.length;e++)if(this._pointers[e]==t.pointerId){this._pointers.splice(e,1);return}}_isTrackingPointer(t){for(let e=0;e<this._pointers.length;e++)if(this._pointers[e]==t.pointerId)return!0;return!1}_trackPointer(t){let e=this._pointerPositions[t.pointerId];e===void 0&&(e=new s.Vector2,this._pointerPositions[t.pointerId]=e),e.set(t.pageX,t.pageY)}_getSecondPointerPosition(t){const e=t.pointerId===this._pointers[0]?this._pointers[1]:this._pointers[0];return this._pointerPositions[e]}_customWheelEvent(t){const e=t.deltaMode,i={clientX:t.clientX,clientY:t.clientY,deltaY:t.deltaY};switch(e){case 1:i.deltaY*=16;break;case 2:i.deltaY*=100;break}return t.ctrlKey&&!this._controlActive&&(i.deltaY*=10),i}}function ie(r){this.enabled!==!1&&(this._pointers.length===0&&(this.domElement.setPointerCapture(r.pointerId),this.domElement.addEventListener("pointermove",this._onPointerMove),this.domElement.addEventListener("pointerup",this._onPointerUp)),!this._isTrackingPointer(r)&&(this._addPointer(r),r.pointerType==="touch"?this._onTouchStart(r):this._onMouseDown(r)))}function se(r){this.enabled!==!1&&(r.pointerType==="touch"?this._onTouchMove(r):this._onMouseMove(r))}function oe(r){switch(this._removePointer(r),this._pointers.length){case 0:this.domElement.releasePointerCapture(r.pointerId),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.dispatchEvent(zt),this.state=m.NONE;break;case 1:const t=this._pointers[0],e=this._pointerPositions[t];this._onTouchStart({pointerId:t,pageX:e.x,pageY:e.y});break}}function ne(r){let t;switch(r.button){case 0:t=this.mouseButtons.LEFT;break;case 1:t=this.mouseButtons.MIDDLE;break;case 2:t=this.mouseButtons.RIGHT;break;default:t=-1}switch(t){case s.MOUSE.DOLLY:if(this.enableZoom===!1)return;this._handleMouseDownDolly(r),this.state=m.DOLLY;break;case s.MOUSE.ROTATE:if(r.ctrlKey||r.metaKey||r.shiftKey){if(this.enablePan===!1)return;this._handleMouseDownPan(r),this.state=m.PAN}else{if(this.enableRotate===!1)return;this._handleMouseDownRotate(r),this.state=m.ROTATE}break;case s.MOUSE.PAN:if(r.ctrlKey||r.metaKey||r.shiftKey){if(this.enableRotate===!1)return;this._handleMouseDownRotate(r),this.state=m.ROTATE}else{if(this.enablePan===!1)return;this._handleMouseDownPan(r),this.state=m.PAN}break;default:this.state=m.NONE}this.state!==m.NONE&&this.dispatchEvent(mt)}function ae(r){switch(this.state){case m.ROTATE:if(this.enableRotate===!1)return;this._handleMouseMoveRotate(r);break;case m.DOLLY:if(this.enableZoom===!1)return;this._handleMouseMoveDolly(r);break;case m.PAN:if(this.enablePan===!1)return;this._handleMouseMovePan(r);break}}function re(r){this.enabled===!1||this.enableZoom===!1||this.state!==m.NONE||(r.preventDefault(),this.dispatchEvent(mt),this._handleMouseWheel(this._customWheelEvent(r)),this.dispatchEvent(zt))}function he(r){this.enabled===!1||this.enablePan===!1||this._handleKeyDown(r)}function le(r){switch(this._trackPointer(r),this._pointers.length){case 1:switch(this.touches.ONE){case s.TOUCH.ROTATE:if(this.enableRotate===!1)return;this._handleTouchStartRotate(r),this.state=m.TOUCH_ROTATE;break;case s.TOUCH.PAN:if(this.enablePan===!1)return;this._handleTouchStartPan(r),this.state=m.TOUCH_PAN;break;default:this.state=m.NONE}break;case 2:switch(this.touches.TWO){case s.TOUCH.DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchStartDollyPan(r),this.state=m.TOUCH_DOLLY_PAN;break;case s.TOUCH.DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchStartDollyRotate(r),this.state=m.TOUCH_DOLLY_ROTATE;break;default:this.state=m.NONE}break;default:this.state=m.NONE}this.state!==m.NONE&&this.dispatchEvent(mt)}function ce(r){switch(this._trackPointer(r),this.state){case m.TOUCH_ROTATE:if(this.enableRotate===!1)return;this._handleTouchMoveRotate(r),this.update();break;case m.TOUCH_PAN:if(this.enablePan===!1)return;this._handleTouchMovePan(r),this.update();break;case m.TOUCH_DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchMoveDollyPan(r),this.update();break;case m.TOUCH_DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchMoveDollyRotate(r),this.update();break;default:this.state=m.NONE}}function de(r){this.enabled!==!1&&r.preventDefault()}function pe(r){r.key==="Control"&&(this._controlActive=!0,this.domElement.getRootNode().addEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}function ue(r){r.key==="Control"&&(this._controlActive=!1,this.domElement.getRootNode().removeEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}class me{constructor(t){h(this,"scene");h(this,"camera");h(this,"renderer");h(this,"controls");h(this,"domElement");h(this,"loader");h(this,"textureLoader");h(this,"currentModel",null);h(this,"animationId",null);h(this,"animate",()=>{this.animationId=requestAnimationFrame(this.animate),this.controls.update(),this.renderer.render(this.scene,this.camera)});const{container:e,backgroundColor:i=1710638}=t;this.domElement=e,this.scene=new c.Scene,this.scene.background=new c.Color(i);const o=e.clientWidth/e.clientHeight;this.camera=new c.PerspectiveCamera(50,o,.1,1e3),this.camera.position.set(50,50,100),this.renderer=new c.WebGLRenderer({antialias:!0,alpha:!0}),this.renderer.setSize(e.clientWidth,e.clientHeight),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=c.PCFSoftShadowMap,e.appendChild(this.renderer.domElement),this.controls=new ee(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.1,this.controls.minDistance=10,this.controls.maxDistance=500,this.loader=new Lt,this.textureLoader=new c.TextureLoader,this.setupLighting(),this.setupHelpers(),window.addEventListener("resize",()=>this.handleResize(e)),this.animate()}setupLighting(){const t=new c.AmbientLight(16777215,.4);this.scene.add(t);const e=new c.DirectionalLight(16777215,.8);e.position.set(50,100,50),e.castShadow=!0,e.shadow.mapSize.width=2048,e.shadow.mapSize.height=2048,this.scene.add(e);const i=new c.DirectionalLight(16777215,.3);i.position.set(-50,50,-50),this.scene.add(i);const o=new c.DirectionalLight(8965375,.2);o.position.set(0,-50,-100),this.scene.add(o)}setupHelpers(){const t=new c.GridHelper(200,20,4473924,3355443);t.position.y=-.1,this.scene.add(t);const e=new c.AxesHelper(20);this.scene.add(e)}handleResize(t){const e=t.clientWidth,i=t.clientHeight;this.camera.aspect=e/i,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,i)}async loadModel(t){this.currentModel&&(this.scene.remove(this.currentModel),this.disposeModel(this.currentModel),this.currentModel=null);try{return this.currentModel=await this.loader.loadFromFile(t),this.scene.add(this.currentModel),this.fitCameraToModel(),console.log(`Loaded model with ${this.countMeshes(this.currentModel)} meshes`),this.currentModel}catch(e){throw console.error("Failed to load model:",e),e}}getModel(){return this.currentModel}async loadTexture(t){if(!this.currentModel){console.warn("No model loaded to apply texture to");return}const e=URL.createObjectURL(t);try{const i=await new Promise((o,a)=>{this.textureLoader.load(e,o,void 0,a)});Ht(this.currentModel,i),console.log("Texture applied")}finally{URL.revokeObjectURL(e)}}fitCameraToModel(){if(!this.currentModel)return;const t=new c.Box3().setFromObject(this.currentModel),e=t.getCenter(new c.Vector3),i=t.getSize(new c.Vector3),o=Math.max(i.x,i.y,i.z),a=this.camera.fov*(Math.PI/180),n=o/(2*Math.tan(a/2))*1.5;this.camera.position.set(e.x+n*.5,e.y+n*.5,e.z+n),this.controls.target.copy(e),this.controls.update()}resetCamera(){this.currentModel?this.fitCameraToModel():(this.camera.position.set(50,50,100),this.controls.target.set(0,0,0),this.controls.update())}setBackgroundColor(t){this.scene.background=new c.Color(t)}toggleWireframe(t){var e;(e=this.currentModel)==null||e.traverse(i=>{if(i instanceof c.Mesh){const o=i.material;o.wireframe=t}})}getModelHierarchy(){if(!this.currentModel)return null;const t=e=>({name:e.name,type:e.type,userData:e.userData,children:e.children.map(t)});return t(this.currentModel)}countMeshes(t){let e=0;return t.traverse(i=>{i instanceof c.Mesh&&e++}),e}disposeModel(t){t.traverse(e=>{e instanceof c.Mesh&&(e.geometry.dispose(),Array.isArray(e.material)?e.material.forEach(i=>i.dispose()):e.material.dispose())})}dispose(){this.animationId!==null&&cancelAnimationFrame(this.animationId),this.currentModel&&this.disposeModel(this.currentModel),this.controls.dispose(),this.renderer.dispose()}}p.AddNodeCommand=it,p.BaseCommand=X,p.BlockyModelLoader=Lt,p.DEFAULT_ORIENTATION=Ct,p.DEFAULT_POSITION=st,p.DEFAULT_STRETCH=ut,p.Editor=qt,p.HierarchyPanel=Jt,p.History=It,p.PropertyPanel=$t,p.RemoveNodeCommand=Dt,p.SelectionManager=gt,p.Serializer=Kt,p.SetPositionCommand=K,p.SetPropertyCommand=A,p.SetRotationCommand=$,p.SetScaleCommand=J,p.TransformManager=Pt,p.UVEditor=Rt,p.ViewerController=me,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
122
+ //# sourceMappingURL=blockymodel-web.umd.cjs.map