{ "metadata": { "name": "", "signature": "sha256:b01df2b0b8090da3c2087d41657504b91ba0ee4207968c11803a428f4eda2aaa" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TopGear Battlecruiser Demo\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Cross-notebook include shim\n", "with open(\"nbinclude.ipynb\") as nbinclude_f: # don't rename nbinclude_f\n", " import IPython.nbformat.current\n", " get_ipython().run_cell(IPython.nbformat.current.read(nbinclude_f, 'json').worksheets[0].cells[0].input)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "nbinclude(\"battlecruiser_widget\")" ], "language": "python", "metadata": {}, "outputs": [ { "javascript": [ "// TODO:\n", "// * code cleanup\n", "// * support button mapping / more than one button\n", "// * better handling for when gamepads disconnect/reconnect at runtime\n", "// * refactor getting gamepads into a function\n", "\n", "require([\"widgets/js/widget\"], function(WidgetManager) {\n", "\n", " var BattleCruiserView = IPython.DOMWidgetView.extend({\n", " render : function(){\n", " // Called when view is rendered.\n", "\n", " //http://drive.google.com/uc?export=view&id=0B_zpNTA3cxZhYlVQREMzRzU5VE0\n", " \n", " //var audio = new Audio('/static/battlecruiser_operational.mp3');\n", " var audio = new Audio('https://drive.google.com/uc?export=view&id=0B_zpNTA3cxZhYlVQREMzRzU5VE0');\n", " audio.play();\n", " \n", " \n", " \n", " //http://drive.google.com/uc?export=view&id=0B_zpNTA3cxZhSHhyR0dYNlhfcVk\n", "\n", " // This is a single-line horizontal widget\n", " this.$el\n", " .addClass('widget-hbox-single')\n", " .css({\n", " 'height': '480px',\n", " 'width': '640px',\n", " //'background-image':'url(/static/starcraft.png)'});\n", " 'background-image':'url(https://drive.google.com/uc?export=view&id=0B_zpNTA3cxZhSHhyR0dYNlhfcVk)'});\n", " // this.$el.style.backgroundImage = \"url(/static/starcraft.png)\";\n", "\n", " // Add a label div, which will contain the description\n", " this.$label = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " this.$value = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " this.$x_val = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " this.$y_val = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " this.$theta_val = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", "\n", " //$('













').appendTo(this.$el);\n", "\n", " this.$antiga_prime=$('
')\n", " .appendTo(this.$el);\n", "\n", " this.$antiga_prime.css({\n", " //'position' : 'fixed',\n", " 'height' : '480px',\n", " 'width' : '640px',\n", " 'top' : 0,\n", " 'left' : 0\n", " // 'background-image':'url(/static/starcraft.png)'\n", "\n", " })\n", " // this.$antiga_prime.style.backgroundImage = \"url(/static/starcraft.png)\";\n", "\n", " this.$bc_image=$('
')\n", " .addClass('stuff')\n", " .css(\"position\", \"relative\")\n", " .appendTo(this.$antiga_prime);\n", "\n", " //this.$bc_image.append(\" \");\n", " this.$bc_image.append(\" \");\n", "\n", " console.log(this.$bc_image.offset())\n", "\n", " // Register an event handler with the joystick - TODO\n", " //onAnalogMove(this.model.get('axis_id'), $.proxy(this.handle_value, this));\n", " //onButton(1, $.proxy(this.handle_value, this));\n", " //register_handler($.proxy(this.handle_value, this));\n", " //console.log(this.model.get('button_id'));\n", "\n", " // this.$el_to_style = this.$checkbox; // Set default element to style\n", " this.update(); // Set defaults.\n", " },\n", "\n", " handle_value: function(new_value) {\n", " // Handles when the checkbox is clicked.\n", "\n", " // Calling model.set will trigger all of the other views of the\n", " // model to update.\n", " this.model.set('value', new_value, {updated_view: this});\n", " this.touch();\n", " },\n", "\n", " update : function(options){\n", " // Update the contents of this view\n", " //\n", " // Called when the model is changed. The model may have been\n", " // changed by another view or by a state update from the back-end.\n", " // this.$checkbox.prop('checked', this.model.get('value'));\n", "\n", " if (options === undefined || options.updated_view != this) {\n", " this.$value.text(this.model.get('value'));\n", " this.$x_val.text(this.model.get('x'));\n", " this.$y_val.text(this.model.get('y'));\n", " this.$theta_val.text(this.model.get('theta'));\n", "\n", " this.$bc_image.children('img').rotate(this.model.get('theta')+310);\n", " //this.$bc_image.offset({'left' : this.model.get('x'), 'top' : this.model.get('y')});\n", " this.$bc_image.css({'left' : this.model.get('x'), 'top' : this.model.get('y')});\n", "\n", "\n", " // var disabled = this.model.get('disabled');\n", " // if (disabled) {\n", " // // Remove the gamepad event\n", " // } else {\n", " // // Re-introduce the gamepad event\n", " // }\n", "\n", " var description = this.model.get('description');\n", " if (description.trim().length === 0) {\n", " this.$label.hide();\n", " } else {\n", " this.$label.text(description);\n", " MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,this.$label.get(0)]);\n", " this.$label.show();\n", " }\n", " }\n", " return BattleCruiserView.__super__.update.apply(this);\n", " },\n", " });\n", "\n", " \n", " WidgetManager.register_widget_view('BattleCruiserView', BattleCruiserView);\n", "});\n" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] }, { "javascript": [ "// VERSION: 1.8 LAST UPDATE: 9.03.2011\r\n", "/* \r\n", " * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php\r\n", " * \r\n", " * Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009\r\n", " * Website: http://code.google.com/p/jqueryrotate/ \r\n", " */\r\n", "\r\n", "// Documentation removed from script file (was kinda useless and outdated)\r\n", "\r\n", "(function($) {\r\n", "var supportedCSS,styles=document.getElementsByTagName(\"head\")[0].style,toCheck=\"transformProperty WebkitTransform OTransform msTransform MozTransform\".split(\" \");\r\n", "for (var a=0;a this._parameters.duration;\r\n", "\r\n", " // TODO: Bug for animatedGif for static rotation ? (to test)\r\n", " if (checkEnd && !this._parameters.animatedGif) \r\n", " {\r\n", " clearTimeout(this._timer);\r\n", " }\r\n", " else \r\n", " {\r\n", " if (this._canvas||this._vimage||this._img) {\r\n", " var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);\r\n", " this._rotate((~~(angle*10))/10);\r\n", " }\r\n", " var self = this;\r\n", " this._timer = setTimeout(function()\r\n", " {\r\n", " self._animate.call(self);\r\n", " }, 10);\r\n", " }\r\n", "\r\n", " // To fix Bug that prevents using recursive function in callback I moved this function to back\r\n", " if (this._parameters.callback && checkEnd){\r\n", " this._angle = this._parameters.animateTo;\r\n", " this._rotate(this._angle);\r\n", " this._parameters.callback.call(this._rootObj);\r\n", " }\r\n", " },\r\n", "\r\n", "\t_rotate : (function()\r\n", "\t{\r\n", "\t\tvar rad = Math.PI/180;\r\n", "\t\tif (IE)\r\n", "\t\treturn function(angle)\r\n", "\t\t{\r\n", " this._angle = angle;\r\n", "\t\t\tthis._container.style.rotation=(angle%360)+\"deg\";\r\n", "\t\t}\r\n", "\t\telse if (supportedCSS)\r\n", "\t\treturn function(angle){\r\n", " this._angle = angle;\r\n", "\t\t\tthis._img.style[supportedCSS]=\"rotate(\"+(angle%360)+\"deg)\";\r\n", "\t\t}\r\n", "\t\telse \r\n", "\t\treturn function(angle)\r\n", "\t\t{\r\n", " this._angle = angle;\r\n", "\t\t\tangle=(angle%360)* rad;\r\n", "\t\t\t// clear canvas\t\r\n", "\t\t\tthis._canvas.width = this._width+this._widthAdd;\r\n", "\t\t\tthis._canvas.height = this._height+this._heightAdd;\r\n", "\t\t\t\t\t\t\r\n", "\t\t\t// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..\r\n", "\t\t\tthis._cnv.translate(this._widthAddHalf,this._heightAddHalf);\t// at least center image on screen\r\n", "\t\t\tthis._cnv.translate(this._widthHalf,this._heightHalf);\t\t\t// we move image back to its orginal \r\n", "\t\t\tthis._cnv.rotate(angle);\t\t\t\t\t\t\t\t\t\t// rotate image\r\n", "\t\t\tthis._cnv.translate(-this._widthHalf,-this._heightHalf);\t\t// move image to its center, so we can rotate around its center\r\n", "\t\t\tthis._cnv.scale(this._aspectW,this._aspectH); // SCALE - if needed ;)\r\n", "\t\t\tthis._cnv.drawImage(this._img, 0, 0);\t\t\t\t\t\t\t// First - we draw image\r\n", "\t\t}\r\n", "\r\n", "\t})()\r\n", "}\r\n", "\r\n", "if (IE)\r\n", "{\r\n", "Wilq32.PhotoEffect.prototype.createVMLNode=(function(){\r\n", "document.createStyleSheet().addRule(\".rvml\", \"behavior:url(#default#VML)\");\r\n", "\t\ttry {\r\n", "\t\t\t!document.namespaces.rvml && document.namespaces.add(\"rvml\", \"urn:schemas-microsoft-com:vml\");\r\n", "\t\t\treturn function (tagName) {\r\n", "\t\t\t\treturn document.createElement('');\r\n", "\t\t\t};\r\n", "\t\t} catch (e) {\r\n", "\t\t\treturn function (tagName) {\r\n", "\t\t\t\treturn document.createElement('<' + tagName + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">');\r\n", "\t\t\t};\r\n", "\t\t}\t\t\r\n", "})();\r\n", "}\r\n", "\r\n", "})(jQuery);\r\n" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "bc=BattleCruiser()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "bc.view" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "bc.cmd(10,0)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 18 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#Awesome!\n", "starcraft is great! everybody should own one!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "nbinclude('gamepad_widget')" ], "language": "python", "metadata": {}, "outputs": [ { "javascript": [ "// TODO:\n", "// * code cleanup\n", "// * support button mapping / more than one button\n", "// * better handling for when gamepads disconnect/reconnect at runtime\n", "// * refactor getting gamepads into a function\n", "\n", "require([\"widgets/js/widget\"], function(WidgetManager) {\n", "\n", " function pollGamepads() {\n", " var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);\n", " for (var i = 0; i < gamepads.length; i++) {\n", " var gp = gamepads[i];\n", " if(gp) {\n", " registerGamepad(i);\n", " clearInterval(interval);\n", " setInterval(pollButtons, 50);\n", " setInterval(pollAxes, 50);\n", " }\n", " }\n", " }\n", "\n", " var gamepad;\n", " function registerGamepad(i) {\n", " gamepad = i;\n", " }\n", "\n", " var button_cache = {};\n", " function pollButtons() {\n", " var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);\n", " var pad = gamepads[gamepad];\n", " var i;\n", " for (i = 0; i < pad.buttons.length; ++i) {\n", " var value = pad.buttons[i];\n", "\n", " if (button_cache[i] !== value) {\n", " notifyButton(i, value);\n", " }\n", " button_cache[i] = value;\n", " }\n", " }\n", "\n", " var button_notifiers = {};\n", " function notifyButton(i, value) {\n", " if (button_notifiers[i] !== undefined) {\n", " for (var j in button_notifiers[i]) {\n", " button_notifiers[i][j](value);\n", " }\n", " }\n", " }\n", "\n", " function onButton(i, callback) {\n", " if (button_notifiers[i] == undefined) {\n", " button_notifiers[i] = []\n", " }\n", " button_notifiers[i].push(callback);\n", " }\n", "\n", " var axes_cache = {};\n", " function pollAxes() {\n", " var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);\n", " var pad = gamepads[gamepad];\n", " var i;\n", " for (i = 0; i < pad.axes.length; ++i) {\n", " var value = pad.axes[i];\n", "\n", " if (axes_cache[i] !== value) {\n", " notifyAnalog(i, value);\n", " }\n", " axes_cache[i] = value;\n", " }\n", " }\n", "\n", " var axes_notifiers = {};\n", " function notifyAnalog(i, value) {\n", " if (axes_notifiers[i] !== undefined) {\n", " for (var j in axes_notifiers[i]) {\n", " axes_notifiers[i][j](value);\n", " }\n", " }\n", " }\n", "\n", " function onAnalogMove(i, callback) {\n", " if (axes_notifiers[i] == undefined) {\n", " axes_notifiers[i] = []\n", " }\n", " axes_notifiers[i].push(callback);\n", " }\n", "\n", " // Assume gamepad events are not available. Use polling\n", " var interval = setInterval(pollGamepads, 500);\n", "\n", " /////// begin IPython stuff\n", " var JoystickBoolView = IPython.DOMWidgetView.extend({\n", " render : function(){\n", " // Called when view is rendered.\n", "\n", " // This is a single-line horizontal widget\n", " this.$el\n", " .addClass('widget-hbox-single');\n", "\n", " // Add a label div, which will contain the description\n", " this.$label = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " // Add a checkbox representing the state\n", " this.$checkbox = $('')\n", " .attr('type', 'checkbox')\n", " .prop('disabled', true)\n", " .appendTo(this.$el);\n", "\n", " // Register an event handler with the joystick - TODO\n", " onButton(this.model.get('button_id'), $.proxy(this.handle_value, this));\n", " //onButton(1, $.proxy(this.handle_value, this));\n", " //register_handler($.proxy(this.handle_value, this));\n", " //console.log(this.model.get('button_id'));\n", "\n", " this.$el_to_style = this.$checkbox; // Set default element to style\n", " this.update(); // Set defaults.\n", " },\n", "\n", " handle_value: function(new_value) {\n", " // Handles when the checkbox is clicked.\n", "\n", " // Calling model.set will trigger all of the other views of the\n", " // model to update.\n", " this.model.set('value', !!new_value, {updated_view: this});\n", " this.touch();\n", " },\n", "\n", " update : function(options){\n", " // Update the contents of this view\n", " //\n", " // Called when the model is changed. The model may have been\n", " // changed by another view or by a state update from the back-end.\n", " this.$checkbox.prop('checked', this.model.get('value'));\n", "\n", "\n", " if (options === undefined || options.updated_view != this) {\n", " var disabled = this.model.get('disabled');\n", " if (disabled) {\n", " // Remove the gamepad event\n", " } else {\n", " // Re-introduce the gamepad event\n", " }\n", "\n", " var description = this.model.get('description');\n", " if (description.trim().length === 0) {\n", " this.$label.hide();\n", " } else {\n", " this.$label.text(description);\n", " MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,this.$label.get(0)]);\n", " this.$label.show();\n", " }\n", " }\n", " return JoystickBoolView.__super__.update.apply(this);\n", " },\n", " });\n", " WidgetManager.register_widget_view('JoystickBoolView', JoystickBoolView);\n", "\n", " var JoystickFloatView = IPython.DOMWidgetView.extend({\n", " render : function(){\n", " // Called when view is rendered.\n", "\n", " // This is a single-line horizontal widget\n", " this.$el\n", " .addClass('widget-hbox-single');\n", "\n", " // Add a label div, which will contain the description\n", " this.$label = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el)\n", " .hide();\n", "\n", " this.$value = $('
')\n", " .addClass('widget-hlabel')\n", " .appendTo(this.$el);\n", "\n", " // Register an event handler with the joystick - TODO\n", " onAnalogMove(this.model.get('axis_id'), $.proxy(this.handle_value, this));\n", " //onButton(1, $.proxy(this.handle_value, this));\n", " //register_handler($.proxy(this.handle_value, this));\n", " //console.log(this.model.get('button_id'));\n", "\n", " // this.$el_to_style = this.$checkbox; // Set default element to style\n", " this.update(); // Set defaults.\n", " },\n", "\n", " handle_value: function(new_value) {\n", " // Handles when the checkbox is clicked.\n", "\n", " // Calling model.set will trigger all of the other views of the\n", " // model to update.\n", " this.model.set('value', new_value, {updated_view: this});\n", " this.touch();\n", " },\n", "\n", " update : function(options){\n", "\n", " this.$value.text(this.model.get('value'));\n", "\n", "\n", " console.log(\"value=\" + this.model.get('value'));\n", "\n", " // Update the contents of this view\n", " //\n", " // Called when the model is changed. The model may have been\n", " // changed by another view or by a state update from the back-end.\n", " // this.$checkbox.prop('checked', this.model.get('value'));\n", "\n", " if (options === undefined || options.updated_view != this) {\n", " // var disabled = this.model.get('disabled');\n", " // if (disabled) {\n", " // // Remove the gamepad event\n", " // } else {\n", " // // Re-introduce the gamepad event\n", " // }\n", "\n", " var description = this.model.get('description');\n", " if (description.trim().length === 0) {\n", " this.$label.hide();\n", " } else {\n", " this.$label.text(description);\n", " MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,this.$label.get(0)]);\n", " this.$label.show();\n", " }\n", " }\n", " return JoystickFloatView.__super__.update.apply(this);\n", " },\n", " });\n", "\n", " \n", " WidgetManager.register_widget_view('JoystickFloatView', JoystickFloatView);\n", "});\n" ], "metadata": {}, "output_type": "display_data", "text": [ "" ] } ], "prompt_number": 81 }, { "cell_type": "code", "collapsed": false, "input": [ "widgets.interact(drive,\n", " x=JoystickFloatWidget(axis_id=1),\n", " z=JoystickFloatWidget(axis_id=2))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 82, "text": [ "" ] } ], "prompt_number": 82 }, { "cell_type": "code", "collapsed": false, "input": [ "widgets.interact(drive,\n", " x=4,\n", " z=1)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 84 }, { "cell_type": "code", "collapsed": false, "input": [ "def drive(x,z):\n", " bc.cmd(x,z)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 83 }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }