/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./node_modules/beholder-detection/dist/beholder-detection.js": /*!********************************************************************!*\ !*** ./node_modules/beholder-detection/dist/beholder-detection.js ***! \********************************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { eval("!function(e,t){ true?module.exports=t(__webpack_require__(/*! mathjs */ \"mathjs\")):0}(window,(function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&\"object\"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,\"default\",{enumerable:!0,value:e}),2&t&&\"string\"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,\"a\",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=\"\",n(n.s=3)}([function(t,n){t.exports=e},function(e,t,n){\"use strict\";var r=n(2),i=n.n(r)()((function(e){return e[1]}));i.push([e.i,\"#beholder-overlay {\\n top: 0;\\n left: 0;\\n position: absolute;\\n}\\n\\n#beholder-video {\\n display: none;\\n}\\n\\n.hidden {\\n display: none;\\n}\\n\\n#detection-panel {\\n width: min(90vw, 800px);\\n height: 90vh;\\n margin: 5vh calc(50vw - 0.5 * min(90vw, 800px));\\n box-sizing: border-box;\\n z-index: 999;\\n /* display: none; */\\n background: black;\\n overflow-y: scroll;\\n overflow-x: hidden;\\n color: white;\\n \\n font-family: monospace;\\n font-size: 12px;\\n position: relative;\\n}\\n\\n#detection-panel #full-video-div {\\n position: relative;\\n float: left;\\n width: 100%;\\n}\\n\\n#full-video-div canvas {\\n position: relative;\\n width: 100%;\\n}\\n\\n#full-video-div #detection-area {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 100%;\\n box-sizing: border-box;\\n border: 1px solid #00FF00;\\n}\\n\\n#detection-panel #detection-video-div {\\n position: relative;\\n float: left;\\n width: 100%;\\n}\\n\\n#detection-video-div #detection-canvas {\\n position: relative;\\n width: 100%;\\n}\\n\\n#area-buttons {\\n position: relative;\\n float: left;\\n width: 100%;\\n height: 5em;\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n}\\n\\n#area-buttons button {\\n padding: 0.5em 1em;\\n margin: 1em;\\n}\\n\\n#detection-video-div #debug-canvas {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 100%;\\n}\\n\\n#detection-panel #parameters-menu {\\n position: relative;\\n float: left;\\n clear: both;\\n margin: 1em 0 1em 0em;\\n padding: 1em 1.5em 1em 1.5em;\\n background: black;\\n}\\n\\n#detection-panel #parameters-menu .parameter-item {\\n position: relative;\\n float: left;\\n clear: both;\\n margin: 0.25em 0 0.25em 0;\\n}\\n\\n#detection-panel #parameters-menu .parameter-item span {\\n position: relative;\\n float: left;\\n width: 18em;\\n font-weight: 600;\\n color: white;\\n}\\n\\n\\n#toggle-screen {\\n position: absolute;\\n left: 10px;\\n top: 10px;\\n width: 60px;\\n height: 60px;\\n background: #000;\\n z-index: 9999;\\n color: white;\\n text-align: center;\\n font-size: 20px;\\n font-weight: 400;\\n padding: 18px 0;\\n border-radius: 30px;\\n box-sizing: border-box;\\n cursor: pointer;\\n transition: all 100ms ease-in;\\n}\\n\\n#toggle-screen:hover, #toggle-screen:active {\\n background: white;\\n color: black;\\n}\\n\\n#beholder-video {\\n display: none;\\n}\\n\",\"\"]),t.a=i},function(e,t,n){\"use strict\";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?\"@media \".concat(t[2],\" {\").concat(n,\"}\"):n})).join(\"\")},t.i=function(e,n,r){\"string\"==typeof e&&(e=[[null,e,\"\"]]);var i={};if(r)for(var a=0;a{e.forEach((e,n)=>{if(\"videoinput\"===e.kind){const r=document.createElement(\"option\");r.value=e.deviceId,r.label=e.label?e.label:n,0===n&&(r.selected=!0),t.appendChild(r)}})})}startCameraFeed(e){let t=e.videoSize,n=e.camID,i=e.rearCamera,a=e.torch;const s=r[t];return this.vStream&&this.vStream.getTracks().forEach(e=>{e.stop()}),void 0===navigator.mediaDevices.getUserMedia&&(navigator.mediaDevices.getUserMedia=function(e){var t=navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((function(n,r){t.call(navigator,e,n,r)})):Promise.reject(new Error(\"getUserMedia is not implemented in this browser\"))}),navigator.mediaDevices.getUserMedia({video:{width:s.width,height:s.height,deviceId:0===n||i?{}:{exact:n},facingMode:i?{exact:\"environment\"}:{}}}).then(e=>{if(\"srcObject\"in this.video?this.video.srcObject=e:this.video.src=window.URL.createObjectURL(e),this.video.width=e.getVideoTracks()[0].getSettings().width,this.video.height=e.getVideoTracks()[0].getSettings().height,this.video.play(),this.vStream=e,console.log(\"BEHOLDER: new video stream established\"),a)if(ImageCapture){const t=e.getVideoTracks()[0];new ImageCapture(t).getPhotoCapabilities().then(()=>{void 0!==t.getCapabilities().torch&&t.applyConstraints({advanced:[{torch:a}]})})}else console.warn(\"**BEHOLDER WARNING** Flahslight/Torch functionality is not supported on this device or platform\")})}},a=a||{};a.Image=function(e,t,n){this.width=e||0,this.height=t||0,this.data=n||[]},a.grayscale=function(e,t){for(var n=e.data,r=t.data,i=n.length,a=0,s=0;au&&(u=n,o=r)}return o},a.stackBoxBlurMult=[1,171,205,293,57,373,79,137,241,27,391,357,41,19,283,265],a.stackBoxBlurShift=[0,9,10,11,9,12,10,11,12,9,13,13,10,9,13,13],a.BlurStack=function(){this.color=0,this.next=null},a.stackBoxBlur=function(e,t,n){var r,i,s,o,c,d,h,l,u,p,m=e.data,y=t.data,x=e.height,v=e.width,g=x-1,f=v-1,b=n+n+1,_=n+1,w=a.stackBoxBlurMult[n],S=a.stackBoxBlurShift[n];for(r=i=new a.BlurStack,p=1;p>>S,h=d+((h=l+_)>>S,h=l+((h=u+_)=1&&0===n[i+1]&&(d=!0),(c||d)&&(++o,m.push(a.borderFollowing(n,i,o,{x:l,y:h},d,r))));return m},a.borderFollowing=function(e,t,n,r,i,s){var o,c,d,h,l,u=[];u.hole=i,h=l=i?0:4;do{if(0!==e[o=t+s[h=h-1&7]])break}while(h!==l);if(h===l)e[t]=-n,u.push({x:r.x,y:r.y});else for(c=t,4^h;;){l=h;do{d=c+s[++h]}while(0===e[d]);if((h&=7)-1>>>0>>0?e[c]=-n:1===e[c]&&(e[c]=n),u.push({x:r.x,y:r.y}),h,r.x+=a.neighborhood[h][0],r.y+=a.neighborhood[h][1],d===t&&c===o)break;c=d,h=h+4&7}return u},a.neighborhood=[[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1],[0,1],[1,1]],a.neighborhoodDeltas=function(e){for(var t=[],n=a.neighborhood.length,r=0;rs&&(s=a,m.start_index=l);for(s<=t?y.push({x:r.x,y:r.y}):(p.start_index=u,p.end_index=m.start_index+=p.start_index,m.start_index-=m.start_index>=v?v:0,m.end_index=p.start_index,m.end_indexs&&(s=a,m.start_index=h);o=s*s<=t*(c*c+d*d)}o?y.push({x:r.x,y:r.y}):(m.end_index=p.end_index,p.end_index=m.start_index,x.push({start_index:m.start_index,end_index:m.end_index}),x.push({start_index:p.start_index,end_index:p.end_index}))}return y},a.warp=function(e,t,n,r){var i,s,o,c,d,h,l,u,p,m,y,x,v,g,f,b,_,w,S,M,k,P,E=e.data,A=t.data,D=e.width,O=e.height,R=0;for(v=(x=a.getPerspectiveTransform(n,r-1))[8],g=x[2],f=x[5],k=0;k>>0)===D-1?i:i+1,c=1-(o=S-i),l=1-(h=(M=(w+=x[3])/b)-(d=M>>>0)),u=p=d*D,m=y=(d===O-1?d:d+1)*D,A[R++]=l*(c*E[u+i]+o*E[p+s])+h*(c*E[m+i]+o*E[y+s])&255;return t.width=r,t.height=r,t},a.getPerspectiveTransform=function(e,t){var n=a.square2quad(e);return n[0]/=t,n[1]/=t,n[3]/=t,n[4]/=t,n[6]/=t,n[7]/=t,n},a.square2quad=function(e){var t,n,r,i,a,s,o,c=[];return t=e[0].x-e[1].x+e[2].x-e[3].x,n=e[0].y-e[1].y+e[2].y-e[3].y,0===t&&0===n?(c[0]=e[1].x-e[0].x,c[1]=e[2].x-e[1].x,c[2]=e[0].x,c[3]=e[1].y-e[0].y,c[4]=e[2].y-e[1].y,c[5]=e[0].y,c[6]=0,c[7]=0,c[8]=1):(r=e[1].x-e[2].x,i=e[3].x-e[2].x,a=e[1].y-e[2].y,o=r*(s=e[3].y-e[2].y)-i*a,c[6]=(t*s-i*n)/o,c[7]=(r*n-t*a)/o,c[8]=1,c[0]=e[1].x-e[0].x+c[6]*e[1].x,c[1]=e[3].x-e[0].x+c[7]*e[3].x,c[2]=e[0].x,c[3]=e[1].y-e[0].y+c[6]*e[1].y,c[4]=e[3].y-e[0].y+c[7]*e[3].y,c[5]=e[0].y),c},a.isContourConvex=function(e){var t,n,r,i,a,s,o,c,d=0,h=!0,l=e.length,u=0,p=0;for(n=e[l-1],a=(t=e[0]).x-n.x,s=t.y-n.y;u(r=o*s)?1:i{l=c(c({},l),e)},h.Marker=(e,t)=>{const n=(t[0].y-t[2].y)/(t[0].x-t[2].x),r=(t[1].y-t[3].y)/(t[1].x-t[3].x),i={x:0,y:0};var a,s,o;return i.x=function(e,t,n,r){return(n.y-r.y+t*r.x-e*n.x)/(t-e)}(n,r,t[0],t[1]),i.y=(a=t[0],s=n,o=i.x,s*(o-a.x)+a.y),{id:e,corners:t,center:i}},h.Detector=function(){this.grey=new s.Image,this.thres=new s.Image,this.homography=new s.Image,this.binary=[],this.contours=[],this.polys=[],this.candidates=[]},h.Detector.prototype.detect=function(e,t){return s.grayscale(e,this.grey),s.adaptiveThreshold(this.grey,this.thres,2,7),this.contours=s.findContours(this.thres,this.binary),this.candidates=this.findCandidates(this.contours,e.width*t.minMarkerPerimeter,e.width*t.maxMarkerPerimeter,.05,10),this.candidates=this.clockwiseCorners(this.candidates),this.candidates=this.notTooNear(this.candidates,t.minMarkerDistance),this.findMarkers(this.grey,this.candidates,t.sizeAfterPerspectiveRemoval)},h.Detector.prototype.findCandidates=function(e,t,n,r,i){var a,o,c,d=[],h=e.length;for(this.polys=[],c=0;c=t&&a.length<=n&&(o=s.approxPolyDP(a,a.length*r),this.polys.push(o),4===o.length&&s.isContourConvex(o)&&s.minEdgeLength(o)>=i&&d.push(o));return d},h.Detector.prototype.clockwiseCorners=function(e){var t,n,r,i,a,s=e.length;for(a=0;a>>0,d=c*c>>1,l=[],u=[],p=[];for(a=0;a<7;++a)for(i=0===a||6===a?1:6,o=0;o<7;o+=i)if(n={x:o*c,y:a*c,width:c,height:c},s.countNonZero(e,n)>d)return null;for(a=0;a<5;++a)for(l[a]=[],o=0;o<5;++o)n={x:(o+1)*c,y:(a+1)*c,width:c,height:c},l[a][o]=s.countNonZero(e,n)>d?1:0;for(u[0]=l,p[0]=this.hammingDistance(u[0]),r={first:p[0],second:0},a=1;a<4;++a)u[a]=this.rotate(u[a-1]),p[a]=this.hammingDistance(u[a]),p[a]20&&this.canvas.width!==this.video.width*r&&(this.canvas.width=this.video.width*r,this.canvas.height=this.video.height*i),this.ctx.filter=`contrast(${(100+Math.floor(t.contrast))/100})\\n brightness(${(100+Math.floor(t.brightness))/100})\\n grayscale(${Math.floor(t.grayscale)/100})`,t.flip?(this.ctx.save(),this.ctx.translate(this.canvas.width,0),this.ctx.scale(-1,1),this.ctx.drawImage(this.video,n.area.start.x*this.video.width,n.area.start.y*this.video.height,this.canvas.width,this.canvas.height,0,0,this.canvas.width,this.canvas.height),this.ctx.restore()):this.ctx.drawImage(this.video,n.area.start.x*this.video.width,n.area.start.y*this.video.height,this.canvas.width,this.canvas.height,0,0,this.canvas.width,this.canvas.height);let a=this.ctx.getImageData(0,0,this.canvas.width,this.canvas.height);return[this.detector.detect(a,n),e,this.canvas.width,this.canvas.height]}return[[],e,this.canvas.width,this.canvas.height]}};class m{static sub(e,t){return new m(t.x-e.x,t.y-e.y)}static fromAngle(e){return new m(Math.cos(e),Math.sin(e))}static add(e,t){return new m(t.x+e.x,t.y+e.y)}static addScalar(e,t,n){const r=e.x+t.x*n,i=e.y+t.y*n;return new m(r,i)}static mag(e){return Math.sqrt(e.x*e.x+e.y*e.y)}static angleBetween(e,t){return Math.atan2(e.x*t.y-e.y*t.x,e.x*t.x+e.y*t.y)}static rotate(e,t){const n=e.x*Math.cos(t)-e.y*Math.sin(t),r=e.x*Math.sin(t)+e.y*Math.cos(t);return new m(n,r)}static scale(e,t){return new m(e.x*t,e.y*t)}static dist(e,t){return new m(t.x-e.x,t.y-e.y).mag()}static dist2(e,t){return new m(t.x-e.x,t.y-e.y).mag2()}static normalize(e){const t=e.mag();return new m(e.x/t,e.y/t)}static copy(e){return new m(e.x,e.y)}constructor(e,t){this.x=e,this.y=t}clone(){return new m(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}set(e,t){return this.x=e,this.y=t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}scale(e){return this.x*=e,this.y*=e,this}mag(){return Math.sqrt(this.x*this.x+this.y*this.y)}mag2(){return this.x*this.x+this.y*this.y}dist(e){return m.sub(this,e).mag()}dist2(e){return m.sub(this,e).mag2()}normalize(){const e=this.mag();return this.x/=e,this.y/=e,this}getAngle(){return Math.atan2(this.y,this.x)}rotate(e){const t=this.x*Math.cos(e)-this.y*Math.sin(e),n=this.x*Math.sin(e)+this.y*Math.cos(e);return this.x=t,this.y=n,this}dot(e){return this.x*e.x+this.y*e.y}angleBetween(e){return Math.atan2(this.x*e.y-this.y*e.x,this.x*e.x+this.y*e.y)}}const y=new m(1,0);var x=class{constructor(e){this.timeout=50,this.timestamp=this.timeout,this.present=!1,this.center=new m(0,0),this.position=new m(0,0),this.rawPosition=new m(0,0),this.deltaPosition=new m(0,0),this.corners=[],this.rawRotation=0,this.rotation=0,this.deltaRotation=0,this.scale=29/640,this.enable3D=!1,this.avgSideLength=0,this.deltaAvgSideLength=0,this.id=e,this.positionSmoothing=0,this.rotationSmoothing=0}setScale(e,t){this.scale=e/t}update(e){this.timestamp=0,this.present=!0,this.deltaPosition.copy(this.position);let t=this.center.clone();this.center.x=this.center.x*this.positionSmoothing+e.center.x*(1-this.positionSmoothing),this.center.y=this.center.y*this.positionSmoothing+e.center.y*(1-this.positionSmoothing),this.position.copy(this.center),this.rawPosition.copy(e.center),this.deltaPosition.sub(this.position).scale(-1),(isNaN(this.center.x)||isNaN(this.center.y))&&(this.center.set(t.x,t.y),this.position.set(t.x,t.y),this.deltaPosition.set(0,0),this.rawP,console.warn(\"BEHOLDER: Detection Broke Momentarily\")),this.corners=e.corners.map(e=>e),this.rawRotation=y.angleBetween(m.sub(this.corners[0],this.corners[1]));const n=m.fromAngle(this.rotation),r=m.fromAngle(this.rawRotation),i=new m(n.x*this.rotationSmoothing+(1*r.x-this.rotationSmoothing),n.y*this.rotationSmoothing+(1*r.y-this.rotationSmoothing));this.rotation=i.getAngle(),this.deltaRotation=m.angleBetween(n,i);const a=this.corners.map((e,t,n)=>{const r=e.x-n[(t+1)%n.length].x,i=e.y-n[(t+1)%n.length].y;return Math.sqrt(r*r+i*i)});this.deltaAvgSideLength=-this.avgSideLength,this.avgSideLength=(a[0]+a[1]+a[2]+a[3])/4,this.deltaAvgSideLength+=this.avgSideLength,this.enable3D&&(this.center.z=this.avgPerim/this.scale)}updatePresence(e){this.timestamp+=e>30?30:e,this.present=!(this.timestamp>=this.timeout)}},v=n(0);var g=class{constructor(e,t){this.markerA=e,this.markerB=t}get isPresent(){return this.markerA.present&&this.markerB.present}get angleBetween(){return this.markerA.rotation-this.markerB.rotation}get distance(){return m.sub(this.markerA.center,this.markerB.center).mag()}getRelativePosition(e){if(this.isPresent()){const t=[{x:-e/2,y:-e/2},{x:e/2,y:-e/2},{x:e/2,y:e/2},{x:-e/2,y:e/2}],n=function(e,t,n,r,i,a,s,o){const c=v.matrix([[i.x,i.y,1,0,0,0,-e.x*i.x,-e.x*i.y],[0,0,0,i.x,i.y,1,-e.y*i.x,-e.y*i.y],[a.x,a.y,1,0,0,0,-t.x*a.x,-t.x*a.y],[0,0,0,a.x,a.y,1,-t.y*a.x,-t.y*a.y],[s.x,s.y,1,0,0,0,-n.x*s.x,-n.x*s.y],[0,0,0,s.x,s.y,1,-n.y*s.x,-n.y*s.y],[o.x,o.y,1,0,0,0,-r.x*o.x,-r.x*o.y],[0,0,0,o.x,o.y,1,-r.y*o.x,-r.y*o.y]]),d=v.matrix([[e.x],[e.y],[t.x],[t.y],[n.x],[n.y],[r.x],[r.y]]),h=v.lusolve(c,d);return v.matrix([[v.subset(h,v.index(0,0)),v.subset(h,v.index(1,0)),v.subset(h,v.index(2,0))],[v.subset(h,v.index(3,0)),v.subset(h,v.index(4,0)),v.subset(h,v.index(5,0))],[v.subset(h,v.index(6,0)),v.subset(h,v.index(7,0)),1]])}(this.markerA.corners[0],this.markerA.corners[1],this.markerA.corners[2],this.markerA.corners[3],t[0],t[1],t[2],t[3]),r=v.inv(n),i=e=>function(e,t){const n=v.matrix([[t.x],[t.y],[1]]),r=v.multiply(e,n);return{x:v.subset(r,v.index(0,0))/v.subset(r,v.index(2,0)),y:v.subset(r,v.index(1,0))/v.subset(r,v.index(2,0))}}(r,e),a=i(this.markerA.center),s=i(this.markerB.center),o=i(this.markerA.corners[0]),c=i(this.markerA.corners[1]),d=i(this.markerB.corners[0]),h=i(this.markerB.corners[1]),l=m.sub(a,s),u=m.sub(o,c);return{distance:m.mag(l),heading:m.angleBetween(u,l),rotation:m.angleBetween(u,m.sub(d,h))}}return{distance:void 0,heading:void 0,rotation:void 0}}},f=n(1);function b(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function _(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n{const e=Date.now(),t=e-$;$=e;(e=>{const t=S(e,2),n=t[0],r=t[1];I.width!==L.width&&(I.width=L.width,I.height=L.height),A||(T.drawImage(L,0,0,I.width,I.height),T.strokeStyle=\"#00FF00\",T.beginPath(),T.moveTo(I.width*F.detection_params.area.start.x,I.height*F.detection_params.area.start.y),T.lineTo(I.width*F.detection_params.area.end.x,I.height*F.detection_params.area.start.y),T.lineTo(I.width*F.detection_params.area.end.x,I.height*F.detection_params.area.end.y),T.lineTo(I.width*F.detection_params.area.start.x,I.height*F.detection_params.area.end.y),T.closePath(),T.stroke()),C.width=j.width,C.height=j.height,A||B.clearRect(0,0,C.width,C.height),n.forEach(e=>{const t=D.find(t=>t.id===e.id);if(void 0===t)return;if(t.update(e),A)return;const n=t.center,r=t.corners,i=t.rotation;B.strokeStyle=\"#FF00AA\",B.beginPath(),r.forEach((e,t)=>{B.moveTo(e.x,e.y);let n=r[(t+1)%r.length];B.lineTo(n.x,n.y)}),B.stroke(),B.closePath(),B.strokeStyle=\"blue\",B.strokeRect(r[0].x-2,r[0].y-2,4,4),B.strokeStyle=\"#FF00AA\",B.strokeRect(n.x-1,n.y-1,2,2),B.font=\"12px monospace\",B.textAlign=\"center\",B.fillStyle=\"#FF55AA\",B.fillText(\"ID=\"+t.id,n.x,n.y-7),B.fillText(i.toFixed(2),n.x,n.y+15)}),D.forEach(e=>e.updatePresence(r))})(R.detect(t,F.feed_params,F.detection_params))},N=()=>D,H=e=>D.find(t=>t.id===e),G=(e,t)=>new g(D[e],D[t]);t.default={init:(e,t,n)=>{if(n)n.length<=0&&console.warn(\"BEHOLDER WARNING: your provided list of markers is empty, no markers will be tracked\"),n.forEach(e=>D.push(new x(e)));else for(let e=0;e<100;e++)D.push(new x(e));const r=document.querySelector(e);F=k,t&&(t.camera_params&&(F.camera_params=_(_({},F.camera_params),t.camera_params)),t.detection_params&&(F.detection_params=_(_({},F.detection_params),t.detection_params)),t.feed_params&&(F.feed_params=_(_({},F.feed_params),t.feed_params)),t.overlay_params&&(F.overlay_params=_(_({},F.overlay_params),t.overlay_params))),r.innerHTML=((e,t)=>`\\n
\\n \\n\\n
\\n ☰\\n
\\n\\n
\\n \\n
\\n \\n \\n
\\n \\n
\\n \\n
\\n \\n
\\n \\n
\\n \\n \\n
\\n\\n
\\n
\\n Camera Feed ID\\n \\n
\\n\\n
\\n Video Size\\n \\n
\\n\\n
\\n Min Marker Distance\\n \\n
\\n\\n
\\n Min Marker Perimeter\\n \\n
\\n
\\n Max Marker Perimeter\\n \\n
\\n\\n
\\n Size After Perspective Removal\\n \\n
\\n\\n
\\n Contrast\\n \\n
\\n\\n
\\n Brightness\\n \\n
\\n\\n
\\n Grayscale\\n \\n
\\n\\n
\\n Torch\\n \\n
\\n\\n
\\n Mirror Camera\\n \\n
\\n
\\n
\\n
`)(F,f.a),L=r.querySelector(\"#beholder-video\"),L.setAttribute(\"playsinline\",\"playsinline\"),document.querySelector(\"#set-area-instructions\").innerHTML=`\\n start=x:${F.detection_params.area.start.x.toFixed(2)},y:${F.detection_params.area.start.y.toFixed(2)}   \\n end=x:${F.detection_params.area.end.x.toFixed(2)},y:${F.detection_params.area.end.y.toFixed(2)}\\n `,r.querySelector(\"#toggle-screen\").addEventListener(\"click\",()=>{A?r.querySelector(\"#detection-panel\").classList.remove(\"hidden\"):r.querySelector(\"#detection-panel\").classList.add(\"hidden\"),A=!A}),A=F.overlay_params.hide,A&&r.querySelector(\"#detection-panel\").classList.add(\"hidden\"),r.querySelector(\"#set-area\").addEventListener(\"click\",()=>{P=!0,E=[],document.querySelector(\"#set-area-instructions\").innerHTML=\"Select top-left corner.\"}),r.querySelector(\"#detection-canvas-overlay\").addEventListener(\"click\",e=>{P&&(E.push({x:e.offsetX/e.target.clientWidth,y:e.offsetY/e.target.clientHeight}),E.length>1?(P=!1,F.detection_params.area={start:{x:Math.min(E[0].x,E[1].x),y:Math.min(E[0].y,E[1].y)},end:{x:Math.max(E[0].x,E[1].x),y:Math.max(E[0].y,E[1].y)}},document.querySelector(\"#set-area-instructions\").innerHTML=`\\n start=x:${F.detection_params.area.start.x.toFixed(2)},y:${F.detection_params.area.start.y.toFixed(2)}   \\n end=x:${F.detection_params.area.end.x.toFixed(2)},y:${F.detection_params.area.end.y.toFixed(2)}\\n `):1===E.length&&(document.querySelector(\"#set-area-instructions\").innerHTML=\"Select bottom-right corner.\"))}),r.querySelector(\"#clear-area\").addEventListener(\"click\",()=>{F.detection_params.area={start:{x:0,y:0},end:{x:1,y:1}},document.querySelector(\"#set-area-instructions\").innerHTML=`\\n start=x:${F.detection_params.area.start.x.toFixed(2)},y:${F.detection_params.area.start.y.toFixed(2)}   \\n end=x:${F.detection_params.area.end.x.toFixed(2)},y:${F.detection_params.area.end.y.toFixed(2)}\\n `}),r.querySelector(\"#camera_param_id\").addEventListener(\"change\",e=>{F.camera_params.camID=e.target.value,O.startCameraFeed(F.camera_params)}),r.querySelector(\"#camera_param_videoSize\").addEventListener(\"change\",e=>{F.camera_params.videoSize=e.target.value,O.startCameraFeed(F.camera_params)}),r.querySelector(\"#detection_params-minMarkerDistance\").addEventListener(\"change\",e=>F.detection_params.minMarkerDistance=e.target.value),r.querySelector(\"#detection_params-minMarkerPerimeter\").addEventListener(\"change\",e=>F.detection_params.minMarkerPerimeter=e.target.value),r.querySelector(\"#detection_params-maxMarkerPerimeter\").addEventListener(\"change\",e=>F.detection_params.maxMarkerPerimeter=e.target.value),r.querySelector(\"#detection_params-sizeAfterPerspectiveRemoval\").addEventListener(\"change\",e=>F.detection_params.sizeAfterPerspectiveRemoval=e.target.value),r.querySelector(\"#detection_params-contrast\").addEventListener(\"change\",e=>F.feed_params.contrast=e.target.value),r.querySelector(\"#detection_params-brightness\").addEventListener(\"change\",e=>F.feed_params.brightness=e.target.value),r.querySelector(\"#detection_params-grayscale\").addEventListener(\"change\",e=>F.feed_params.grayscale=e.target.value),r.querySelector(\"#detection_params-flip\").addEventListener(\"change\",e=>F.feed_params.flip=e.target.checked),r.querySelector(\"#detection_params-torch\").addEventListener(\"change\",e=>{F.camera_params.torch=e.target.checked,O.startCameraFeed(F.camera_params)}),O=new i(r.querySelector(\"#beholder-video\")),R=new p(r.querySelector(\"#detection-canvas\"),r.querySelector(\"#beholder-video\")),I=r.querySelector(\"#detection-canvas-overlay\"),T=I.getContext(\"2d\"),j=r.querySelector(\"#detection-canvas\"),q=j.getContext(\"2d\"),C=r.querySelector(\"#debug-canvas\"),B=C.getContext(\"2d\"),O.startCameraFeed(F.camera_params)},update:z,getMarker:H,getMarkerPair:G,getAllMarkers:N,hide:()=>{document.querySelector(\"#detection-panel\").classList.add(\"hidden\")},show:()=>{document.querySelector(\"#detection-panel\").classList.remove(\"hidden\")},getVideo:()=>O.video}}])}));\n\n//# sourceURL=webpack://p5.beholder/./node_modules/beholder-detection/dist/beholder-detection.js?"); /***/ }), /***/ "./src/p5.beholder.js": /*!****************************!*\ !*** ./src/p5.beholder.js ***! \****************************/ /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { eval("/**\r\n * The main class of the library. It should have a single instance per sketch, which is then prepared at the `setup()` function.\r\n */\r\nclass P5Beholder {\r\n /**\r\n * Creates an instance of P5Beholder. It is automatically called during p5 loading. Initialization of the library is only compelte after `prepare()` is called on sketch setup (see {@link P5Beholder#prepare}).\r\n * @class\r\n * @private\r\n */\r\n constructor() {\r\n // Requires the Beholder system\r\n this._bh = (__webpack_require__(/*! beholder-detection */ \"./node_modules/beholder-detection/dist/beholder-detection.js\")[\"default\"]);\r\n }\r\n\r\n /**\r\n * Sets-up the p5beholder and sketch integration. Adds Beholder to the HTML page at the and initializes it with proper config file.\r\n * **Important**: must be called once on `setup()`.\r\n * The config file must use {@link P5Beholder._defaultConfig} as a base.\r\n *\r\n * @param {*} [config=P5Beholder._defaultConfig] - Controls how Beholder detection will run.\r\n * @param {string} [querySelector=\"#beholder_root\"] - Picks an HTML element to be the parent of the Beholder system elements (GUI, etc).\r\n * @memberof P5Beholder\r\n */\r\n prepare(\r\n config = P5Beholder._defaultConfig,\r\n querySelector = \"#beholder_root\"\r\n ) {\r\n // Stores the configuration\r\n this._config = config;\r\n this._rootQuery = querySelector;\r\n // Sets up Beholder in the document DOM.\r\n if (this._rootQuery == null || this._rootQuery == \"#beholder_root\") {\r\n let newDiv = document.createElement(\"div\");\r\n newDiv.setAttribute(\"id\", \"beholder_root\");\r\n document.querySelector(\"body\").appendChild(newDiv);\r\n }\r\n // Start the detection system\r\n this._bh.init(this._rootQuery, this._config);\r\n }\r\n\r\n /**\r\n *If a marker is present, the mouse button 0 goes down and, when undetected, goes up. The position of the resulting click can be defined, in pixels.\r\n * @param {number!} [markerId=0] - The id of the marker to check presence.\r\n * @param {number} [clickX=0] - The X position where of the resulting click.\r\n * @param {number} [clickY=0] - The Y position where of the resulting click.\r\n * @memberof P5Beholder\r\n */\r\n markerPresenceToMouseClick(markerId = 0, clickX = 0, clickY = 0) {\r\n let pos = createVector(clickX, clickY);\r\n\r\n const downEvent = new MouseEvent(\"mousedown\", {\r\n bubbles: true,\r\n cancelable: true,\r\n button: 0,\r\n clientX: pos.x,\r\n clientY: pos.y,\r\n });\r\n\r\n const upEvent = new MouseEvent(\"mouseup\", {\r\n bubbles: true,\r\n cancelable: true,\r\n button: 0,\r\n clientX: pos.x,\r\n clientY: pos.y,\r\n });\r\n\r\n this._forwardEventForId(markerId, \"markerdetected\", downEvent);\r\n this._forwardEventForId(markerId, \"markerundetected\", upEvent);\r\n }\r\n\r\n /**\r\n * Quick converter between marker presence and keyboard input. When a marker is detected, fires the `keydown` event. Whe the marker is undetected, fires the `keyup` event.\r\n * @param {number} [markerId=0] - The id of the marker to check.\r\n * @param {number} [pKeyCode=32] - The number with the keyboard code (from `event.key`).\r\n * @memberof P5Beholder\r\n */\r\n markerPresenceToKey(markerId = 0, pKeyCode = \"Space\") {\r\n const downEvent = new KeyboardEvent(\"keydown\", {\r\n bubbles: true,\r\n cancelable: true,\r\n keyCode: pKeyCode,\r\n which: pKeyCode,\r\n });\r\n\r\n const upEvent = new KeyboardEvent(\"keyup\", {\r\n bubbles: true,\r\n cancelable: true,\r\n keyCode: pKeyCode,\r\n which: pKeyCode,\r\n });\r\n\r\n this._forwardEventForId(markerId, \"markerdetected\", downEvent);\r\n this._forwardEventForId(markerId, \"markerundetected\", upEvent);\r\n }\r\n\r\n /**\r\n * Changes the timeout value for all markers.\r\n * @param {number} [timeout=50] - New time in milliseconds.\r\n * @memberof P5Beholder\r\n */\r\n setMarkersTimeout(timeout = 50) {\r\n for (let i = 0; i < this._bh.getAllMarkers().length; i++) {\r\n const item = this._bh.getMarker(i);\r\n item.timeout = timeout;\r\n }\r\n }\r\n\r\n /**\r\n * Debug functionality for drawing a marker on the canvas.\r\n * @param {number} [markerId=0] - The id of the marker to draw.\r\n * @memberof P5Beholder\r\n */\r\n debugDrawMarker(markerId = 0) {\r\n let marker = this._bh.getMarker(markerId);\r\n if (marker.present == false) return;\r\n push();\r\n fill(255, 0, 0);\r\n stroke(0, 0, 0);\r\n beginShape();\r\n vertex(\r\n this.cameraToCanvasVector(marker.corners[0]).x,\r\n this.cameraToCanvasVector(marker.corners[0]).y\r\n );\r\n vertex(\r\n this.cameraToCanvasVector(marker.corners[1]).x,\r\n this.cameraToCanvasVector(marker.corners[1]).y\r\n );\r\n vertex(\r\n this.cameraToCanvasVector(marker.corners[2]).x,\r\n this.cameraToCanvasVector(marker.corners[2]).y\r\n );\r\n vertex(\r\n this.cameraToCanvasVector(marker.corners[3]).x,\r\n this.cameraToCanvasVector(marker.corners[3]).y\r\n );\r\n endShape(CLOSE);\r\n fill(0, 255, 0);\r\n let center = this.cameraToCanvasXY(marker.center.x, marker.center.y);\r\n ellipse(center.x, center.y, 10, 10);\r\n textSize(12);\r\n text(marker.rotation, center.x, center.y + 30, 80, 40);\r\n pop();\r\n }\r\n\r\n /**\r\n * Converts X position from camera to canvas.\r\n * @param {number} x - Camera X position.\r\n * @return {number} - Canvas X position.\r\n * @memberof P5Beholder\r\n */\r\n cameraToCanvasX(x) {\r\n return map(x, 0, this.cameraWidth, 0, width);\r\n }\r\n\r\n /**\r\n * Converts Y position from camera to canvas.\r\n * @param {number} y - Camera Y position.\r\n * @return {number} - Canvas Y position.\r\n * @memberof P5Beholder\r\n */\r\n cameraToCanvasY(y) {\r\n return map(y, 0, this.cameraHeight, 0, height);\r\n }\r\n\r\n /**\r\n * Converts a position from camera to canvas using a p5.Vector.\r\n * @param {p5.Vector} coord - p5.Vector with camera position.\r\n * @return {p5.Vector} - p5.Vector with canvas position.\r\n * @memberof P5Beholder\r\n */\r\n cameraToCanvasVector(coord) {\r\n return createVector(\r\n this.cameraToCanvasX(coord.x),\r\n this.cameraToCanvasY(coord.y)\r\n );\r\n }\r\n\r\n /**\r\n * Converts a position from camera to canvas positions using 2 numbers.\r\n * @param {number} pX - Camera-relative X value.\r\n * @param {number} pY - Camera-relative Y value.\r\n * @return {p5.Vector} - p5.Vector with canvas position.\r\n * @memberof P5Beholder\r\n */\r\n cameraToCanvasXY(pX, pY) {\r\n return createVector(this.cameraToCanvasX(pX), this.cameraToCanvasY(pY));\r\n }\r\n\r\n /**\r\n * Checks if a marker's rotation is within a specified range from a target angle. Useful for detecting things like a crank or spinner with a marker at its center.\r\n * All angles are in radians.\r\n * @param {number} markerId - The id of the marker to be checked.\r\n * @param {number} detectionTargetAngle - The target angle.\r\n * @param {number} angleRange - The range centers around the target angle. Should be less than PI.\r\n * @return {true|false}\r\n * @memberof P5Beholder\r\n */\r\n markerRotationInRange(markerId, detectionTargetAngle, angleRange) {\r\n const m = this._bh.getMarker(markerId);\r\n const currentAngle = m.present ? m.rotation : 0;\r\n return this.angleInRange(currentAngle, detectionTargetAngle, angleRange);\r\n }\r\n\r\n /**\r\n * Checks if the current angle is within a defined range from a target angle. All angles are in radians.\r\n * @param {number} currentAngle - Value to be checked.\r\n * @param {number} detectionTargetAngle - The target angle.\r\n * @param {number} angleRange - The range centers around the target angle. Should be less than PI.\r\n * @return {true|false}\r\n * @memberof P5Beholder\r\n */\r\n angleInRange(currentAngle, detectionTargetAngle, angleRange) {\r\n const av = p5.Vector.fromAngle(currentAngle, 1);\r\n const dv = p5.Vector.fromAngle(detectionTargetAngle, 1);\r\n const da = dv.angleBetween(av);\r\n return abs(da) <= angleRange / 2;\r\n }\r\n\r\n /// Wrappers to Beholder API\r\n\r\n getMarker(markerId) {\r\n return this._bh.getMarker(markerId);\r\n }\r\n\r\n /// PRIVATE METHODS AND PROPERTIES\r\n\r\n /**\r\n * An object holding camera, detection, feed and overlay default options for the Beholder detection system.\r\n * @static\r\n * @memberof P5Beholder\r\n * @example\r\n * // Structure of the default configuration object\r\n{\r\n camera_params: {\r\n videoSize: 0, // The video size values map to the following [320 x 240, 640 x 480, 1280 x 720, 1920 x 1080]\r\n rearCamera: false, // Boolean value for defaulting to the rear facing camera. Only works on mobile\r\n torch: false, // Boolean value for if torch/flashlight is on. Only works for rear facing mobile cameras. Can only be set from init\r\n },\r\n detection_params: {\r\n minMarkerDistance: 10,\r\n minMarkerPerimeter: 0.2,\r\n maxMarkerPerimeter: 0.8,\r\n sizeAfterPerspectiveRemoval: 49,\r\n },\r\n feed_params: {\r\n contrast: 0,\r\n brightness: 0,\r\n grayscale: 0,\r\n flip: false,\r\n },\r\n overlay_params: {\r\n present: true, // Determines if the Beholder overlay will display or be invisible entirely via display: none\r\n hide: true, // Determines if the overlay should be hidden on the left of the screen or visible\r\n },\r\n}\r\n */\r\n static _defaultConfig = {\r\n camera_params: {\r\n videoSize: 0, // The video size values map to the following [320 x 240, 640 x 480, 1280 x 720, 1920 x 1080]\r\n rearCamera: false, // Boolean value for defaulting to the rear facing camera. Only works on mobile\r\n torch: false, // Boolean value for if torch/flashlight is on. Only works for rear facing mobile cameras. Can only be set from init\r\n },\r\n detection_params: {\r\n minMarkerDistance: 10,\r\n minMarkerPerimeter: 0.2,\r\n maxMarkerPerimeter: 0.8,\r\n sizeAfterPerspectiveRemoval: 49,\r\n },\r\n feed_params: {\r\n contrast: 0,\r\n brightness: 0,\r\n grayscale: 0,\r\n flip: false,\r\n },\r\n overlay_params: {\r\n present: true, // Determines if the Beholder overlay will display or be invisible entirely via display: none\r\n hide: true, // Determines if the overlay should be hidden on the left of the screen or visible\r\n },\r\n };\r\n\r\n _forwardEventForId(markerId, eventName, destEvt) {\r\n window.addEventListener(eventName, (srcEvt) => {\r\n if (srcEvt.detail.id == markerId) {\r\n window.dispatchEvent(destEvt);\r\n }\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Global instance of the P5Beholder class.\r\n * @global\r\n */\r\n__webpack_require__.g.p5beholder = new P5Beholder();\r\n\r\n// Register preupdate on p5 flow. Thsi needs to be outside the class because of p5 way of dealing with registering methods (i.e. it loses the `this` binding). So, the preUpdate changes things on the global instance just created. Not very nice, but works.\r\n__webpack_require__.g.p5.prototype.registerMethod(\"pre\", _beholderPreUpdate);\r\n\r\nfunction _beholderPreUpdate() {\r\n const p5b = __webpack_require__.g.p5beholder;\r\n p5b.cameraWidth = p5b._bh.getVideo().width;\r\n p5b.cameraHeight = p5b._bh.getVideo().height;\r\n\r\n let prevPresence = p5b._bh.getAllMarkers().map((m) => m.present);\r\n\r\n p5b._bh.update();\r\n\r\n let currPresence = p5b._bh.getAllMarkers().map((m) => m.present);\r\n\r\n if (frameCount == 1) {\r\n prevPresence = [false];\r\n currPresence = [false];\r\n }\r\n\r\n prevPresence.forEach((prevState, index) => {\r\n const currState = currPresence[index];\r\n\r\n if (prevState == false && currState == true) {\r\n let evDetected = new CustomEvent(\"markerdetected\", {\r\n detail: { id: index, marker: p5b._bh.getMarker(index) },\r\n });\r\n window.dispatchEvent(evDetected);\r\n return;\r\n }\r\n if (prevState == true && currState == false) {\r\n let evUndetected = new CustomEvent(\"markerundetected\", {\r\n detail: { id: index, marker: p5b._bh.getMarker(index) },\r\n });\r\n window.dispatchEvent(evUndetected);\r\n return;\r\n }\r\n });\r\n}\r\n\n\n//# sourceURL=webpack://p5.beholder/./src/p5.beholder.js?"); /***/ }), /***/ "mathjs": /*!******************************************************************************************!*\ !*** external {"commonjs":"mathjs","commonjs2":"mathjs","amd":"mathjs","root":"mathjs"} ***! \******************************************************************************************/ /***/ ((module) => { "use strict"; module.exports = undefined; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/global */ /******/ (() => { /******/ __webpack_require__.g = (function() { /******/ if (typeof globalThis === 'object') return globalThis; /******/ try { /******/ return this || new Function('return this')(); /******/ } catch (e) { /******/ if (typeof window === 'object') return window; /******/ } /******/ })(); /******/ })(); /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module can't be inlined because the eval devtool is used. /******/ var __webpack_exports__ = __webpack_require__("./src/p5.beholder.js"); /******/ /******/ })() ;