@jucie.io/engine-painter 1.0.39 → 1.0.41
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/dist/main.js +1 -1
- package/dist/main.js.map +2 -2
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var l={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var d=class{#t=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#t.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#t.delete(e)}get(e){return this.#t.get(e)}has(e){return this.#t.has(e)}get areas(){return Array.from(this.#t.values())}clear(){this.#t.clear()}};import{ServiceProvider as S}from"@jucie.io/engine";var f=class extends S{#t=null;#o=null;#i=null;#b=null;#u=new Set;#h=new Set;#y=null;#c=null;#s=!1;#e={isPressed:!1,button:null,dragStartX:null,dragStartY:null,isDragging:!1,dragThreshold:5,prevX:null,prevY:null};static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),onResize:e=>this.onResize(e),transferControlToOffscreen:()=>this.transferControlToOffscreen()}}setCanvas(e){this.#t&&this.#n(),this.#t=e,this.#m(),this.#v()}subscribe(e){return this.#u.add(e),()=>this.#u.delete(e)}onResize(e){return this.#h.add(e),()=>this.#h.delete(e)}transferControlToOffscreen(){if(!this.#t)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#s)throw new Error("Control has already been transferred to offscreen");return this.#o=this.#t.transferControlToOffscreen(),this.#s=!0,this.#o.width=this.#i.width,this.#o.height=this.#i.height,this.#S({width:this.#t.width,height:this.#t.height}),this.#o}#m(){this.#t&&(this.#i=this.#t.getBoundingClientRect())}#v(){this.#t&&(this.#m(),this.#b=new ResizeObserver(e=>{for(let t of e){if(t.target!==this.#t)continue;let{width:s,height:r}=t.contentRect;this.#S({width:s,height:r})}this.#m()}),this.#b.observe(this.#t),document.addEventListener("wheel",this.#l,{passive:!1}),document.addEventListener("pointermove",this.#g),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#a),document.addEventListener("pointercancel",this.#a),document.addEventListener("dblclick",this.#w))}#n(){this.#b&&(this.#b.disconnect(),this.#b=null),document.removeEventListener("wheel",this.#l),document.removeEventListener("pointermove",this.#g),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#a),document.removeEventListener("pointercancel",this.#a),document.removeEventListener("dblclick",this.#w)}#l=e=>{if(e.target===this.#t)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#p(e,"zoom");this.#f(t)}else{let t=this.#p(e,"scroll");this.#f(t)}};#g=e=>{this.#y=e,!this.#c&&(this.#c=requestAnimationFrame(()=>{if(this.#y){let t=this.#y;this.#y=null;let s="move",r=this.#E(t);if(this.#e.isPressed&&!this.#e.isDragging){let n=r.x-this.#e.dragStartX,o=r.y-this.#e.dragStartY;Math.sqrt(n*n+o*o)>this.#e.dragThreshold&&(this.#e.isDragging=!0,s="dragstart")}else this.#e.isDragging&&(s="drag");let i=this.#p(t,s);this.#f(i)}this.#c=null}))};#d=e=>{if(e.target===this.#t){let t=this.#E(e);this.#e.isPressed=!0,this.#e.button=e.button??null,this.#e.dragStartX=t.x,this.#e.dragStartY=t.y,this.#e.isDragging=!1;let s=this.#p(e,"down");this.#f(s)}};#a=e=>{if(this.#e.isDragging){let s=this.#p(e,"dragend");this.#f(s)}let t=this.#p(e,"up");this.#f(t),this.#e.isPressed=!1,this.#e.isDragging=!1,this.#e.dragStartX=null,this.#e.dragStartY=null};#w=e=>{let t=this.#p(e,"dblclick");this.#f(t)};#f(e){for(let t of this.#u)t(e)}#S(e){for(let t of this.#h)t(e)}#E(e){let t=e.target===this.#t,s,r;return t?(s=e.offsetX,r=e.offsetY):this.#i?(s=e.clientX-this.#i.left,r=e.clientY-this.#i.top):(s=e.clientX,r=e.clientY),{x:s,y:r,isOverCanvas:t}}#p(e,t){let{x:s,y:r,isOverCanvas:i}=this.#E(e),n=i||this.#i&&s>=0&&s<=this.#i.width&&r>=0&&r<=this.#i.height,o=0,a=0,h=0,b=0;t==="scroll"?(o=e.deltaX,a=e.deltaY,h=e.deltaZ,b=e.deltaMode):t==="zoom"?(o=0,a=e.deltaY,h=0):(t==="move"||t==="drag"||t==="dragstart")&&this.#e.prevX!==null&&this.#e.prevY!==null&&(o=s-this.#e.prevX,a=r-this.#e.prevY);let y=0;if(this.#e.isDragging&&this.#e.dragStartX!==null&&this.#e.dragStartY!==null){let v=s-this.#e.dragStartX,w=r-this.#e.dragStartY;y=Math.sqrt(v*v+w*w)}let R={x:s,y:r,clientX:e.clientX,clientY:e.clientY,prevX:this.#e.prevX,prevY:this.#e.prevY,type:t,timestamp:Date.now(),isOverCanvas:i,isWithinBounds:n,deltaX:o,deltaY:a,deltaZ:h,deltaMode:b,button:e.button??this.#e.button,buttons:e.buttons??0,isPressed:this.#e.isPressed,isDragging:this.#e.isDragging,dragStartX:this.#e.dragStartX,dragStartY:this.#e.dragStartY,dragDistance:y,shiftKey:e.shiftKey||!1,ctrlKey:e.ctrlKey||!1,altKey:e.altKey||!1,metaKey:e.metaKey||!1};return this.#e.prevX=s,this.#e.prevY=r,R}destroy(){this.#c&&(cancelAnimationFrame(this.#c),this.#c=null),this.#n(),this.#t=null,this.#o=null,this.#i=null,this.#u.clear(),this.#h.clear(),this.#s=!1,this.#e.isPressed=!1,this.#e.button=null,this.#e.dragStartX=null,this.#e.dragStartY=null,this.#e.isDragging=!1,this.#e.prevX=null,this.#e.prevY=null}};import{defineSurface as x}from"@jucie.io/reactive";var u=x(c=>{let e=c.signal(null),t=c.signal(null),s=c.signal(null),r=c.action((a,h)=>{e(h)}),i=c.action((a,h)=>{t(h)}),n=c.action((a,h)=>{s(h)}),o=c.action(()=>{e(null),t(null),s(null)});return{event:e,hoveredArea:t,activeArea:s,handleEvent:r,setHoveredArea:i,setActiveArea:n,reset:o}});import{ServiceProvider as T}from"@jucie.io/engine";import{createComputed as C,destroyComputed as m,addEffect as P}from"@jucie.io/reactive";import{createDefinition as E,definitionType as g}from"@jucie.io/engine";var L=E("BRUSH",[Object]),A=E("LAYER",[Object]),p=class extends T{#t=new Map;#o=null;#i=new Map;#b=new Map;#u=!1;#h=null;#y=!1;#c=!1;#s={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#e={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#m={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#v=new d;#n=u();#l=null;#g=null;#d=null;#a=new Map;#w=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#n}}actions(){return this.config&&Object.assign(this.#s,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setOffscreenCanvas:e=>this.setOffscreenCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(e),start:()=>this.start(),stop:()=>this.stop(),render:()=>this.render(),setTargetFPS:e=>this.setTargetFPS(e),setTimeScale:e=>this.setTimeScale(e),setFixedTimeStep:e=>this.setFixedTimeStep(e),setDebug:e=>this.setDebug(e),getMetrics:()=>this.getMetrics(),handleResize:(e,t)=>this.handleResize(e,t),subscribe:(e,t)=>this.subscribe(e,t),handlePointerEvent:e=>this.handlePointerEvent(e),subscribeToPointer:e=>this.#n.$subscribe(e),bindPointer:e=>this.#n.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e,s=e.transferControlToOffscreen();s.width=t.width,s.height=t.height,this.#o=s,Object.values(l).forEach(r=>{try{let i=s.getContext(r);i&&this.#i.set(r,i)}catch{console.warn(`Context type ${r} not supported`)}}),this.#l||(this.#l=new f),this.#l.setCanvas(t),this.#d&&this.#d.disconnect(),this.#d=new ResizeObserver(r=>{let i=r[0];i&&i.target===t&&(s.width=t.width,s.height=t.height,this.handleResize(t.width,t.height))}),this.#d.observe(t),this.#g&&this.#g(),this.#g=this.#l.subscribe(r=>{this.handlePointerEvent(r)})}setOffscreenCanvas(e){this.#o=e,Object.values(l).forEach(t=>{try{let s=e.getContext(t);s&&this.#i.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#o);t&&(this.#o=t)}setAssets(e){this.#b=e}start(){this.#u||(this.#u=!0,this.#f())}stop(){this.#u&&(this.#u=!1,this.#h&&(cancelAnimationFrame(this.#h),this.#h=null))}addLayer(e){if(g(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#v),r={...s,name:t};if(s.data&&(r.dataReactor=this.#x(s.data,()=>this.#n)),s.when&&(r.whenReactor=this.#x(s.when,()=>r?.dataReactor?.computed()||void 0)),r.brushes=s.children.map(i=>{if(g(i)==="BRUSH"){let n=i._name,o=i(this.useContext,this.#v),a={name:n,...o};if(o.data&&(a.dataReactor=this.#x(o.data,()=>this.#n)),o.when&&(a.whenReactor=this.#x(o.when,()=>a?.dataReactor?.computed()||void 0)),a.lifecycle?.onMount)try{a.lifecycle.onMount(this.#i.get(a.context||s.context))}catch(h){console.error(`Error in brush "${a.name}" onMount:`,h)}return a}return g(i)==="LAYER"?this.addLayer(i):i}),this.#t.set(t,r),r.lifecycle?.onMount)try{r.lifecycle.onMount(r.context)}catch(i){console.error(`Error in layer "${t}" onMount:`,i)}return r}removeLayer(e){let t=this.#t.get(e);if(t){if(t.lifecycle?.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(s){console.error(`Error in layer "${e}" onUnmount:`,s)}t.brushes.forEach(s=>{if(s.lifecycle?.onUnmount)try{s.lifecycle.onUnmount(this.#i.get(s.context||t.context))}catch(r){console.error(`Error in brush "${s.name}" onUnmount:`,r)}s.whenReactor&&m(s.whenReactor),s.dataReactor&&(s.dataReactor?.unsubscribe(),s.dataReactor?.computed&&m(s.dataReactor.computed))}),t.whenReactor&&(t.whenReactor?.unsubscribe(),t.whenReactor?.computed&&m(t.whenReactor.computed)),this.#t.delete(e)}}#f(){this.#c||this.#y||(this.#c=!0,this.#h=requestAnimationFrame(()=>{this.#c=!1,this.#h=null,this.#S()}))}async#S(){if(this.#o){this.#y=!0;try{this.#v.clear();let e=this.#s.debug?.enabled?performance.now():0;this.#i.forEach(t=>{t.clearRect(0,0,this.#o.width,this.#o.height)});for(let t of this.#t.values()){let s=this.#s.debug?.enabled?performance.now():0;if(t.whenReactor&&!t.whenReactor.computed())continue;let r=t.context;if(r){if(t.lifecycle?.beforeRender)try{t.lifecycle.beforeRender(r,this.#e)}catch(i){console.error(`Error in layer "${t.name}" beforeRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}r.save(),t.settings&&Object.entries(t.settings).forEach(([i,n])=>{typeof r[i]=="function"?r[i](...Array.isArray(n)?n:[n]):r[i]=n});for(let i of t.brushes){let n=this.#s.debug?.enabled?performance.now():0;if(i.whenReactor&&!i.whenReactor.computed())continue;let o=i.context?this.#i.get(i.context):r;if(o){if(i.lifecycle?.beforeRender)try{i.lifecycle.beforeRender(o,this.#e)}catch(a){console.error(`Error in brush "${i.name}" beforeRender:`,a),i.lifecycle?.onError&&i.lifecycle.onError(a);continue}o.save(),i.settings&&Object.entries(i.settings).forEach(([a,h])=>{typeof o[a]=="function"?o[a](...Array.isArray(h)?h:[h]):o[a]=h});try{let a={};if(i.assets)for(let h of i.assets)a[h]=this.#b.get(h);if(i.render(o,i.dataReactor?i.dataReactor.computed():void 0,a,this.#e),i.lifecycle?.afterRender&&i.lifecycle.afterRender(o,this.#e),this.#s.debug?.enabled){let h=performance.now()-n;this.#m.brushTimes.set(i.name,h),this.#s.debug?.showBounds&&this.#E(o,i)}}catch(a){console.error(`Error in brush "${i.name}":`,a),i.lifecycle?.onError&&i.lifecycle.onError(a)}finally{o.restore()}}}if(r.restore(),t.lifecycle?.afterRender)try{t.lifecycle.afterRender(r,this.#e)}catch(i){console.error(`Error in layer "${t.name}" afterRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}if(this.#s.debug?.enabled){let i=performance.now()-s;this.#m.layerTimes.set(t.name,i),this.#s.debug?.showBounds&&this.#p(r,t)}}}this.#s.debug?.enabled&&this.#P()}finally{this.#y=!1}}}#E(e,t){e.save(),e.strokeStyle="rgba(0, 255, 0, 0.5)",e.lineWidth=1,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#p(e,t){e.save(),e.strokeStyle="rgba(255, 0, 0, 0.5)",e.lineWidth=2,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#P(){let e=this.#i.get(l["2D"]);if(!e)return;e.save(),e.resetTransform(),e.font="12px monospace",e.fillStyle="white",e.strokeStyle="black",e.lineWidth=3;let t=20,s=15;if(this.#s.debug?.showFPS){let r=`FPS: ${Math.round(this.#m.fps)} (${this.#e.deltaTime.toFixed(2)}ms)`;e.strokeText(r,10,t),e.fillText(r,10,t),t+=s}if(this.#s.debug?.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[r,i]of this.#m.layerTimes){let n=` ${r}: ${i.toFixed(2)}ms`;e.strokeText(n,10,t),e.fillText(n,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){for(let s of this.#t.values())if(s.lifecycle?.onResize)try{s.lifecycle.onResize(e,t,s.context)}catch(r){console.error(`Error in layer "${s.name}" onResize:`,r),s.lifecycle?.onError&&s.lifecycle.onError(r)}}#x(e,t=()=>{}){if(!e)return null;let s=C(e,{immediate:!0,context:t}),r=P(s,()=>this.#f());return{computed:s,unsubscribe:r}}destroy(){this.stop(),this.#g&&(this.#g(),this.#g=null),this.#l&&(this.#l.destroy(),this.#l=null),this.#d&&(this.#d.disconnect(),this.#d=null),this.#n&&this.#n.$destroy();for(let e of this.#t.keys())this.removeLayer(e)}setTargetFPS(e){this.#s.targetFPS=e,this.#s.fixedTimeStep=1e3/e}setTimeScale(e){this.#s.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#s.fixedTimeStep=e}setDebug(e={}){this.#s.debug||(this.#s.debug={}),Object.assign(this.#s.debug,e)}getMetrics(){return{...this.#m,deltaTime:this.#e.deltaTime,elapsedTime:this.#e.elapsedTime,frameCount:this.#e.frameCount}}handlePointerEvent(e){this.#n.handleEvent(e),this.#T(e),this.#L(e)}#L(e){let{type:t}=e,s=this.#n,r=s.event.value;switch(t){case"down":this.#r("pointer:down",s);break;case"up":this.#r("pointer:up",s),r&&!r.isDragging&&this.#r("pointer:click",s);break;case"move":this.#r("pointer:move",s);break;case"dragstart":this.#r("pointer:drag:start",s);break;case"drag":this.#r("pointer:drag:move",s);break;case"dragend":this.#r("pointer:drag:end",s);break;case"scroll":this.#r("pointer:scroll",s);break;case"zoom":this.#r("pointer:zoom",s);break;case"dblclick":this.#r("pointer:dblclick",s);break}let i=this.#w,n=r?.isOverCanvas||!1;n&&!i?this.#r("pointer:enter",s):!n&&i&&this.#r("pointer:leave",s),this.#w=n}#T(e){let{type:t,x:s,y:r}=e,i=this.#n;switch(t){case"down":{let n=this.#C(s,r);if(i.setActiveArea(n),n?.onPointerDown?.handler){let o=this.#R(n);n.onPointerDown.handler({...i,ctx:o,emit:this.#r.bind(this)})}break}case"up":{let n=i.activeArea;if(n?.onPointerUp?.handler){let o=this.#R(n);n.onPointerUp.handler({...i,ctx:o,emit:this.#r.bind(this)})}break}case"move":{let n=this.#C(s,r),o=i.hoveredArea,a=i.activeArea;if(a?.onPointerMove?.handler&&i.isDragging){let h=this.#R(a);a.onPointerMove.handler({...i,ctx:h,emit:this.#r.bind(this)})}if(n?.id!==o?.id){if(o?.onPointerLeave?.handler){let h=this.#R(o);o.onPointerLeave.handler({...i,ctx:h,emit:this.#r.bind(this)})}if(n?.onPointerEnter?.handler){let h=this.#R(n);n.onPointerEnter.handler({...i,ctx:h,emit:this.#r.bind(this)})}i.setHoveredArea(n)}break}case"scroll":case"zoom":break;case"dblclick":break}}#R(e){return e?e.context?this.#i.get(e.context):this.#i.get(l["2D"]):null}subscribe(e,t){return this.#a.has(e)||this.#a.set(e,new Set),this.#a.get(e).add(t),()=>{let s=this.#a.get(e);s&&(s.delete(t),s.size===0&&this.#a.delete(e))}}#C(e,t){let s=this.#v.areas.sort((r,i)=>(i.priority||0)-(r.priority||0));for(let r of s)if(this.#A(e,t,r.bounds))return r;return null}#A(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#r(e,t){let s=this.#a.get(e);if(s)for(let r of s)r(t)}_testEmitPointerEvent(e){this.#n.handleEvent(e),this.#T(e)}};export{f as CanvasEvents,d as HitRegistry,p as Painter,L as defineBrush,A as defineLayer,u as usePointerSurface};
|
|
1
|
+
var d={"2D":"2d",WEBGL:"webgl",WEBGL2:"webgl2",BITMAPRENDERER:"bitmaprenderer"};var f=class{#t=new Map;register(e,t){if(!e)throw new Error("Hit area must have an id");return this.#t.set(e,{id:e,...t}),()=>this.unregister(e)}unregister(e){this.#t.delete(e)}get(e){return this.#t.get(e)}has(e){return this.#t.has(e)}get areas(){return Array.from(this.#t.values())}clear(){this.#t.clear()}};import{ServiceProvider as S}from"@jucie.io/engine";var u=class extends S{#t=null;#o=null;#i=null;#p=null;#u=new Set;#h=new Set;#y=null;#c=null;#s=!1;#e={isPressed:!1,button:null,dragStartX:null,dragStartY:null,isDragging:!1,dragThreshold:5,prevX:null,prevY:null};static manifest={name:"CanvasEvents",namespace:"canvasEvents",version:"1.0.0"};actions(){return{setCanvas:e=>this.setCanvas(e),subscribe:e=>this.subscribe(e),onResize:e=>this.onResize(e),transferControlToOffscreen:()=>this.transferControlToOffscreen()}}setCanvas(e){this.#t&&this.#n(),this.#t=e,this.#m(),this.#v()}subscribe(e){return this.#u.add(e),()=>this.#u.delete(e)}onResize(e){return this.#h.add(e),()=>this.#h.delete(e)}transferControlToOffscreen(){if(!this.#t)throw new Error("Canvas must be set before transferring control to offscreen");if(this.#s)throw new Error("Control has already been transferred to offscreen");return this.#o=this.#t.transferControlToOffscreen(),this.#s=!0,this.#o.width=this.#i.width,this.#o.height=this.#i.height,this.#S({width:this.#t.width,height:this.#t.height}),this.#o}#m(){this.#t&&(this.#i=this.#t.getBoundingClientRect())}#v(){this.#t&&(this.#m(),this.#p=new ResizeObserver(e=>{for(let t of e){if(t.target!==this.#t)continue;let{width:s,height:r}=t.contentRect;this.#S({width:s,height:r})}this.#m()}),this.#p.observe(this.#t),document.addEventListener("wheel",this.#l,{passive:!1}),document.addEventListener("pointermove",this.#g),document.addEventListener("pointerdown",this.#d),document.addEventListener("pointerup",this.#a),document.addEventListener("pointercancel",this.#a),document.addEventListener("dblclick",this.#E))}#n(){this.#p&&(this.#p.disconnect(),this.#p=null),document.removeEventListener("wheel",this.#l),document.removeEventListener("pointermove",this.#g),document.removeEventListener("pointerdown",this.#d),document.removeEventListener("pointerup",this.#a),document.removeEventListener("pointercancel",this.#a),document.removeEventListener("dblclick",this.#E)}#l=e=>{if(e.target===this.#t)if(e.preventDefault(),e.stopPropagation(),e.ctrlKey){let t=this.#b(e,"zoom");this.#f(t)}else{let t=this.#b(e,"scroll");this.#f(t)}};#g=e=>{this.#y=e,!this.#c&&(this.#c=requestAnimationFrame(()=>{if(this.#y){let t=this.#y;this.#y=null;let s="move",r=this.#R(t);if(this.#e.isPressed&&!this.#e.isDragging){let a=r.x-this.#e.dragStartX,n=r.y-this.#e.dragStartY;Math.sqrt(a*a+n*n)>this.#e.dragThreshold&&(this.#e.isDragging=!0,s="dragstart")}else this.#e.isDragging&&(s="drag");let i=this.#b(t,s);this.#f(i)}this.#c=null}))};#d=e=>{if(e.target===this.#t){let t=this.#R(e);this.#e.isPressed=!0,this.#e.button=e.button??null,this.#e.dragStartX=t.x,this.#e.dragStartY=t.y,this.#e.isDragging=!1;let s=this.#b(e,"down");this.#f(s)}};#a=e=>{if(this.#e.isDragging){let s=this.#b(e,"dragend");this.#f(s)}let t=this.#b(e,"up");this.#f(t),this.#e.isPressed=!1,this.#e.isDragging=!1,this.#e.dragStartX=null,this.#e.dragStartY=null};#E=e=>{let t=this.#b(e,"dblclick");this.#f(t)};#f(e){for(let t of this.#u)t(e)}#S(e){for(let t of this.#h)t(e)}#R(e){let t=e.target===this.#t,s,r;return t?(s=e.offsetX,r=e.offsetY):this.#i?(s=e.clientX-this.#i.left,r=e.clientY-this.#i.top):(s=e.clientX,r=e.clientY),{x:s,y:r,isOverCanvas:t}}#b(e,t){let{x:s,y:r,isOverCanvas:i}=this.#R(e),a=i||this.#i&&s>=0&&s<=this.#i.width&&r>=0&&r<=this.#i.height,n=0,o=0,h=0,l=0;t==="scroll"?(n=e.deltaX,o=e.deltaY,h=e.deltaZ,l=e.deltaMode):t==="zoom"?(n=0,o=e.deltaY,h=0):(t==="move"||t==="drag"||t==="dragstart")&&this.#e.prevX!==null&&this.#e.prevY!==null&&(n=s-this.#e.prevX,o=r-this.#e.prevY);let y=0;if(this.#e.isDragging&&this.#e.dragStartX!==null&&this.#e.dragStartY!==null){let v=s-this.#e.dragStartX,w=r-this.#e.dragStartY;y=Math.sqrt(v*v+w*w)}let R={x:s,y:r,clientX:e.clientX,clientY:e.clientY,prevX:this.#e.prevX,prevY:this.#e.prevY,type:t,timestamp:Date.now(),isOverCanvas:i,isWithinBounds:a,deltaX:n,deltaY:o,deltaZ:h,deltaMode:l,button:e.button??this.#e.button,buttons:e.buttons??0,isPressed:this.#e.isPressed,isDragging:this.#e.isDragging,dragStartX:this.#e.dragStartX,dragStartY:this.#e.dragStartY,dragDistance:y,shiftKey:e.shiftKey||!1,ctrlKey:e.ctrlKey||!1,altKey:e.altKey||!1,metaKey:e.metaKey||!1};return this.#e.prevX=s,this.#e.prevY=r,R}destroy(){this.#c&&(cancelAnimationFrame(this.#c),this.#c=null),this.#n(),this.#t=null,this.#o=null,this.#i=null,this.#u.clear(),this.#h.clear(),this.#s=!1,this.#e.isPressed=!1,this.#e.button=null,this.#e.dragStartX=null,this.#e.dragStartY=null,this.#e.isDragging=!1,this.#e.prevX=null,this.#e.prevY=null}};import{defineSurface as x}from"@jucie.io/reactive";var m=x(c=>{let e=c.signal(null),t=c.signal(null),s=c.signal(null),r=c.action((o,h)=>{e(h)}),i=c.action((o,h)=>{t(h)}),a=c.action((o,h)=>{s(h)}),n=c.action(()=>{e(null),t(null),s(null)});return{event:e,hoveredArea:t,activeArea:s,handleEvent:r,setHoveredArea:i,setActiveArea:a,reset:n}});import{ServiceProvider as T}from"@jucie.io/engine";import{createComputed as C,destroyComputed as g,addEffect as P}from"@jucie.io/reactive";import{createDefinition as E,definitionType as b}from"@jucie.io/engine";var L=E("BRUSH",[Object]),A=E("LAYER",[Object]),p=class extends T{#t=new Map;#o=null;#i=new Map;#p=new Map;#u=!1;#h=null;#y=!1;#c=!1;#s={targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}};#e={lastFrameTime:0,deltaTime:0,elapsedTime:0,frameCount:0};#m={fps:0,frameTime:0,layerTimes:new Map,brushTimes:new Map,skippedFrames:0};#v=new f;#n=m();#l=null;#g=null;#d=null;#a=new Map;#E=!1;static manifest={name:"Painter",namespace:"painter",version:"1.0.0",defaults:{targetFPS:60,fixedTimeStep:1e3/60,timeScale:1,debug:{enabled:!1,showFPS:!0,showBounds:!0,showLayerTiming:!0}}};getters(){return{pointer:()=>this.#n}}actions(){return this.config&&Object.assign(this.#s,this.config),{addLayer:e=>this.addLayer(e),addLayers:(...e)=>{for(let t of e)this.addLayer(t)},updateCanvas:e=>this.updateCanvas(e),setCanvas:e=>this.setCanvas(e),setOffscreenCanvas:e=>this.setOffscreenCanvas(e),setAssets:e=>this.setAssets(e),removeLayer:e=>this.removeLayer(e),start:()=>this.start(),stop:()=>this.stop(),render:()=>this.render(),setTargetFPS:e=>this.setTargetFPS(e),setTimeScale:e=>this.setTimeScale(e),setFixedTimeStep:e=>this.setFixedTimeStep(e),setDebug:e=>this.setDebug(e),getMetrics:()=>this.getMetrics(),handleResize:(e,t)=>this.handleResize(e,t),subscribe:(e,t)=>this.subscribe(e,t),handlePointerEvent:e=>this.handlePointerEvent(e),subscribeToPointer:e=>this.#n.$subscribe(e),bindPointer:e=>this.#n.$bind(e),_testEmitPointerEvent:e=>this._testEmitPointerEvent(e)}}setCanvas(e){let t=e,s=e.transferControlToOffscreen();s.width=t.width,s.height=t.height,this.#o=s,Object.values(d).forEach(r=>{try{let i=s.getContext(r);i&&this.#i.set(r,i)}catch{console.warn(`Context type ${r} not supported`)}}),this.#l||(this.#l=new u),this.#l.setCanvas(t),this.#d&&this.#d.disconnect(),this.#d=new ResizeObserver(r=>{let i=r[0];i&&i.target===t&&(s.width=t.width,s.height=t.height,this.handleResize(t.width,t.height))}),this.#d.observe(t),this.#g&&this.#g(),this.#g=this.#l.subscribe(r=>{this.handlePointerEvent(r)})}setOffscreenCanvas(e){this.#o=e,Object.values(d).forEach(t=>{try{let s=e.getContext(t);s&&this.#i.set(t,s)}catch{console.warn(`Context type ${t} not supported`)}})}updateCanvas(e){let t=e(this.#o);t&&(this.#o=t)}setAssets(e){this.#p=e}start(){this.#u||(this.#u=!0,this.#f())}stop(){this.#u&&(this.#u=!1,this.#h&&(cancelAnimationFrame(this.#h),this.#h=null))}addLayer(e){if(b(e)!=="LAYER")throw new Error("Invalid layer definition");let t=e._name,s=e(this.useContext,this.#v),r={...s,name:t,context:this.#i.get(s.context||"2d")};if(s.data&&(r.dataReactor=this.#x(s.data,()=>this.#n)),s.when&&(r.whenReactor=this.#x(s.when,()=>r?.dataReactor?.computed()||void 0)),r.brushes=s.children.map(i=>{if(b(i)==="BRUSH"){let a=i._name,n=i(this.useContext,this.#v),o={name:a,...n};if(n.data&&(o.dataReactor=this.#x(n.data,()=>this.#n)),n.when&&(o.whenReactor=this.#x(n.when,()=>o?.dataReactor?.computed()||void 0)),o.lifecycle?.onMount)try{o.lifecycle.onMount(this.#i.get(o.context||s.context))}catch(h){console.error(`Error in brush "${o.name}" onMount:`,h)}return o}return b(i)==="LAYER"?this.addLayer(i):i}),this.#t.set(t,r),r.lifecycle?.onMount)try{r.lifecycle.onMount(r.context)}catch(i){console.error(`Error in layer "${t}" onMount:`,i)}return r}removeLayer(e){let t=this.#t.get(e);if(t){if(t.lifecycle?.onUnmount)try{t.lifecycle.onUnmount(t.context)}catch(s){console.error(`Error in layer "${e}" onUnmount:`,s)}t.brushes.forEach(s=>{if(s.lifecycle?.onUnmount)try{s.lifecycle.onUnmount(this.#i.get(s.context||t.context))}catch(r){console.error(`Error in brush "${s.name}" onUnmount:`,r)}s.whenReactor&&g(s.whenReactor),s.dataReactor&&(s.dataReactor?.unsubscribe(),s.dataReactor?.computed&&g(s.dataReactor.computed))}),t.whenReactor&&(t.whenReactor?.unsubscribe(),t.whenReactor?.computed&&g(t.whenReactor.computed)),this.#t.delete(e)}}#f(){this.#c||this.#y||(this.#c=!0,this.#h=requestAnimationFrame(()=>{this.#c=!1,this.#h=null,this.#S()}))}async#S(){if(this.#o){this.#y=!0;try{this.#v.clear();let e=this.#s.debug?.enabled?performance.now():0;this.#i.forEach(t=>{t.clearRect(0,0,this.#o.width,this.#o.height)});for(let t of this.#t.values()){let s=this.#s.debug?.enabled?performance.now():0;if(t.whenReactor&&!t.whenReactor.computed())continue;let r=t.context;if(r){if(t.lifecycle?.beforeRender)try{t.lifecycle.beforeRender(r,this.#e)}catch(i){console.error(`Error in layer "${t.name}" beforeRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}r.save(),t.settings&&Object.entries(t.settings).forEach(([i,a])=>{typeof r[i]=="function"?r[i](...Array.isArray(a)?a:[a]):r[i]=a});for(let i of t.brushes){let a=this.#s.debug?.enabled?performance.now():0;if(i.whenReactor&&!i.whenReactor.computed())continue;let n=i.context?this.#i.get(i.context):r;if(n){if(i.lifecycle?.beforeRender)try{i.lifecycle.beforeRender(n,this.#e)}catch(o){console.error(`Error in brush "${i.name}" beforeRender:`,o),i.lifecycle?.onError&&i.lifecycle.onError(o);continue}n.save(),i.settings&&Object.entries(i.settings).forEach(([o,h])=>{typeof n[o]=="function"?n[o](...Array.isArray(h)?h:[h]):n[o]=h});try{let o={};if(i.assets)for(let h of i.assets)o[h]=this.#p.get(h);if(i.render(n,i.dataReactor?i.dataReactor.computed():void 0,o,this.#e),i.lifecycle?.afterRender&&i.lifecycle.afterRender(n,this.#e),this.#s.debug?.enabled){let h=performance.now()-a;this.#m.brushTimes.set(i.name,h),this.#s.debug?.showBounds&&this.#R(n,i)}}catch(o){console.error(`Error in brush "${i.name}":`,o),i.lifecycle?.onError&&i.lifecycle.onError(o)}finally{n.restore()}}}if(r.restore(),t.lifecycle?.afterRender)try{t.lifecycle.afterRender(r,this.#e)}catch(i){console.error(`Error in layer "${t.name}" afterRender:`,i),t.lifecycle?.onError&&t.lifecycle.onError(i)}if(this.#s.debug?.enabled){let i=performance.now()-s;this.#m.layerTimes.set(t.name,i),this.#s.debug?.showBounds&&this.#b(r,t)}}}this.#s.debug?.enabled&&this.#P()}finally{this.#y=!1}}}#R(e,t){e.save(),e.strokeStyle="rgba(0, 255, 0, 0.5)",e.lineWidth=1,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#b(e,t){e.save(),e.strokeStyle="rgba(255, 0, 0, 0.5)",e.lineWidth=2,e.strokeRect(0,0,e.canvas.width,e.canvas.height),e.restore()}#P(){let e=this.#i.get(d["2D"]);if(!e)return;e.save(),e.resetTransform(),e.font="12px monospace",e.fillStyle="white",e.strokeStyle="black",e.lineWidth=3;let t=20,s=15;if(this.#s.debug?.showFPS){let r=`FPS: ${Math.round(this.#m.fps)} (${this.#e.deltaTime.toFixed(2)}ms)`;e.strokeText(r,10,t),e.fillText(r,10,t),t+=s}if(this.#s.debug?.showLayerTiming){e.fillText("Layer Times:",10,t),t+=s;for(let[r,i]of this.#m.layerTimes){let a=` ${r}: ${i.toFixed(2)}ms`;e.strokeText(a,10,t),e.fillText(a,10,t),t+=s}e.fillText(this.state.get(["_transitions","pointer","currentState"]),10,t)}e.restore()}handleResize(e,t){for(let s of this.#t.values())if(s.lifecycle?.onResize)try{s.lifecycle.onResize(e,t,s.context)}catch(r){console.error(`Error in layer "${s.name}" onResize:`,r),s.lifecycle?.onError&&s.lifecycle.onError(r)}}#x(e,t=()=>{}){if(!e)return null;let s=C(e,{immediate:!0,context:t}),r=P(s,()=>this.#f());return{computed:s,unsubscribe:r}}destroy(){this.stop(),this.#g&&(this.#g(),this.#g=null),this.#l&&(this.#l.destroy(),this.#l=null),this.#d&&(this.#d.disconnect(),this.#d=null),this.#n&&this.#n.$destroy();for(let e of this.#t.keys())this.removeLayer(e)}setTargetFPS(e){this.#s.targetFPS=e,this.#s.fixedTimeStep=1e3/e}setTimeScale(e){this.#s.timeScale=Math.max(0,e)}setFixedTimeStep(e){this.#s.fixedTimeStep=e}setDebug(e={}){this.#s.debug||(this.#s.debug={}),Object.assign(this.#s.debug,e)}getMetrics(){return{...this.#m,deltaTime:this.#e.deltaTime,elapsedTime:this.#e.elapsedTime,frameCount:this.#e.frameCount}}handlePointerEvent(e){this.#n.handleEvent(e),this.#C(e),this.#L(e)}#L(e){let{type:t}=e,s=this.#n,r=s.event.value;switch(t){case"down":this.#r("pointer:down",s);break;case"up":this.#r("pointer:up",s),r&&!r.isDragging&&this.#r("pointer:click",s);break;case"move":this.#r("pointer:move",s);break;case"dragstart":this.#r("pointer:drag:start",s);break;case"drag":this.#r("pointer:drag:move",s);break;case"dragend":this.#r("pointer:drag:end",s);break;case"scroll":this.#r("pointer:scroll",s);break;case"zoom":this.#r("pointer:zoom",s);break;case"dblclick":this.#r("pointer:dblclick",s);break}let i=this.#E,a=r?.isOverCanvas||!1;a&&!i?this.#r("pointer:enter",s):!a&&i&&this.#r("pointer:leave",s),this.#E=a}#C(e){let{type:t,x:s,y:r}=e,i=this.#n;switch(t){case"down":{let n=this.#T(s,r);if(i.setActiveArea(n),n?.onPointerDown?.handler){let o=this.#w(n);n.onPointerDown.handler({...i,ctx:o,emit:this.#r.bind(this)})}break}case"up":{let n=i.activeArea;if(n?.onPointerUp?.handler){let o=this.#w(n);n.onPointerUp.handler({...i,ctx:o,emit:this.#r.bind(this)})}break}case"move":{let n=this.#T(s,r),o=i.hoveredArea,h=i.activeArea;if(h?.onPointerMove?.handler&&i.isDragging){let l=this.#w(h);h.onPointerMove.handler({...i,ctx:l,emit:this.#r.bind(this)})}if(n?.id!==o?.id){if(o?.onPointerLeave?.handler){let l=this.#w(o);o.onPointerLeave.handler({...i,ctx:l,emit:this.#r.bind(this)})}if(n?.onPointerEnter?.handler){let l=this.#w(n);n.onPointerEnter.handler({...i,ctx:l,emit:this.#r.bind(this)})}i.setHoveredArea(n)}break}case"dblclick":let a=this.#T(s,r);if(i.setActiveArea(a),a?.onPointerDblClick?.handler){let n=this.#w(a);a.onPointerDblClick.handler({...i,ctx:n,emit:this.#r.bind(this)})}break}}#w(e){return e?e.context?this.#i.get(e.context):this.#i.get(d["2D"]):null}subscribe(e,t){return this.#a.has(e)||this.#a.set(e,new Set),this.#a.get(e).add(t),()=>{let s=this.#a.get(e);s&&(s.delete(t),s.size===0&&this.#a.delete(e))}}#T(e,t){let s=this.#v.areas.sort((r,i)=>(i.priority||0)-(r.priority||0));for(let r of s)if(this.#A(e,t,r.bounds))return r;return null}#A(e,t,s){return e>=s.x&&e<=s.x+s.width&&t>=s.y&&t<=s.y+s.height}#r(e,t){let s=this.#a.get(e);if(s)for(let r of s)r(t)}_testEmitPointerEvent(e){this.#n.handleEvent(e),this.#C(e)}};export{u as CanvasEvents,f as HitRegistry,p as Painter,L as defineBrush,A as defineLayer,m as usePointerSurface};
|
|
2
2
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/ContextTypes.js", "../src/HitRegistry.js", "../src/CanvasEvents.js", "../src/usePointerSurface.js", "../src/Painter.js"],
|
|
4
|
-
"sourcesContent": ["export const ContextTypes = {\n '2D': '2d',\n 'WEBGL': 'webgl',\n 'WEBGL2': 'webgl2',\n 'BITMAPRENDERER': 'bitmaprenderer'\n};", "export class HitRegistry {\n #areas = new Map();\n\n register(id, area) {\n if (!id) {\n throw new Error('Hit area must have an id');\n }\n this.#areas.set(id, { id, ...area });\n return () => this.unregister(id);\n }\n\n unregister(id) {\n this.#areas.delete(id);\n }\n\n get(id) {\n return this.#areas.get(id);\n }\n\n has(id) {\n return this.#areas.has(id);\n }\n\n get areas() {\n return Array.from(this.#areas.values());\n }\n\n clear() {\n this.#areas.clear();\n }\n}", "import { ServiceProvider } from '@jucie.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n\n // Internal state for semantic event interpretation\n #state = {\n isPressed: false,\n button: null,\n dragStartX: null,\n dragStartY: null,\n isDragging: false,\n dragThreshold: 5,\n prevX: null,\n prevY: null\n };\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen()\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#cachedRect.width;\n this.#offscreenCanvas.height = this.#cachedRect.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n \n if (event.ctrlKey) {\n const normalized = this.#normalizeEvent(event, 'zoom');\n this.#emit(normalized);\n } else {\n const normalized = this.#normalizeEvent(event, 'scroll');\n this.#emit(normalized);\n }\n }\n\n #handleMove = (event) => {\n // Store latest raw event and throttle with RAF\n this.#pendingMove = event;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n const rawEvent = this.#pendingMove;\n this.#pendingMove = null;\n \n // Determine event type based on state\n let type = 'move';\n const position = this.#getPosition(rawEvent);\n \n // Check for drag start\n if (this.#state.isPressed && !this.#state.isDragging) {\n const dx = position.x - this.#state.dragStartX;\n const dy = position.y - this.#state.dragStartY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance > this.#state.dragThreshold) {\n this.#state.isDragging = true;\n type = 'dragstart';\n }\n } else if (this.#state.isDragging) {\n type = 'drag';\n }\n \n const normalized = this.#normalizeEvent(rawEvent, type);\n this.#emit(normalized);\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const position = this.#getPosition(event);\n \n // Update state\n this.#state.isPressed = true;\n this.#state.button = event.button ?? null;\n this.#state.dragStartX = position.x;\n this.#state.dragStartY = position.y;\n this.#state.isDragging = false;\n \n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Emit dragend if we were dragging\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Always emit up event\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleDblClick = (event) => {\n const normalized = this.#normalizeEvent(event, 'dblclick');\n this.#emit(normalized);\n }\n\n #emit(event) {\n for (const subscriber of this.#subscribers) {\n subscriber(event);\n }\n }\n\n #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\n }\n }\n\n #getPosition(event) {\n const isOverCanvas = event.target === this.#canvas;\n \n let x, y;\n if (isOverCanvas) {\n x = event.offsetX;\n y = event.offsetY;\n } else if (this.#cachedRect) {\n x = event.clientX - this.#cachedRect.left;\n y = event.clientY - this.#cachedRect.top;\n } else {\n x = event.clientX;\n y = event.clientY;\n }\n \n return { x, y, isOverCanvas };\n }\n\n #normalizeEvent(event, type) {\n const { x, y, isOverCanvas } = this.#getPosition(event);\n\n const isWithinBounds = isOverCanvas || (\n this.#cachedRect &&\n x >= 0 && \n x <= this.#cachedRect.width && \n y >= 0 && \n y <= this.#cachedRect.height\n );\n \n // Calculate deltas based on event type\n let deltaX = 0;\n let deltaY = 0;\n let deltaZ = 0;\n let deltaMode = 0;\n \n if (type === 'scroll') {\n // Scroll events use wheel deltas\n deltaX = event.deltaX;\n deltaY = event.deltaY;\n deltaZ = event.deltaZ;\n deltaMode = event.deltaMode;\n } else if (type === 'zoom') {\n // Zoom uses simplified delta\n deltaX = 0;\n deltaY = event.deltaY;\n deltaZ = 0;\n } else if (type === 'move' || type === 'drag' || type === 'dragstart') {\n // Position-based events calculate deltas from previous position\n if (this.#state.prevX !== null && this.#state.prevY !== null) {\n deltaX = x - this.#state.prevX;\n deltaY = y - this.#state.prevY;\n }\n }\n \n // Calculate drag distance if dragging\n let dragDistance = 0;\n if (this.#state.isDragging && this.#state.dragStartX !== null && this.#state.dragStartY !== null) {\n const dx = x - this.#state.dragStartX;\n const dy = y - this.#state.dragStartY;\n dragDistance = Math.sqrt(dx * dx + dy * dy);\n }\n\n const normalized = {\n // Position\n x,\n y,\n clientX: event.clientX,\n clientY: event.clientY,\n prevX: this.#state.prevX,\n prevY: this.#state.prevY,\n \n // Event metadata\n type,\n timestamp: Date.now(),\n isOverCanvas,\n isWithinBounds,\n \n // Deltas (appropriate to event type)\n deltaX,\n deltaY,\n deltaZ,\n deltaMode,\n \n // Button state\n button: event.button ?? this.#state.button,\n buttons: event.buttons ?? 0,\n isPressed: this.#state.isPressed,\n \n // Drag state\n isDragging: this.#state.isDragging,\n dragStartX: this.#state.dragStartX,\n dragStartY: this.#state.dragStartY,\n dragDistance,\n \n // Modifiers\n shiftKey: event.shiftKey || false,\n ctrlKey: event.ctrlKey || false,\n altKey: event.altKey || false,\n metaKey: event.metaKey || false\n };\n \n // Update previous position for next delta calculation\n this.#state.prevX = x;\n this.#state.prevY = y;\n\n return normalized;\n }\n\n destroy() {\n if (this.#rafId) {\n cancelAnimationFrame(this.#rafId);\n this.#rafId = null;\n }\n this.#removeListeners();\n this.#canvas = null;\n this.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.button = null;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n this.#state.isDragging = false;\n this.#state.prevX = null;\n this.#state.prevY = null;\n }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.addLayer(layer);\n }\n },\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n layer.brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n \n // Handle nested layers recursively\n if (definitionType(child) === 'LAYER') { \n return this.addLayer(child);\n }\n\n return child;\n });\n\n \n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n });\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event.value;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'scroll':\n case 'zoom':\n // These are already emitted in #emitPointerEvents\n break;\n\n case 'dblclick':\n // This is already emitted in #emitPointerEvents\n break;\n }\n }\n\n #getContextForArea(area) {\n if (!area) return null;\n return area.context \n ? this.#contexts.get(area.context) \n : this.#contexts.get(ContextTypes['2D']);\n }\n\n subscribe(event, callback) {\n if (!this.#subscribers.has(event)) {\n this.#subscribers.set(event, new Set());\n }\n this.#subscribers.get(event).add(callback);\n \n return () => {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.#subscribers.delete(event);\n }\n }\n };\n }\n\n #hitTest(x, y) {\n // Sort by priority (highest first) and test\n const sorted = this.#hitRegistry.areas.sort((a, b) => \n (b.priority || 0) - (a.priority || 0)\n );\n \n for (const area of sorted) {\n if (this.#isPointInBounds(x, y, area.bounds)) {\n return area;\n }\n }\n return null;\n }\n\n #isPointInBounds(x, y, bounds) {\n return x >= bounds.x && \n x <= bounds.x + bounds.width &&\n y >= bounds.y && \n y <= bounds.y + bounds.height;\n }\n\n #emit(event, data) {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n callback(data);\n }\n }\n }\n\n // Test helper - only for testing, simulates normalized pointer events\n _testEmitPointerEvent(normalizedEvent) {\n this.#pointerSurface.handleEvent(normalizedEvent);\n this.#handlePointerInteraction(normalizedEvent);\n }\n}"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["export const ContextTypes = {\n '2D': '2d',\n 'WEBGL': 'webgl',\n 'WEBGL2': 'webgl2',\n 'BITMAPRENDERER': 'bitmaprenderer'\n};", "export class HitRegistry {\n #areas = new Map();\n\n register(id, area) {\n if (!id) {\n throw new Error('Hit area must have an id');\n }\n this.#areas.set(id, { id, ...area });\n return () => this.unregister(id);\n }\n\n unregister(id) {\n this.#areas.delete(id);\n }\n\n get(id) {\n return this.#areas.get(id);\n }\n\n has(id) {\n return this.#areas.has(id);\n }\n\n get areas() {\n return Array.from(this.#areas.values());\n }\n\n clear() {\n this.#areas.clear();\n }\n}", "import { ServiceProvider } from '@jucie.io/engine';\n\nexport class CanvasEvents extends ServiceProvider {\n #canvas = null;\n #offscreenCanvas = null;\n #cachedRect = null;\n #resizeObserver = null;\n #subscribers = new Set();\n #resizeSubscribers = new Set();\n #pendingMove = null;\n #rafId = null;\n #hasTransferredControl = false;\n\n // Internal state for semantic event interpretation\n #state = {\n isPressed: false,\n button: null,\n dragStartX: null,\n dragStartY: null,\n isDragging: false,\n dragThreshold: 5,\n prevX: null,\n prevY: null\n };\n\n static manifest = {\n name: 'CanvasEvents',\n namespace: 'canvasEvents',\n version: '1.0.0'\n };\n\n actions() {\n return {\n setCanvas: (canvas) => this.setCanvas(canvas),\n subscribe: (listener) => this.subscribe(listener),\n onResize: (listener) => this.onResize(listener),\n transferControlToOffscreen: () => this.transferControlToOffscreen()\n };\n }\n\n setCanvas(canvas) {\n if (this.#canvas) {\n this.#removeListeners();\n }\n \n this.#canvas = canvas;\n this.#updateCachedRect();\n this.#initializeListeners();\n }\n\n subscribe(subscriber) {\n this.#subscribers.add(subscriber);\n return () => this.#subscribers.delete(subscriber);\n }\n\n onResize(subscriber) {\n this.#resizeSubscribers.add(subscriber);\n return () => this.#resizeSubscribers.delete(subscriber);\n }\n\n transferControlToOffscreen() {\n if (!this.#canvas) {\n throw new Error('Canvas must be set before transferring control to offscreen');\n }\n\n if (this.#hasTransferredControl) {\n throw new Error('Control has already been transferred to offscreen');\n }\n\n // Transfer control\n this.#offscreenCanvas = this.#canvas.transferControlToOffscreen();\n this.#hasTransferredControl = true;\n\n\n\n // Set initial dimensions on offscreen canvas\n this.#offscreenCanvas.width = this.#cachedRect.width;\n this.#offscreenCanvas.height = this.#cachedRect.height;\n\n // Emit initial resize event with actual canvas dimensions\n this.#emitResize({\n width: this.#canvas.width,\n height: this.#canvas.height\n });\n\n return this.#offscreenCanvas;\n }\n\n #updateCachedRect() {\n if (this.#canvas) {\n this.#cachedRect = this.#canvas.getBoundingClientRect();\n }\n }\n\n #initializeListeners() {\n if (!this.#canvas) return;\n\n this.#updateCachedRect();\n\n this.#resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target !== this.#canvas) {\n continue;\n }\n const { width, height } = entry.contentRect;\n this.#emitResize({\n width: width,\n height: height\n });\n }\n this.#updateCachedRect();\n });\n this.#resizeObserver.observe(this.#canvas);\n\n document.addEventListener('wheel', this.#handleScroll, { passive: false });\n document.addEventListener('pointermove', this.#handleMove);\n document.addEventListener('pointerdown', this.#handleDown);\n document.addEventListener('pointerup', this.#handleUp);\n document.addEventListener('pointercancel', this.#handleUp);\n document.addEventListener('dblclick', this.#handleDblClick);\n }\n\n #removeListeners() {\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n\n document.removeEventListener('wheel', this.#handleScroll);\n document.removeEventListener('pointermove', this.#handleMove);\n document.removeEventListener('pointerdown', this.#handleDown);\n document.removeEventListener('pointerup', this.#handleUp);\n document.removeEventListener('pointercancel', this.#handleUp);\n document.removeEventListener('dblclick', this.#handleDblClick);\n }\n\n #handleScroll = (event) => {\n if (event.target !== this.#canvas) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n \n if (event.ctrlKey) {\n const normalized = this.#normalizeEvent(event, 'zoom');\n this.#emit(normalized);\n } else {\n const normalized = this.#normalizeEvent(event, 'scroll');\n this.#emit(normalized);\n }\n }\n\n #handleMove = (event) => {\n // Store latest raw event and throttle with RAF\n this.#pendingMove = event;\n if (this.#rafId) return;\n \n this.#rafId = requestAnimationFrame(() => {\n if (this.#pendingMove) {\n const rawEvent = this.#pendingMove;\n this.#pendingMove = null;\n \n // Determine event type based on state\n let type = 'move';\n const position = this.#getPosition(rawEvent);\n \n // Check for drag start\n if (this.#state.isPressed && !this.#state.isDragging) {\n const dx = position.x - this.#state.dragStartX;\n const dy = position.y - this.#state.dragStartY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance > this.#state.dragThreshold) {\n this.#state.isDragging = true;\n type = 'dragstart';\n }\n } else if (this.#state.isDragging) {\n type = 'drag';\n }\n \n const normalized = this.#normalizeEvent(rawEvent, type);\n this.#emit(normalized);\n }\n this.#rafId = null;\n });\n }\n\n #handleDown = (event) => {\n // Only capture if starting on canvas\n if (event.target === this.#canvas) {\n const position = this.#getPosition(event);\n \n // Update state\n this.#state.isPressed = true;\n this.#state.button = event.button ?? null;\n this.#state.dragStartX = position.x;\n this.#state.dragStartY = position.y;\n this.#state.isDragging = false;\n \n const normalized = this.#normalizeEvent(event, 'down');\n this.#emit(normalized); // Immediate\n }\n }\n\n #handleUp = (event) => {\n // Emit dragend if we were dragging\n if (this.#state.isDragging) {\n const dragend = this.#normalizeEvent(event, 'dragend');\n this.#emit(dragend);\n }\n \n // Always emit up event\n const normalized = this.#normalizeEvent(event, 'up');\n this.#emit(normalized); // Immediate\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.isDragging = false;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n }\n\n #handleDblClick = (event) => {\n const normalized = this.#normalizeEvent(event, 'dblclick');\n this.#emit(normalized);\n }\n\n #emit(event) {\n for (const subscriber of this.#subscribers) {\n subscriber(event);\n }\n }\n\n #emitResize(resizeData) {\n for (const subscriber of this.#resizeSubscribers) {\n subscriber(resizeData);\n }\n }\n\n #getPosition(event) {\n const isOverCanvas = event.target === this.#canvas;\n \n let x, y;\n if (isOverCanvas) {\n x = event.offsetX;\n y = event.offsetY;\n } else if (this.#cachedRect) {\n x = event.clientX - this.#cachedRect.left;\n y = event.clientY - this.#cachedRect.top;\n } else {\n x = event.clientX;\n y = event.clientY;\n }\n \n return { x, y, isOverCanvas };\n }\n\n #normalizeEvent(event, type) {\n const { x, y, isOverCanvas } = this.#getPosition(event);\n\n const isWithinBounds = isOverCanvas || (\n this.#cachedRect &&\n x >= 0 && \n x <= this.#cachedRect.width && \n y >= 0 && \n y <= this.#cachedRect.height\n );\n \n // Calculate deltas based on event type\n let deltaX = 0;\n let deltaY = 0;\n let deltaZ = 0;\n let deltaMode = 0;\n \n if (type === 'scroll') {\n // Scroll events use wheel deltas\n deltaX = event.deltaX;\n deltaY = event.deltaY;\n deltaZ = event.deltaZ;\n deltaMode = event.deltaMode;\n } else if (type === 'zoom') {\n // Zoom uses simplified delta\n deltaX = 0;\n deltaY = event.deltaY;\n deltaZ = 0;\n } else if (type === 'move' || type === 'drag' || type === 'dragstart') {\n // Position-based events calculate deltas from previous position\n if (this.#state.prevX !== null && this.#state.prevY !== null) {\n deltaX = x - this.#state.prevX;\n deltaY = y - this.#state.prevY;\n }\n }\n \n // Calculate drag distance if dragging\n let dragDistance = 0;\n if (this.#state.isDragging && this.#state.dragStartX !== null && this.#state.dragStartY !== null) {\n const dx = x - this.#state.dragStartX;\n const dy = y - this.#state.dragStartY;\n dragDistance = Math.sqrt(dx * dx + dy * dy);\n }\n\n const normalized = {\n // Position\n x,\n y,\n clientX: event.clientX,\n clientY: event.clientY,\n prevX: this.#state.prevX,\n prevY: this.#state.prevY,\n \n // Event metadata\n type,\n timestamp: Date.now(),\n isOverCanvas,\n isWithinBounds,\n \n // Deltas (appropriate to event type)\n deltaX,\n deltaY,\n deltaZ,\n deltaMode,\n \n // Button state\n button: event.button ?? this.#state.button,\n buttons: event.buttons ?? 0,\n isPressed: this.#state.isPressed,\n \n // Drag state\n isDragging: this.#state.isDragging,\n dragStartX: this.#state.dragStartX,\n dragStartY: this.#state.dragStartY,\n dragDistance,\n \n // Modifiers\n shiftKey: event.shiftKey || false,\n ctrlKey: event.ctrlKey || false,\n altKey: event.altKey || false,\n metaKey: event.metaKey || false\n };\n \n // Update previous position for next delta calculation\n this.#state.prevX = x;\n this.#state.prevY = y;\n\n return normalized;\n }\n\n destroy() {\n if (this.#rafId) {\n cancelAnimationFrame(this.#rafId);\n this.#rafId = null;\n }\n this.#removeListeners();\n this.#canvas = null;\n this.#offscreenCanvas = null;\n this.#cachedRect = null;\n this.#subscribers.clear();\n this.#resizeSubscribers.clear();\n this.#hasTransferredControl = false;\n \n // Reset state\n this.#state.isPressed = false;\n this.#state.button = null;\n this.#state.dragStartX = null;\n this.#state.dragStartY = null;\n this.#state.isDragging = false;\n this.#state.prevX = null;\n this.#state.prevY = null;\n }\n}\n", "import { defineSurface } from '@jucie.io/reactive';\n\nexport const usePointerSurface = defineSurface((setup) => {\n // Current normalized event from CanvasEvents\n const event = setup.signal(null);\n \n // Hit registry integration (still managed here)\n const hoveredArea = setup.signal(null);\n const activeArea = setup.signal(null);\n \n // Main handler - just stores the event\n const handleEvent = setup.action((_, normalizedEvent) => {\n event(normalizedEvent);\n });\n \n const setHoveredArea = setup.action((_, area) => {\n hoveredArea(area);\n });\n \n const setActiveArea = setup.action((_, area) => {\n activeArea(area);\n });\n \n const reset = setup.action(() => {\n event(null);\n hoveredArea(null);\n activeArea(null);\n });\n \n return {\n // Signals\n event,\n hoveredArea,\n activeArea,\n\n // Actions\n handleEvent,\n setHoveredArea,\n setActiveArea,\n reset\n };\n});\n", "import { ServiceProvider } from '@jucie.io/engine';\nimport { ContextTypes } from './ContextTypes.js';\nimport { createComputed, destroyComputed, addEffect } from '@jucie.io/reactive';\nimport { createDefinition, definitionType } from '@jucie.io/engine';\nimport { HitRegistry } from './HitRegistry.js';\nimport { CanvasEvents } from './CanvasEvents.js';\nimport { usePointerSurface } from './usePointerSurface.js';\n\nexport const defineBrush = createDefinition('BRUSH', [Object]);\nexport const defineLayer = createDefinition('LAYER', [Object]);\n\nexport class Painter extends ServiceProvider {\n #layers = new Map();\n #canvas = null; // Always OffscreenCanvas\n #contexts = new Map();\n #assets = new Map();\n #isRunning = false;\n #frameId = null;\n #isRendering = false;\n #renderScheduled = false;\n\n // Mutable runtime config (separate from frozen config)\n #runtimeConfig = {\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n };\n\n // Timing state\n #timing = {\n lastFrameTime: 0,\n deltaTime: 0,\n elapsedTime: 0,\n frameCount: 0\n };\n\n // Debug metrics\n #metrics = {\n fps: 0,\n frameTime: 0,\n layerTimes: new Map(),\n brushTimes: new Map(),\n skippedFrames: 0\n };\n\n // Hit detection state\n #hitRegistry = new HitRegistry();\n #pointerSurface = usePointerSurface();\n #canvasEvents = null; // Only created in main thread mode\n #pointerUnsubscribe = null;\n #resizeObserver = null; // For main thread canvas resize watching\n #subscribers = new Map(); // Map<event, Set<callback>>\n \n // Track state for event emission\n #wasOverCanvas = false;\n\n static manifest = {\n name: 'Painter',\n namespace: 'painter',\n version: '1.0.0',\n defaults: {\n // Timing configuration\n targetFPS: 60,\n fixedTimeStep: 1000 / 60,\n timeScale: 1.0,\n // Debug configuration\n debug: {\n enabled: false,\n showFPS: true,\n showBounds: true,\n showLayerTiming: true\n }\n }\n };\n\n getters () {\n return {\n pointer: () => this.#pointerSurface,\n };\n }\n\n actions() {\n // Initialize runtime config from frozen config\n if (this.config) {\n Object.assign(this.#runtimeConfig, this.config);\n }\n \n return {\n addLayer: (layerDef) => this.addLayer(layerDef),\n addLayers: (...layers) => {\n for (const layer of layers) {\n this.addLayer(layer);\n }\n },\n updateCanvas: (fn) => this.updateCanvas(fn),\n setCanvas: (canvas) => this.setCanvas(canvas),\n setOffscreenCanvas: (offscreenCanvas) => this.setOffscreenCanvas(offscreenCanvas),\n setAssets: (assets) => this.setAssets(assets),\n removeLayer: (name) => this.removeLayer(name),\n start: () => this.start(),\n stop: () => this.stop(),\n render: () => this.render(),\n setTargetFPS: (fps) => this.setTargetFPS(fps),\n setTimeScale: (scale) => this.setTimeScale(scale),\n setFixedTimeStep: (step) => this.setFixedTimeStep(step),\n setDebug: (options) => this.setDebug(options),\n getMetrics: () => this.getMetrics(),\n handleResize: (width, height) => this.handleResize(width, height),\n subscribe: (event, callback) => this.subscribe(event, callback),\n // Pointer API - receives normalized events from main thread\n handlePointerEvent: (normalizedEvent) => this.handlePointerEvent(normalizedEvent),\n subscribeToPointer: (callback) => this.#pointerSurface.$subscribe(callback),\n bindPointer: (path) => this.#pointerSurface.$bind(path),\n // Test helper - only for testing\n _testEmitPointerEvent: (normalizedEvent) => this._testEmitPointerEvent(normalizedEvent)\n };\n }\n\n // Main thread mode: Pass regular canvas, we create OffscreenCanvas + CanvasEvents\n setCanvas(canvas) {\n // Store reference to DOM canvas for resize observation\n const domCanvas = canvas;\n \n // Transfer control to offscreen\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Set initial dimensions\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Create and set up canvas events (main thread only)\n if (!this.#canvasEvents) {\n this.#canvasEvents = new CanvasEvents();\n }\n \n this.#canvasEvents.setCanvas(domCanvas);\n\n // Watch for canvas resizes and sync to offscreen canvas\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n }\n \n this.#resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry && entry.target === domCanvas) {\n // Sync dimensions to offscreen canvas\n offscreenCanvas.width = domCanvas.width;\n offscreenCanvas.height = domCanvas.height;\n \n // Notify layers of resize\n this.handleResize(domCanvas.width, domCanvas.height);\n }\n });\n \n this.#resizeObserver.observe(domCanvas);\n\n // Connect canvas events to surface\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n }\n\n this.#pointerUnsubscribe = this.#canvasEvents.subscribe((normalizedEvent) => {\n this.handlePointerEvent(normalizedEvent);\n });\n }\n\n // Worker thread mode: Accept pre-created OffscreenCanvas, expect external events\n setOffscreenCanvas(offscreenCanvas) {\n this.#canvas = offscreenCanvas;\n \n // Create contexts for each type\n Object.values(ContextTypes).forEach(type => {\n try {\n const ctx = offscreenCanvas.getContext(type);\n if (ctx) this.#contexts.set(type, ctx);\n } catch (e) {\n console.warn(`Context type ${type} not supported`);\n }\n });\n\n // Don't create CanvasEvents - events will come from external source\n // via handlePointerEvent()\n }\n\n updateCanvas(fn) {\n const result = fn(this.#canvas);\n if (result) {\n this.#canvas = result;\n }\n }\n\n setAssets(assets) {\n this.#assets = assets;\n }\n\n start() {\n if (!this.#isRunning) {\n this.#isRunning = true;\n this.#scheduleRender();\n }\n }\n\n stop() {\n if (this.#isRunning) {\n this.#isRunning = false;\n if (this.#frameId) {\n cancelAnimationFrame(this.#frameId);\n this.#frameId = null;\n }\n }\n }\n\n addLayer(layerDef) {\n if (definitionType(layerDef) !== 'LAYER') {\n throw new Error('Invalid layer definition');\n }\n\n const name = layerDef._name;\n const config = layerDef(this.useContext, this.#hitRegistry);\n\n const layer = {...config, name, context: this.#contexts.get(config.context || '2d') };\n \n // Set up layer computed if it has data paths\n if (config.data) {\n layer.dataReactor = this.#createReactor(config.data, () => this.#pointerSurface);\n }\n\n // Set up when reactor if layer has condition\n if (config.when) {\n layer.whenReactor = this.#createReactor(config.when, () => (layer?.dataReactor?.computed() || undefined));\n }\n\n // Set up brush reactors and structure\n layer.brushes = config.children.map(child => {\n if (definitionType(child) === 'BRUSH') {\n const name = child._name;\n const brushConfig = child(this.useContext, this.#hitRegistry);\n const brush = {\n name,\n ...brushConfig\n };\n\n if (brushConfig.data) {\n brush.dataReactor = this.#createReactor(brushConfig.data, () => this.#pointerSurface);\n }\n\n if (brushConfig.when) {\n brush.whenReactor = this.#createReactor(brushConfig.when, () => (brush?.dataReactor?.computed() || undefined));\n }\n\n // Call brush mount hook\n if (brush.lifecycle?.onMount) {\n try {\n brush.lifecycle.onMount(this.#contexts.get(brush.context || config.context));\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onMount:`, error);\n }\n }\n\n return brush;\n }\n \n // Handle nested layers recursively\n if (definitionType(child) === 'LAYER') { \n return this.addLayer(child);\n }\n\n return child;\n });\n\n \n\n this.#layers.set(name, layer);\n\n // Call layer mount hook\n if (layer.lifecycle?.onMount) {\n try {\n layer.lifecycle.onMount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onMount:`, error);\n }\n }\n\n return layer;\n }\n\n removeLayer(name) {\n const layer = this.#layers.get(name);\n if (!layer) return;\n\n // Call layer unmount hook\n if (layer.lifecycle?.onUnmount) {\n try {\n layer.lifecycle.onUnmount(layer.context);\n } catch (error) {\n console.error(`Error in layer \"${name}\" onUnmount:`, error);\n }\n }\n\n // Call brush unmount hooks and clean up reactors\n layer.brushes.forEach(brush => {\n if (brush.lifecycle?.onUnmount) {\n try {\n brush.lifecycle.onUnmount(\n this.#contexts.get(brush.context || layer.context)\n );\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" onUnmount:`, error);\n }\n }\n // Clean up brush when reactor\n if (brush.whenReactor) {\n destroyComputed(brush.whenReactor);\n }\n // Clean up brush computed and subscription\n if (brush.dataReactor) {\n brush.dataReactor?.unsubscribe();\n if (brush.dataReactor?.computed) {\n destroyComputed(brush.dataReactor.computed);\n }\n }\n });\n\n // Clean up layer when reactor\n if (layer.whenReactor) {\n layer.whenReactor?.unsubscribe();\n if (layer.whenReactor?.computed) {\n destroyComputed(layer.whenReactor.computed);\n }\n }\n\n this.#layers.delete(name);\n }\n\n #scheduleRender() {\n if (this.#renderScheduled || this.#isRendering) return;\n \n this.#renderScheduled = true;\n \n this.#frameId = requestAnimationFrame(() => {\n this.#renderScheduled = false;\n this.#frameId = null;\n this.#render();\n });\n }\n\n async #render() {\n if (!this.#canvas) return;\n this.#isRendering = true;\n \n try {\n // Clear hit registry at start of render\n this.#hitRegistry.clear();\n \n const renderStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Clear all contexts\n this.#contexts.forEach(ctx => {\n ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n });\n\n // Render layers in order\n for (const layer of this.#layers.values()) {\n const layerStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n // Check layer condition\n if (layer.whenReactor && !layer.whenReactor.computed()) continue;\n\n const ctx = layer.context;\n\n if (!ctx) continue;\n\n // Layer beforeRender hook\n if (layer.lifecycle?.beforeRender) {\n try {\n layer.lifecycle.beforeRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" beforeRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n // Apply layer settings\n ctx.save();\n if (layer.settings) {\n Object.entries(layer.settings).forEach(([key, value]) => {\n if (typeof ctx[key] === 'function') {\n ctx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n ctx[key] = value;\n }\n });\n }\n\n // Render brushes\n for (const brush of layer.brushes) {\n const brushStart = this.#runtimeConfig.debug?.enabled ? performance.now() : 0;\n\n if (brush.whenReactor && !brush.whenReactor.computed()) continue;\n\n\n const brushCtx = brush.context ? \n this.#contexts.get(brush.context) : \n ctx;\n\n if (!brushCtx) continue;\n\n // Brush beforeRender hook\n if (brush.lifecycle?.beforeRender) {\n try {\n brush.lifecycle.beforeRender(brushCtx, this.#timing);\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\" beforeRender:`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n continue;\n }\n }\n\n brushCtx.save();\n \n if (brush.settings) {\n Object.entries(brush.settings).forEach(([key, value]) => {\n if (typeof brushCtx[key] === 'function') {\n brushCtx[key](...(Array.isArray(value) ? value : [value]));\n } else {\n brushCtx[key] = value;\n }\n });\n }\n \n try {\n const requiredAssets = {};\n if (brush.assets) {\n for (const key of brush.assets) {\n requiredAssets[key] = this.#assets.get(key);\n }\n }\n brush.render(brushCtx, (brush.dataReactor ? brush.dataReactor.computed() : undefined), requiredAssets, this.#timing);\n\n // Brush afterRender hook\n if (brush.lifecycle?.afterRender) {\n brush.lifecycle.afterRender(brushCtx, this.#timing);\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const brushTime = performance.now() - brushStart;\n this.#metrics.brushTimes.set(brush.name, brushTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderBrushBounds(brushCtx, brush);\n }\n }\n } catch (error) {\n console.error(`Error in brush \"${brush.name}\":`, error);\n if (brush.lifecycle?.onError) brush.lifecycle.onError(error);\n } finally {\n brushCtx.restore();\n }\n }\n\n ctx.restore();\n\n // Layer afterRender hook\n if (layer.lifecycle?.afterRender) {\n try {\n layer.lifecycle.afterRender(ctx, this.#timing);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" afterRender:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n\n if (this.#runtimeConfig.debug?.enabled) {\n const layerTime = performance.now() - layerStart;\n this.#metrics.layerTimes.set(layer.name, layerTime);\n\n if (this.#runtimeConfig.debug?.showBounds) {\n this.#renderLayerBounds(ctx, layer);\n }\n }\n }\n\n // Render debug overlay if enabled\n if (this.#runtimeConfig.debug?.enabled) {\n this.#renderDebugOverlay();\n }\n \n } finally {\n this.#isRendering = false;\n }\n }\n\n #renderBrushBounds(ctx, brush) {\n ctx.save();\n ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';\n ctx.lineWidth = 1;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderLayerBounds(ctx, layer) {\n ctx.save();\n ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';\n ctx.lineWidth = 2;\n ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n ctx.restore();\n }\n\n #renderDebugOverlay() {\n const ctx = this.#contexts.get(ContextTypes['2D']);\n if (!ctx) return;\n\n ctx.save();\n ctx.resetTransform();\n ctx.font = '12px monospace';\n ctx.fillStyle = 'white';\n ctx.strokeStyle = 'black';\n ctx.lineWidth = 3;\n\n let y = 20;\n const lineHeight = 15;\n\n if (this.#runtimeConfig.debug?.showFPS) {\n const text = `FPS: ${Math.round(this.#metrics.fps)} (${this.#timing.deltaTime.toFixed(2)}ms)`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n if (this.#runtimeConfig.debug?.showLayerTiming) {\n ctx.fillText('Layer Times:', 10, y);\n y += lineHeight;\n\n for (const [name, time] of this.#metrics.layerTimes) {\n const text = ` ${name}: ${time.toFixed(2)}ms`;\n ctx.strokeText(text, 10, y);\n ctx.fillText(text, 10, y);\n y += lineHeight;\n }\n\n ctx.fillText(this.state.get(['_transitions', 'pointer', 'currentState']), 10, y);\n }\n\n ctx.restore();\n }\n\n handleResize(width, height) {\n // Call onResize hooks for all layers\n for (const layer of this.#layers.values()) {\n if (layer.lifecycle?.onResize) {\n try {\n layer.lifecycle.onResize(width, height, layer.context);\n } catch (error) {\n console.error(`Error in layer \"${layer.name}\" onResize:`, error);\n if (layer.lifecycle?.onError) layer.lifecycle.onError(error);\n }\n }\n }\n }\n\n #createReactor(fn, context = () => undefined) {\n if (!fn) return null;\n \n const computed = createComputed(fn, {\n immediate: true,\n context\n });\n \n const unsubscribe = addEffect(computed, () => this.#scheduleRender());\n \n return {computed, unsubscribe};\n }\n\n destroy() {\n this.stop();\n\n // Clean up pointer system\n if (this.#pointerUnsubscribe) {\n this.#pointerUnsubscribe();\n this.#pointerUnsubscribe = null;\n }\n if (this.#canvasEvents) {\n this.#canvasEvents.destroy();\n this.#canvasEvents = null;\n }\n if (this.#resizeObserver) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = null;\n }\n if (this.#pointerSurface) {\n this.#pointerSurface.$destroy();\n }\n\n // Clean up all layers and reactors\n for (const name of this.#layers.keys()) {\n this.removeLayer(name);\n }\n }\n\n setTargetFPS(fps) {\n this.#runtimeConfig.targetFPS = fps;\n this.#runtimeConfig.fixedTimeStep = 1000 / fps;\n }\n\n setTimeScale(scale) {\n this.#runtimeConfig.timeScale = Math.max(0, scale);\n }\n\n setFixedTimeStep(step) {\n this.#runtimeConfig.fixedTimeStep = step;\n }\n\n setDebug(options = {}) {\n if (!this.#runtimeConfig.debug) {\n this.#runtimeConfig.debug = {};\n }\n Object.assign(this.#runtimeConfig.debug, options);\n }\n\n getMetrics() {\n return {\n ...this.#metrics,\n deltaTime: this.#timing.deltaTime,\n elapsedTime: this.#timing.elapsedTime,\n frameCount: this.#timing.frameCount\n };\n }\n\n // Public method to receive pointer events from main thread\n handlePointerEvent(normalizedEvent) {\n // Feed normalized events into surface\n this.#pointerSurface.handleEvent(normalizedEvent);\n\n // Handle hit testing and interactions\n this.#handlePointerInteraction(normalizedEvent);\n \n // Emit generic pointer events for external subscribers\n this.#emitPointerEvents(normalizedEvent);\n }\n\n #emitPointerEvents(normalizedEvent) {\n const { type } = normalizedEvent;\n const pointer = this.#pointerSurface;\n const event = pointer.event.value;\n \n // Emit basic pointer events\n switch (type) {\n case 'down':\n this.#emit('pointer:down', pointer);\n break;\n \n case 'up':\n this.#emit('pointer:up', pointer);\n \n // Emit click if it wasn't a drag\n if (event && !event.isDragging) {\n this.#emit('pointer:click', pointer);\n }\n break;\n \n case 'move':\n this.#emit('pointer:move', pointer);\n break;\n \n case 'dragstart':\n this.#emit('pointer:drag:start', pointer);\n break;\n \n case 'drag':\n this.#emit('pointer:drag:move', pointer);\n break;\n \n case 'dragend':\n this.#emit('pointer:drag:end', pointer);\n break;\n \n case 'scroll':\n this.#emit('pointer:scroll', pointer);\n break;\n \n case 'zoom':\n this.#emit('pointer:zoom', pointer);\n break;\n \n case 'dblclick':\n this.#emit('pointer:dblclick', pointer);\n break;\n }\n \n // Check for canvas enter/leave\n const wasOverCanvas = this.#wasOverCanvas;\n const isOverCanvas = event?.isOverCanvas || false;\n \n if (isOverCanvas && !wasOverCanvas) {\n this.#emit('pointer:enter', pointer);\n } else if (!isOverCanvas && wasOverCanvas) {\n this.#emit('pointer:leave', pointer);\n }\n \n this.#wasOverCanvas = isOverCanvas;\n }\n\n #handlePointerInteraction(normalizedEvent) {\n const { type, x, y } = normalizedEvent;\n const pointer = this.#pointerSurface;\n\n switch (type) {\n case 'down': {\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDown?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDown.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'up': {\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerUp?.handler) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerUp.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n\n case 'move': {\n const hitArea = this.#hitTest(x, y);\n const prevHovered = pointer.hoveredArea;\n\n // Handle drag on active area\n const activeArea = pointer.activeArea;\n if (activeArea?.onPointerMove?.handler && pointer.isDragging) {\n const ctx = this.#getContextForArea(activeArea);\n activeArea.onPointerMove.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n // Handle hover changes\n if (hitArea?.id !== prevHovered?.id) {\n if (prevHovered?.onPointerLeave?.handler) {\n const ctx = this.#getContextForArea(prevHovered);\n prevHovered.onPointerLeave.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n if (hitArea?.onPointerEnter?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerEnter.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n\n pointer.setHoveredArea(hitArea);\n }\n break;\n }\n\n case 'dblclick':\n const hitArea = this.#hitTest(x, y);\n pointer.setActiveArea(hitArea);\n\n if (hitArea?.onPointerDblClick?.handler) {\n const ctx = this.#getContextForArea(hitArea);\n hitArea.onPointerDblClick.handler({\n ...pointer,\n ctx,\n emit: this.#emit.bind(this)\n });\n }\n break;\n }\n }\n\n #getContextForArea(area) {\n if (!area) return null;\n return area.context \n ? this.#contexts.get(area.context) \n : this.#contexts.get(ContextTypes['2D']);\n }\n\n subscribe(event, callback) {\n if (!this.#subscribers.has(event)) {\n this.#subscribers.set(event, new Set());\n }\n this.#subscribers.get(event).add(callback);\n \n return () => {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.#subscribers.delete(event);\n }\n }\n };\n }\n\n #hitTest(x, y) {\n // Sort by priority (highest first) and test\n const sorted = this.#hitRegistry.areas.sort((a, b) => \n (b.priority || 0) - (a.priority || 0)\n );\n \n for (const area of sorted) {\n if (this.#isPointInBounds(x, y, area.bounds)) {\n return area;\n }\n }\n return null;\n }\n\n #isPointInBounds(x, y, bounds) {\n return x >= bounds.x && \n x <= bounds.x + bounds.width &&\n y >= bounds.y && \n y <= bounds.y + bounds.height;\n }\n\n #emit(event, data) {\n const callbacks = this.#subscribers.get(event);\n if (callbacks) {\n for (const callback of callbacks) {\n callback(data);\n }\n }\n }\n\n // Test helper - only for testing, simulates normalized pointer events\n _testEmitPointerEvent(normalizedEvent) {\n this.#pointerSurface.handleEvent(normalizedEvent);\n this.#handlePointerInteraction(normalizedEvent);\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ContextTypes", "HitRegistry", "#areas", "id", "area", "ServiceProvider", "CanvasEvents", "#canvas", "#offscreenCanvas", "#cachedRect", "#resizeObserver", "#subscribers", "#resizeSubscribers", "#pendingMove", "#rafId", "#hasTransferredControl", "#state", "canvas", "listener", "#removeListeners", "#updateCachedRect", "#initializeListeners", "subscriber", "#emitResize", "entries", "entry", "width", "height", "#handleScroll", "#handleMove", "#handleDown", "#handleUp", "#handleDblClick", "event", "normalized", "#normalizeEvent", "#emit", "rawEvent", "type", "position", "#getPosition", "dx", "dy", "dragend", "resizeData", "isOverCanvas", "x", "y", "isWithinBounds", "deltaX", "deltaY", "deltaZ", "deltaMode", "dragDistance", "defineSurface", "usePointerSurface", "setup", "event", "hoveredArea", "activeArea", "handleEvent", "_", "normalizedEvent", "setHoveredArea", "area", "setActiveArea", "reset", "ServiceProvider", "createComputed", "destroyComputed", "addEffect", "createDefinition", "definitionType", "defineBrush", "defineLayer", "Painter", "#layers", "#canvas", "#contexts", "#assets", "#isRunning", "#frameId", "#isRendering", "#renderScheduled", "#runtimeConfig", "#timing", "#metrics", "#hitRegistry", "HitRegistry", "#pointerSurface", "usePointerSurface", "#canvasEvents", "#pointerUnsubscribe", "#resizeObserver", "#subscribers", "#wasOverCanvas", "layerDef", "layers", "layer", "fn", "canvas", "offscreenCanvas", "assets", "name", "fps", "scale", "step", "options", "width", "height", "event", "callback", "normalizedEvent", "path", "domCanvas", "ContextTypes", "type", "ctx", "CanvasEvents", "entries", "entry", "result", "#scheduleRender", "config", "#createReactor", "child", "brushConfig", "brush", "error", "#render", "renderStart", "layerStart", "key", "value", "brushStart", "brushCtx", "requiredAssets", "brushTime", "#renderBrushBounds", "layerTime", "#renderLayerBounds", "#renderDebugOverlay", "y", "lineHeight", "text", "time", "context", "computed", "unsubscribe", "#handlePointerInteraction", "#emitPointerEvents", "pointer", "#emit", "wasOverCanvas", "isOverCanvas", "x", "hitArea", "#hitTest", "#getContextForArea", "activeArea", "prevHovered", "area", "callbacks", "sorted", "a", "b", "#isPointInBounds", "bounds", "data"]
|
|
7
7
|
}
|