xref: /expo/packages/expo-processing/index.js (revision 8aa6c128)
1import React from 'react';
2import { GLView } from 'expo-gl';
3
4const Browser = require('processing-js/lib/Browser');
5Browser.window = window;
6const Processing = require('processing-js/src')(Browser);
7
8export class ProcessingView extends React.Component {
9  componentWillUnmount() {
10    if (this._p) {
11      this._p.exit();
12      this._p = null;
13    }
14    cancelAnimationFrame(this._rafID);
15  }
16
17  render() {
18    const { sketch, ...props } = this.props;
19    return <GLView {...props} onContextCreate={this._onGLContextCreate} />;
20  }
21
22  _onGLContextCreate = gl => {
23    // Canvas polyfilling
24
25    let canvas = Browser.document.createElement('canvas');
26
27    canvas.getContext = () => gl;
28
29    // Cache uniform and attrib locations
30
31    const origGetUniformLocation = gl.getUniformLocation;
32    gl.getUniformLocation = (program, name) => {
33      if (!program.uniformLocationCache) {
34        program.uniformLocationCache = {};
35      }
36      let loc = program.uniformLocationCache[name];
37      if (loc !== undefined) {
38        return loc;
39      }
40      loc = origGetUniformLocation.call(gl, program, name);
41      program.uniformLocationCache[name] = loc;
42      return loc;
43    };
44
45    const origGetAttribLocation = gl.getAttribLocation;
46    gl.getAttribLocation = (program, name) => {
47      if (!program.attribLocationCache) {
48        program.attribLocationCache = {};
49      }
50      let loc = program.attribLocationCache[name];
51      if (loc !== undefined) {
52        return loc;
53      }
54      loc = origGetAttribLocation.call(gl, program, name);
55      program.attribLocationCache[name] = loc;
56      return loc;
57    };
58
59    // Call `gl.endFrameEXP()` every frame
60
61    const keepFlushing = () => {
62      gl.endFrameEXP();
63      this._rafID = requestAnimationFrame(keepFlushing);
64    };
65    keepFlushing();
66
67    // The Processing sketch
68
69    new Processing(canvas, p => {
70      this._p = p;
71
72      // Force render viewport size / mode
73      p.size(gl.drawingBufferWidth, gl.drawingBufferHeight, p.WEBGL);
74      p.size = () => {};
75
76      // Run user's sketch
77      if (this.props.sketch) {
78        this.props.sketch(p);
79      } else {
80        p.draw = () => {};
81      }
82    });
83  };
84}
85