Skip to content

Instantly share code, notes, and snippets.

@toxicFork
Created March 2, 2016 18:39
Show Gist options
  • Save toxicFork/8a13399f6a93a05e5bf2 to your computer and use it in GitHub Desktop.
Save toxicFork/8a13399f6a93a05e5bf2 to your computer and use it in GitHub Desktop.
react-three-renderer module example
import Module from 'react-three-renderer/lib/Module';
import PropTypes from 'react/lib/ReactPropTypes';
import events from 'events';
const { EventEmitter } = events;
// or shim EventEmitter
class UpdateAllObjects extends Module {
constructor() {
super();
this._updatePropName = 'onUpdate';
this._patchedDescriptors = [];
this._activeCallbacks = new EventEmitter();
this._objectsWithUpdateCallbacks = {};
}
update() {
this._activeCallbacks.emit('update');
}
_addUpdateCallback(threeObject, callback) {
this._activeCallbacks.addListener('update', callback);
threeObject.userData.events.addListener('dispose', this._objectDisposed);
threeObject.userData._updateCallback = callback;
this._objectsWithUpdateCallbacks[threeObject.uuid] = threeObject;
}
_removeUpdateCallback(threeObject) {
this._activeCallbacks.removeListener('update', threeObject.userData._updateCallback);
threeObject.userData.events.removeListener('dispose', this._objectDisposed);
delete threeObject.userData._updateCallback;
delete this._objectsWithUpdateCallbacks[threeObject.uuid];
}
_objectDisposed = ({ object: disposedObject }) => {
this._removeUpdateCallback(disposedObject);
};
_objectUpdateCallbackChanged = (threeObject, updateCallback) => {
if (updateCallback !== threeObject.userData._updateCallback) {
if (!updateCallback) {
if (!!threeObject.userData._updateCallback) {
this._removeUpdateCallback(threeObject);
}
} else {
// new update callback wants to be set
if (!!threeObject.userData._updateCallback) {
// was already set, so remove that to update cleanly
this._removeUpdateCallback(threeObject);
}
this._addUpdateCallback(threeObject, updateCallback);
}
}
};
setup(react3RendererInstance) {
super.setup(react3RendererInstance);
const Object3DDescriptor = react3RendererInstance.threeElementDescriptors.object3D.constructor;
Object.values(react3RendererInstance.threeElementDescriptors).forEach(elementDescriptor => {
if (elementDescriptor instanceof Object3DDescriptor) {
elementDescriptor.hasProp(this._updatePropName, {
type: PropTypes.func,
updateInitial: true,
update: this._objectUpdateCallbackChanged,
default: undefined,
});
this._patchedDescriptors.push(elementDescriptor);
}
});
}
dispose() {
this._patchedDescriptors.forEach(elementDescriptor => {
elementDescriptor.removeProp(this._updatePropName);
});
const objectsThatStillHaveProps = Object.values(this._objectsWithUpdateCallbacks);
if (process.env.NODE_ENV !== 'production') {
if (objectsThatStillHaveProps.length > 0) {
console.warn('The UpdateAllObjects module' + // eslint-disable-line no-console
' has been removed; but there are objects' +
' that still have the `onUpdate` property defined:', objectsThatStillHaveProps);
}
}
objectsThatStillHaveProps
.forEach(threeObject => {
this._removeUpdateCallback(threeObject);
});
this._activeCallbacks.removeAllListeners();
}
}
module.exports = UpdateAllObjects;
import React from 'react';
import React3 from 'react-three-renderer';
import UpdateAllObjects from './UpdateAllObjects';
class MyComponent extends React.Component {
_onMeshUpdate = () => {
console.log('mesh updated');
};
_onOtherMeshUpdate = () => {
console.log('other mesh updated');
};
render() {
return (<React3
// canvas props
>
<module
descriptor={UpdateAllObjects}
/>
<scene>
<perspectiveCamera
// camera props
/>
<mesh
onUpdate={this._onMeshUpdate}
>
<mesh
onUpdate={this._onOtherMeshUpdate}
>
</mesh>
</scene>
</React3>);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment