UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

358 lines (311 loc) 10.1 kB
var $builtinmodule = function(name) { var mod = {}; var makeFailHTML = function(msg) { return '' + '<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' + '<td align="center">' + '<div style="display: table-cell; vertical-align: middle;">' + '<div style="">' + msg + '</div>' + '</div>' + '</td></tr></table>'; }; var GET_A_WEBGL_BROWSER = '' + 'This page requires a browser that supports WebGL.<br/>' + '<a href="http://get.webgl.org">Click here to upgrade your browser.</a>'; var NEED_HARDWARE = '' + "It doesn't appear your computer can support WebGL.<br/>" + '<a href="http://get.webgl.org">Click here for more information.</a>'; var create3DContext = function(canvas) { var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; var gl = null; for (var ii = 0; ii < names.length; ++ii) { try { gl = canvas.getContext(names[ii]); } catch(e) { } if (gl) { break; } } if (gl) { // Disallow selection by default. This keeps the cursor from changing to an // I-beam when the user clicks and drags. It's easier on the eyes. function returnFalse() { return false; } canvas.onselectstart = returnFalse; canvas.onmousedown = returnFalse; } return gl; }; var setupWebGL = function(canvasContainerId, opt_canvas) { var container = document.getElementById(canvasContainerId); var context; if (!opt_canvas) { opt_canvas = container.getElementsByTagName("canvas")[0]; } if (!opt_canvas) { // this browser doesn't support the canvas tag at all. Not even 2d. container.innerHTML = makeFailHTML(GET_A_WEBGL_BROWSER); return; } var gl = create3DContext(opt_canvas); if (!gl) { // TODO(gman): fix to official way to detect that it's the user's machine, not the browser. var browserStrings = navigator.userAgent.match(/(\w+\/.*? )/g); var browsers = {}; try { for (var b = 0; b < browserStrings.length; ++b) { var parts = browserStrings[b].match(/(\w+)/g); var bb = []; for (var ii = 1; ii < parts.length; ++ii) { bb.push(parseInt(parts[ii])); } browsers[parts[0]] = bb; } } catch (e) { } if (browsers.Chrome && (browsers.Chrome[0] > 7 || (browsers.Chrome[0] == 7 && browsers.Chrome[1] > 0) || (browsers.Chrome[0] == 7 && browsers.Chrome[1] == 0 && browsers.Chrome[2] >= 521))) { container.innerHTML = makeFailHTML(NEED_HARDWARE); } else { container.innerHTML = makeFailHTML(GET_A_WEBGL_BROWSER); } } return gl; }; /** * The Context encapsulates the underlying WebGL native JavaScript API. */ mod.Context = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func( function(self, canvasid) { var canvas = document.getElementById(canvasid.v); var gl = setupWebGL(canvasid.v, canvas) if (!gl) { throw new Error("Your browser does not appear to support WebGL."); } self.gl = gl; // Copy symbolic constants and functions from native WebGL, encapsulating where necessary. for (var k in gl.__proto__) { if (typeof gl.__proto__[k] === 'number') { Sk.abstr.objectSetItem(self['$d'], new Sk.builtin.str(k), gl.__proto__[k]); } else if (typeof gl.__proto__[k] === "function") { switch(k) { case 'bufferData': { } break; case 'clearColor': { } break; case 'drawArrays': { } break; case 'getAttribLocation': { } break; case 'getUniformLocation': { } break; case 'shaderSource': { } break; case 'uniformMatrix4fv': { } break; case 'vertexAttribPointer': { } break; case 'viewport': { } break; default: { (function(key) { Sk.abstr.objectSetItem(self['$d'], new Sk.builtin.str(k), new Sk.builtin.func(function() { var f = gl.__proto__[key]; return f.apply(gl, arguments); })); }(k)); } } } } gl.clearColor(100.0/255.0, 149.0/255.0, 237.0/255.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); } ); $loc.tp$getattr = Sk.builtin.object.prototype.GenericGetAttr; $loc.bufferData = new Sk.builtin.func( function(self, target, data, usage) { self.gl.bufferData(target, data.v, usage); } ); $loc.clearColor = new Sk.builtin.func( function(self, red, green, blue, alpha) { self.gl.clearColor(Sk.builtin.asnum$(red), Sk.builtin.asnum$(green), Sk.builtin.asnum$(blue), Sk.builtin.asnum$(alpha)); } ); $loc.getAttribLocation = new Sk.builtin.func( function(self, program, name) { return self.gl.getAttribLocation(program, name.v); } ); $loc.getUniformLocation = new Sk.builtin.func( function(self, program, name) { return self.gl.getUniformLocation(program, name.v); } ); $loc.shaderSource = new Sk.builtin.func( function(self, shader, src) { self.gl.shaderSource(shader, src.v); } ); $loc.drawArrays = new Sk.builtin.func( function(self, mode, first, count) { self.gl.drawArrays(Sk.builtin.asnum$(mode), Sk.builtin.asnum$(first), Sk.builtin.asnum$(count)); } ); $loc.vertexAttribPointer = new Sk.builtin.func( function(self, index, size, type, normalized, stride, dunno) { self.gl.vertexAttribPointer(index, Sk.builtin.asnum$(size), Sk.builtin.asnum$(type), normalized, Sk.builtin.asnum$(stride), Sk.builtin.asnum$(dunno)); } ); $loc.viewport = new Sk.builtin.func( function(self, x, y, width, height) { self.gl.viewport(Sk.builtin.asnum$(x), Sk.builtin.asnum$(y), Sk.builtin.asnum$(width), Sk.builtin.asnum$(height)); } ); $loc.uniformMatrix4fv = new Sk.builtin.func( function(self, location, transpose, values) { // console.log("location " + (typeof location)); // console.log("transpose " + (typeof transpose)); // console.log("values.v " + (typeof values.v)); self.gl.uniformMatrix4fv(Sk.builtin.asnum$(location), transpose, values.v); } ); $loc.setDrawFunc = new Sk.builtin.func(function(self, func) { var startTime = (new Date()).getTime(); var intervalId = setInterval( function() { Sk.misceval.callsim(func, self, (new Date()).getTime() - startTime); }, 1000.0 / 60.0); // 60 fps }); }, 'Context', []); mod.Float32Array = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func(function(self, data) { if (typeof data === "number") { self.v = new Float32Array(data); } else { self.v = new Float32Array(Sk.ffi.remapToJs(data)); } }); $loc.__repr__ = new Sk.builtin.func(function(self) { var copy = []; for (var i = 0; i < self.v.length; ++i) { copy.push(self.v[i]); } return new Sk.builtin.str("[" + copy.join(', ') + "]"); }); }, 'Float32Array', []); /** * A 4x4 (mutable) matrix suitable for OpenGL. * * Mutability is chosen for performance. * The inderlying implementation is Float32Array. * The indexing of the elements is * 0 4 8 12 * 1 5 9 13 * 2 6 10 14 * 3 7 11 15 */ mod.Matrix4x4 = Sk.misceval.buildClass(mod, function($gbl, $loc) { $loc.__init__ = new Sk.builtin.func(function(self, data) { self.v = new Float32Array(Sk.ffi.remapToJs(data)); }); $loc.identity = new Sk.builtin.func( function(self) { var m = self.v; m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0; m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; } ); $loc.perspective = new Sk.builtin.func( function(self, fov, aspect, near, far) { var t = Math.tan(Math.PI * 0.5 - 0.5 * (Sk.builtin.asnum$(fov) * Math.PI / 180)); var a = Sk.builtin.asnum$(aspect) var n = Sk.builtin.asnum$(near) var f = Sk.builtin.asnum$(far) var k = 1.0 / (n - f); var m = self.v; m[0] = t / a; m[1] = 0; m[2] = 0; m[3] = 0; m[4] = 0; m[5] = t; m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = (n + f) * k; m[11] = -1; m[12] = 0; m[13] = 0; m[14] = n * f * k * 2; m[15] = 0; } ); $loc.translate = new Sk.builtin.func( function(self, translation) { var m = self.v; var t = Sk.ffi.remapToJs(translation); m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0; m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; m[12] = t[0]; m[13] = t[1]; m[14] = t[2]; m[15] = 1; } ); $loc.__repr__ = new Sk.builtin.func(function(self) { var copy = []; for (var i = 0; i < self.v.length; ++i) { copy.push(self.v[i]); } return new Sk.builtin.str("[" + copy.join(', ') + "]"); }); }, 'Matrix4x4', []); return mod; };