Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

this.dispatchEvent is not a function on ArToolkitContext Init / Update #264

Open
leoncvlt opened this issue May 4, 2021 · 5 comments
Open
Assignees
Labels
bug Something isn't working

Comments

@leoncvlt
Copy link

leoncvlt commented May 4, 2021

Do you want to request a feature or report a bug?
Bug Report

What is the current behavior?
I'm trying to get the default three.js example from https://github.com/AR-js-org/AR.js/blob/master/three.js/examples/default.html to work - it behaves fine when the code is embedded in a script tag, but as soon as I place it on a separate file and run it through a bundler / frontend tool, I get the error on the Init callback:
image

I guess the bundler screws up the this reference in the ar.js file - I've tried both with parcel and vite and I get the same error in both.

If the current behavior is a bug, please provide the steps to reproduce.
Here's a codesandbox replicating the code from the example: https://codesandbox.io/s/arjs-bundled-59si5 - when accessed on a standalone window at https://59si5.csb.app/ you can see the error in the console. Codesandbox uses parcel to bundle the project files.

Please mention other relevant information such as the browser version, Operating System and Device Name
.

What is the expected behavior?
It should work fine, like it does when accessing the example page via https://raw.githack.com/AR-js-org/AR.js/master/three.js/examples/default.html

If this is a feature request, what is motivation or use case for changing the behavior?
.

I assume this will be fixed when the package becomes module-friendly in #234...?

@kalwalt
Copy link
Member

kalwalt commented May 4, 2021

Hi @leoncvlt have you tried has described in #234? That is import it as a npm package in package.json and import the needed THREEx classes in this way:

import { ArToolkitProfile, ArToolkitSource, ArToolkitContext, ArMarkerControls} from 'arjs/three.js/build/ar-threex.js';

@leoncvlt
Copy link
Author

leoncvlt commented May 8, 2021

Yup, that seems to work using the latest commit of the ES6 branch as the npm dependency. Parcel works fine after that, ViteJS still shows the same issues... but then again it seems to handle dependencies differently than your usual bundler, need to look into it a bit more.

Keep up the good work guys, looking forward to the ES6 refactor being merged on the main branch.

@leoncvlt leoncvlt closed this as completed May 8, 2021
@karltaylor
Copy link

I've come across this too, shouldn't it work anyway even if you're using it via a script?

@msoula
Copy link

msoula commented Jun 22, 2021

I've got the same issue when trying to make that default.html example works.

After some debug, it appears that the following instruction is not working anymore when using recent versions of Threejs library:

Object.assign(ARjs.Context.prototype, THREE.EventDispatcher.prototype);

In fact, EventDispatcher object is now declared as an ECM6 class since version 0.128.0.
So, one solution to get rid of this "dispatchEvent is not a function" error is to make sure you're using a version of Threejs that is prior to 0.128.0.

Below is the html header working on my environment:

<!DOCTYPE html>
<html>
  <head>
    <meta name='viewport' content='width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
    <!-- three.js library -->
    <script src="https://unpkg.com/three@0.103.0/build/three.js"></script>
    <script src="https://unpkg.com/three@0.103.0/examples/js/libs/stats.min.js"></script>
    <!-- ar.js -->
    <script src="https://raw.githack.com/AR-js-org/AR.js/master/three.js/build/ar.js"></script>

    <!-- Bind window error for error handling -->
    <script>
      window.addEventListener('error', function(event) {
        alert("ERROR: " + event.message + " at " + event.filename + " : " + event.lineno + " : " + event.colno);
      });
    </script>
  </head>

  <body style='margin : 0px; overflow: hidden; font-family: Monospace;'>
    <div style='position: absolute; top: 10px; width:100%; text-align: center;z-index:1';>
      <a href='https://github.com/AR-js-org/AR.js/' target='_blank'>AR.js</a> - default setting - webcam + hiro + profile + lerp<br/>
      Contact me any time at <a href='https://twitter.com/nicolocarp' target='_blank'>@nicolocarp</a>
    </div>
  </body>
<script>
//////////////////////////////////////////////////////////////////////////////////
//  Init
//////////////////////////////////////////////////////////////////////////////////

// init renderer
var renderer = new THREE.WebGLRenderer({
    // antialias : true,
    alpha: true
});
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
// renderer.setPixelRatio( 2 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0px'
renderer.domElement.style.left = '0px'
document.body.appendChild( renderer.domElement );

// array of functions for the rendering loop
var onRenderFcts= [];

// init scene and camera
var scene = new THREE.Scene();

//////////////////////////////////////////////////////////////////////////////////
//  Initialize a basic camera
//////////////////////////////////////////////////////////////////////////////////

// Create a camera
var camera = new THREE.Camera();
scene.add(camera);

////////////////////////////////////////////////////////////////////////////////
//          handle arToolkitSource
////////////////////////////////////////////////////////////////////////////////

var artoolkitProfile = new THREEx.ArToolkitProfile()
artoolkitProfile.sourceWebcam()
// artoolkitProfile.sourceVideo(THREEx.ArToolkitContext.baseURL + '../data/videos/headtracking.mp4').kanjiMarker();
// artoolkitProfile.sourceImage(THREEx.ArToolkitContext.baseURL + '../data/images/img.jpg').hiroMarker()

var arToolkitSource = new THREEx.ArToolkitSource(artoolkitProfile.sourceParameters)

arToolkitSource.init(function onReady(){
    onResize()
})

// handle resize
window.addEventListener('resize', function(){
    onResize()
})
function onResize(){
    arToolkitSource.onResizeElement()
    arToolkitSource.copyElementSizeTo(renderer.domElement)
    if( arToolkitContext.arController !== null ){
        arToolkitSource.copyElementSizeTo(arToolkitContext.arController.canvas)
    }
}

////////////////////////////////////////////////////////////////////////////////
//          initialize arToolkitContext
////////////////////////////////////////////////////////////////////////////////

// create atToolkitContext
var arToolkitContext = new THREEx.ArToolkitContext(artoolkitProfile.contextParameters)
// initialize it
arToolkitContext.init(function onCompleted(){
    // copy projection matrix to camera
    camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() );
})

// update artoolkit on every frame
onRenderFcts.push(function(){
    if( arToolkitSource.ready === false ) return

    arToolkitContext.update( arToolkitSource.domElement )
})


////////////////////////////////////////////////////////////////////////////////
//          Create a ArMarkerControls
////////////////////////////////////////////////////////////////////////////////

var markerGroup = new THREE.Group
scene.add(markerGroup)
var markerControls = new THREEx.ArMarkerControls(arToolkitContext, markerGroup, {
    type : 'pattern',
    patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.hiro',
})


// // build a smoothedControls
// var smoothedGroup = new THREE.Group()
// scene.add(smoothedGroup)
// var smoothedControls = new THREEx.ArSmoothedControls(smoothedGroup)
// onRenderFcts.push(function(delta){
//  smoothedControls.update(markerGroup)
// })

//////////////////////////////////////////////////////////////////////////////////
//  add an object in the scene
//////////////////////////////////////////////////////////////////////////////////


var markerScene = new THREE.Scene()
markerGroup.add(markerScene)

var mesh = new THREE.AxesHelper()
markerScene.add(mesh)

// add a torus knot
var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshNormalMaterial({
    transparent : true,
    opacity: 0.5,
    side: THREE.DoubleSide
});
var mesh = new THREE.Mesh( geometry, material );
mesh.position.y = geometry.parameters.height/2
markerScene.add(mesh)

var geometry = new THREE.TorusKnotGeometry(0.3,0.1,64,16);
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh( geometry, material );
mesh.position.y = 0.5
markerScene.add( mesh );

onRenderFcts.push(function(delta){
    mesh.rotation.x += delta * Math.PI
})

//////////////////////////////////////////////////////////////////////////////////
//  render the whole thing on the page
//////////////////////////////////////////////////////////////////////////////////
var stats = new Stats();
document.body.appendChild( stats.dom );
// render the scene
onRenderFcts.push(function(){
    renderer.render( scene, camera );
    stats.update();
})

// run the rendering loop
var lastTimeMsec= null
requestAnimationFrame(function animate(nowMsec){
    // keep looping
    requestAnimationFrame( animate );
    // measure time
    lastTimeMsec = lastTimeMsec || nowMsec-1000/60
    var deltaMsec = Math.min(200, nowMsec - lastTimeMsec)
    lastTimeMsec = nowMsec
    // call each update function
    onRenderFcts.forEach(function(onRenderFct){
        onRenderFct(deltaMsec/1000, nowMsec/1000)
    })
})
</script>
</html>

@kalwalt
Copy link
Member

kalwalt commented Nov 18, 2021

@msoula and all here, this was fixed see:

Context.prototype.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent;
Context.prototype.addEventListener = THREE.EventDispatcher.prototype.addEventListener;
Context.prototype.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener;
Context.prototype.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener;

Context.prototype.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent;
Context.prototype.addEventListener = THREE.EventDispatcher.prototype.addEventListener;
Context.prototype.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener;
Context.prototype.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener;

The code now is dev branch, i hope to merge soon.

@kalwalt kalwalt reopened this Nov 18, 2021
@kalwalt kalwalt self-assigned this Feb 9, 2022
@kalwalt kalwalt added the bug Something isn't working label Feb 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants