Skip to content
Browse files

Working fine

  • Loading branch information...
0 parents commit a9e702b8c2f000f9ec4db3f84e9bf20614dace5e Iraklis Rossis committed Oct 17, 2011
10 .build
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<buildSequence>
+<buildStep type="bundle">
+<bundle foe="true" inFile="%current-project%/LocalFiles" name="HTML5/JavaScript bundling" outFile="%current-project%/Resources/LocalFiles.bin"/>
+</buildStep>
+<buildStep type="resource"/>
+<buildStep type="compile"/>
+<buildStep type="link"/>
+<buildStep type="pack"/>
+</buildSequence>
17 .cproject
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="org.eclipse.cdt.core.default.config.919827482">
+ <storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="org.eclipse.cdt.core.default.config.919827482" moduleId="org.eclipse.cdt.core.settings" name="Configuration">
+ <externalSettings/>
+ <extensions/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.pathentry">
+ <pathentry kind="con" path="com.mobilesorcery.mosync.includepaths"/>
+ </storageModule>
+</cproject>
17 .mosyncproject
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project supports-build-configs="true" version="1.2">
+<build.cfg id="Debug" types="Debug"/>
+<build.cfg id="Release" types="Release"/>
+<properties>
+<property key="build.prefs:additional.libraries" value="MAUtil.lib, NativeUI.lib, MAFS.lib, Wormhole.lib"/>
+<property key="build.prefs:additional.libraries/Debug" value="MAUtilD.lib, NativeUID.lib, MAFSD.lib, WormholeD.lib"/>
+<property key="build.prefs:memory.data/Debug" value="4096"/>
+<property key="build.prefs:memory.data/Release" value="4096"/>
+<property key="build.prefs:memory.heap/Debug" value="3072"/>
+<property key="build.prefs:memory.heap/Release" value="3072"/>
+<property key="build.prefs:memory.stack/Debug" value="512"/>
+<property key="build.prefs:memory.stack/Release" value="512"/>
+<property key="com.mobilesorcery.sdk.html5.support" value="true"/>
+<property key="template.id" value="project.html5.hybrid"/>
+</properties>
+</project>
8 .mosyncproject.local
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="1.2">
+<active.build.cfg active="Release"/>
+<target-profile device="iPhone" vendor="Apple"/>
+<properties>
+<property key="privileged.access.token" value="CA2441A1D2DA0741429E429FCB838F92"/>
+</properties>
+</project>
36 .project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>WebFountain</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.mobilesorcery.sdk.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.mobilesorcery.sdk.core.nature</nature>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.core.ccnature</nature>
+ <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+ </natures>
+ <filteredResources>
+ <filter>
+ <id>1318342833419</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-true-.*rebuild.build.cpp</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+</projectDescription>
1 .settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
1 .settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
155 HTMLScreen.cpp
@@ -0,0 +1,155 @@
+/*
+ * HTMLScreen.cpp
+ *
+ * Created on: Oct 13, 2011
+ * Author: iraklis
+ */
+
+#include "HTMLScreen.h"
+#include <Wormhole/WebViewMessage.h>
+
+// Namespaces we want to access.
+using namespace MAUtil; // Class Moblet
+using namespace NativeUI; // WebView widget.
+using namespace Wormhole; // Class WebAppMoblet
+
+HTMLScreen::HTMLScreen(int maxParticles, int minFlow, int maxFlow,
+ int particleLifetime, float gravityScale, float initVelocity):Screen()
+{
+ createUI();
+ // Enable message sending from JavaScript to C++.
+ mWebView->enableWebViewMessages();
+
+ // Remove this line to enable the user to
+ // zoom the web page. To disable zoom is one
+ // way of making web pages display in a
+ // reasonable degault size on devices with
+ // different screen sizes.
+ mWebView->disableZoom();
+
+ mWebView->addWebViewListener(this);
+
+ // The page in the "LocalFiles" folder to
+ // show when the application starts.
+ mWebView->openURL("fountain.html");
+
+ sprintf(mBuffer,"init(%d, %d, %d, %d, %f, %f)", maxParticles, minFlow, maxFlow,
+ particleLifetime, gravityScale, initVelocity);
+}
+
+HTMLScreen::~HTMLScreen()
+{
+
+}
+
+void HTMLScreen::createUI()
+{
+ mAddButton = new Button();
+ mAddButton->fillSpaceHorizontally();
+ mAddButton->wrapContentVertically();
+ mAddButton->setText("Increase");
+ mAddButton->addButtonListener(this);
+
+ mRemoveButton = new Button();
+ mRemoveButton->fillSpaceHorizontally();
+ mRemoveButton->wrapContentVertically();
+ mRemoveButton->setText("Decrease");
+ mRemoveButton->addButtonListener(this);
+
+ HorizontalLayout* hLayout = new HorizontalLayout();
+ hLayout->wrapContentVertically();
+ hLayout->addChild(mAddButton);
+ hLayout->addChild(mRemoveButton);
+
+ mWebView = new WebView();
+ mWebView->fillSpaceHorizontally();
+ mWebView->fillSpaceVertically();
+
+ VerticalLayout* vLayout = new VerticalLayout();
+ vLayout->addChild(hLayout);
+ vLayout->addChild(mWebView);
+
+ setMainWidget(vLayout);
+
+ setTitle("HTML Render/Native Buttons");
+}
+
+/**
+ * This method handles messages sent from the WebView.
+ * @param webView The WebView that sent the message.
+ * @param urlData Data object that holds message content.
+ * Note that the data object will be valid only during
+ * the life-time of the call of this method, then it
+ * will be deallocated.
+ */
+void HTMLScreen::webViewHookInvoked(WebView* webView, int hookType, MAHandle urlData)
+{
+ // Create message object. This parses the message.
+ WebViewMessage message(webView, urlData);
+ if (message.is("enableButtons"))
+ {
+ if(message.getParam("add") == "true")
+ {
+ mAddButton->setEnabled(true);
+ mAddButton->setFontColor(0x000000);
+ }
+ else
+ {
+ mAddButton->setEnabled(false);
+ mAddButton->setFontColor(0x969696);
+ }
+
+ if(message.getParam("remove") == "true")
+ {
+ mRemoveButton->setEnabled(true);
+ mRemoveButton->setFontColor(0x000000);
+ }
+ else
+ {
+ mRemoveButton->setEnabled(false);
+ mRemoveButton->setFontColor(0x969696);
+ }
+ }
+
+ if (message.is("pageLoaded"))
+ {
+ mWebView->callJS(mBuffer);
+ shouldRender(mShouldRender);
+ }
+
+ // Tell the WebView that we have processed the message, so that
+ // it can send the next one.
+ mWebView->callJS("bridge.messagehandler.processedMessage()");
+}
+
+void HTMLScreen::buttonClicked(Widget* button)
+{
+ if(button == mAddButton){
+ mWebView->callJS("increaseFlow()");
+ }
+ else if(button == mRemoveButton){
+ mWebView->callJS("decreaseFlow()");
+ }
+}
+
+void HTMLScreen::sensorEvent(MASensor a)
+{
+ char buffer[128];
+ sprintf(buffer,"setGravity(%f, %f, %f)",a.values[0],a.values[1],a.values[2]);
+ mWebView->callJS(buffer);
+}
+
+void HTMLScreen::shouldRender(bool render)
+{
+ mShouldRender = render;
+ if(render)
+ {
+ mWebView->callJS("shouldRender(true)");
+ }
+ else
+ {
+ mWebView->callJS("shouldRender(false)");
+ }
+}
+
+
49 HTMLScreen.h
@@ -0,0 +1,49 @@
+/*
+ * HTMLScreen.h
+ *
+ * Created on: Oct 13, 2011
+ * Author: iraklis
+ */
+
+#include <Wormhole/FileUtil.h>
+#include <NativeUI/Widgets.h>
+
+// Namespaces we want to access.
+using namespace MAUtil; // Class Moblet
+using namespace NativeUI; // WebView widget.
+using namespace Wormhole; // Class WebAppMoblet
+
+#ifndef HTMLSCREEN_H_
+#define HTMLSCREEN_H_
+
+class HTMLScreen : public Screen, public ButtonListener, public SensorListener, public WebViewListener
+{
+public:
+ HTMLScreen(int maxParticles, int minFlow, int maxFlow,
+ int particleLifetime, float gravityScale, float initVelocity);
+
+ ~HTMLScreen();
+
+ void createUI();
+
+ virtual void webViewHookInvoked(WebView* webView, int hookType, MAHandle urlData);
+
+ virtual void buttonClicked(Widget* button);
+
+ virtual void sensorEvent(MASensor a);
+
+ void shouldRender(bool render);
+private:
+ Button* mAddButton;
+
+ Button* mRemoveButton;
+
+ WebView* mWebView;
+
+ bool mShouldRender;
+
+ char mBuffer[128];
+};
+
+
+#endif /* HTMLSCREEN_H_ */
BIN LocalFiles/.DS_Store
Binary file not shown.
BIN LocalFiles/Res/.DS_Store
Binary file not shown.
BIN LocalFiles/Res/particle.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 LocalFiles/buttons.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+ <title>Particles</title>
+ <!-- Import MoSync JavaScript library. -->
+ <script src="js/bridge.js"></script>
+
+ <!-- JavaScript goes here -->
+ <script type="text/javascript">
+
+ var increaseFlowMessage = new Array();
+ increaseFlowMessage["messageName"] = "increaseFlow";
+
+ function IncreaseFlow()
+ {
+ bridge.messagehandler.send(increaseFlowMessage);
+ }
+
+ var decreaseFlowMessage = new Array();
+ decreaseFlowMessage["messageName"] = "decreaseFlow";
+
+ function DecreaseFlow()
+ {
+ bridge.messagehandler.send(decreaseFlowMessage);
+ }
+ </script>
+
+ </head>
+
+ <body onload="" style="background-color:black">
+ <input type="button" value="Increase" onclick="IncreaseFlow()" />
+ <input type="button" value="Decrease" onclick="DecreaseFlow()" />
+ </body>
+</html>
253 LocalFiles/fountain.html
@@ -0,0 +1,253 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+ <title>Particles</title>
+ <!-- Import MoSync JavaScript library. -->
+ <script src="js/bridge.js"></script>
+
+ <!-- JavaScript goes here -->
+ <script type="text/javascript">
+ var MAX_PARTICLES = 65;
+ var MIN_FLOW = 1;
+ var MAX_FLOW = 10;
+ var GRAVITY_SCALE = 0.002;
+ var INIT_VELOCITY = 1.5;
+
+ var innerWidth = window.innerWidth - 10;
+ var innerHeight = window.innerHeight - 10;
+
+ var flow = MIN_FLOW; //Particles per second
+
+ var PARTICLE_LIFETIME = 5000;
+
+ setInterval(timedFunc, 10);
+
+ particle = new Image();
+ particle.src = 'Res/particle.png';
+
+ frames = 0;
+ fps = 0;
+
+ var particles;
+
+ function increaseFlow()
+ {
+ if(flow < MAX_FLOW)
+ {
+ flow += 1;
+ handleButtons();
+ }
+ }
+
+ function decreaseFlow()
+ {
+ if(flow > MIN_FLOW)
+ {
+ flow -= 1;
+ handleButtons();
+ }
+ }
+
+ var render = true;
+ function shouldRender(r)
+ {
+ render = r;
+ }
+
+ var prevTime = new Date().getTime();
+
+ function timedFunc()
+ {
+ if(render)
+ {
+ var currentTime = new Date().getTime();
+ addNewParticles(currentTime);
+ draw(currentTime);
+ removeOldParticles(currentTime);
+ prevTime = currentTime;
+ }
+ }
+
+ var timeToNextParticle = 0;
+
+ function addNewParticles(currentTime)
+ {
+ timeToNextParticle += currentTime - prevTime;
+ if(timeToNextParticle > 1000 / flow)
+ {
+ for(var i = 0; i < particles.length; i++)
+ {
+ var p = particles[i];
+ if(p.alive == false)
+ {
+ p.alive = true;
+ p.addTime = currentTime;
+ var phi = 2*Math.PI * Math.random();
+ var theta = (Math.PI/16) * Math.random();
+ p.xv = INIT_VELOCITY * Math.sin(theta) * Math.cos(phi);
+ p.yv = INIT_VELOCITY * Math.sin(theta) * Math.sin(phi);
+ p.zv = INIT_VELOCITY * Math.cos(theta);
+ p.x = 0;
+ p.y = 0;
+ p.z = 0;
+ break;
+ }
+ }
+ timeToNextParticle = 0;
+ }
+ }
+
+ function removeOldParticles(currentTime)
+ {
+ for(var i = 0; i < particles.length; i++)
+ {
+ var p = particles[i];
+ if(p.alive == true &&
+ (p.addTime + PARTICLE_LIFETIME < currentTime || p.z < 0))
+ {
+ p.alive = false;
+ }
+ }
+ }
+
+ var enableButtonsMessage = new Array();
+ enableButtonsMessage["messageName"] = "enableButtons";
+
+ function handleButtons()
+ {
+ enableButtonsMessage["add"] = "true";
+ enableButtonsMessage["remove"] = "true";
+
+ if(flow >= MAX_FLOW)
+ {
+ enableButtonsMessage["add"] = "false";
+ }
+ else if(flow <= MIN_FLOW)
+ {
+ enableButtonsMessage["remove"] = "false";
+ }
+ bridge.messagehandler.send(enableButtonsMessage);
+ }
+
+ /**
+ * Renders a particle object. The 'dots' argument
+ * should be an array of objects which have members
+ * x, y, width, height
+ **/
+ function renderParticleObject(gfx, particles) {
+
+ for(var i = 0; i < particles.length; i++) {
+ var p = particles[i];
+ if(p.alive ==true && p.z > 0)
+ {
+ gfx.drawImage(particle,
+ p.x - p.z/2 + innerWidth/2,
+ p.y - p.z/2 + innerHeight/2,
+ p.z, p.z);
+ }
+ }
+ }
+
+ var ax = 0;
+ var ay = 0;
+ var az = 0;
+
+ function setGravity(gx,gy,gz)
+ {
+ ax = gx * GRAVITY_SCALE;
+ ay = -gy * GRAVITY_SCALE;
+ az = gz * GRAVITY_SCALE;
+ }
+
+ function draw(currentTime){
+ var canvas = document.getElementById('gfx');
+
+ canvas.width = innerWidth;
+ canvas.height = innerHeight;
+
+ if (canvas.getContext){
+ var gfx = canvas.getContext('2d');
+
+ gfx.globalCompositeOperation = 'source-over';
+ gfx.fillStyle = '#000';
+ gfx.fillRect(0, 0, innerWidth, innerHeight);
+ gfx.save(); // push state
+
+ var twoPI = 2*Math.PI;
+
+ gfx.globalCompositeOperation = 'lighter';
+
+ var cycleTime = (currentTime - prevTime);
+ for(var i = 0; i < particles.length; i++) {
+ var p = particles[i];
+ if(p.alive ==true)
+ {
+ var particleTime = cycleTime;
+ if(p.addTime > prevTime)
+ {
+ particleTime = (currentTime - p.addTime);
+ }
+ p.zv += az*particleTime;
+ p.xv += ax*particleTime;
+ p.yv += ay*particleTime;
+
+ p.z += p.zv*particleTime;
+ p.x += p.xv*particleTime;
+ p.y += p.yv*particleTime;
+
+ }
+
+ }
+
+ renderParticleObject(gfx, particles);
+
+ gfx.fillStyle = '#fff';
+
+ gfx.restore();
+ frames++;
+
+ //fps = 1000 * frames / (time - startTime);
+ }
+ }
+
+ function init(maxParticles, minFlow, maxFlow,
+ particleLifetime, gravityScale, initVelocity)
+ {
+ MAX_PARTICLES = maxParticles;
+ MIN_FLOW = minFlow;
+ MAX_FLOW = maxFlow;
+ GRAVITY_SCALE = gravityScale;
+ INIT_VELOCITY = initVelocity;
+ PARTICLE_LIFETIME = particleLifetime;
+ particles = new Array(MAX_PARTICLES);
+ for(var i = 0; i < MAX_PARTICLES; i++)
+ {
+ particles[i] = new Object();
+ particles[i].alive = false;
+ }
+ handleButtons();
+ }
+
+ function pageLoaded()
+ {
+ var message = new Array();
+ message["messageName"] = "pageLoaded";
+ bridge.messagehandler.send(message);
+ }
+ </script>
+
+ </head>
+
+
+
+
+
+
+
+
+ <body onload="pageLoaded()" style="background-color:black">
+ <canvas id="gfx"/>
+ </body>
+</html>
BIN LocalFiles/images/.DS_Store
Binary file not shown.
BIN LocalFiles/images/MoSyncLogo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 LocalFiles/index.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<!--
+ This application shows how to communicate from JavaScript to C++.
+ When the LogoBox is touched, a call is made to C++ to make the
+ device vibrate. The C++ code that gets called is in main.cpp.
+-->
+<html>
+<head>
+<style>
+html
+{
+ /* Set page attributes. */
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #FFFFFF;
+
+ /* Disable text selection in all browsers. */
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
+#LogoBox
+{
+ /* Center element horizontally. */
+ display: table;
+ margin: auto auto;
+
+ /* Set width of box. */
+ width: 16em;
+
+ /* Use a hand pointer. */
+ cursor: pointer;
+}
+
+#LogoBox img
+{
+ /* Make image same with as LogoBox. */
+ width: 16em;
+}
+
+#TextBox
+{
+ /* Text attributes. */
+ font-size: 2.5em;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: center;
+}
+</style>
+
+<!--
+ Import the bridge library for communication between
+ JavaScript and C++.
+-->
+<script src="js/bridge.js"></script>
+
+<script>
+/**
+ * Array with texts for the TextBox.
+ */
+var TextArray = ["Touch Me!", "Welcome to MoSync and HTML5!"];
+
+/**
+ * Change the text in the TextBox. Swaps between array elements.
+ */
+function SwapText()
+{
+ var textBox = document.getElementById("TextBox");
+ if (textBox.innerHTML == TextArray[0])
+ {
+ textBox.innerHTML = TextArray[1];
+ }
+ else
+ {
+ textBox.innerHTML = TextArray[0];
+ }
+}
+
+/**
+ * Make device vibrate and update the text shown
+ * in the user interface.
+ */
+function OnTouch()
+{
+ Vibrate();
+ SwapText();
+}
+
+/**
+ * Make device vibrate.
+ */
+function Vibrate()
+{
+ // This is how a message is passed to C++ when
+ // using the bridge library.
+ bridge.messagehandler.send({messageName: "Vibrate"}, null);
+}
+</script>
+</head>
+
+<body>
+<div id="LogoBox" onclick="OnTouch()">
+ <img src="images/MoSyncLogo.png"/>
+ <div id="TextBox"></div>
+</div>
+</body>
+<script>
+ // Page elements has loaded, show initial text.
+ SwapText();
+</script>
+</html>
BIN LocalFiles/js/.DS_Store
Binary file not shown.
191 LocalFiles/js/bridge.js
@@ -0,0 +1,191 @@
+/*
+Copyright (C) 2011 MoSync AB
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License,
+version 2, as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.
+*/
+
+/**
+ * @file bridge.js
+ * @author Mikael Kindborg
+ *
+ * Library for JavaScript to C++ communication on the MoSync platform.
+ */
+
+/**
+ * Create a global instance of the library.
+ */
+var bridge = function()
+{
+ var self = {};
+
+ // The messagehandler submodule.
+
+ self.messagehandler = function()
+ {
+ var self = {};
+ var callbackTable = {};
+ var callbackIdCounter = 0;
+ var messageQueue = [];
+
+ /**
+ * Utility function that creates a mosync:// url
+ * that contains the supplied parameters. Format:
+ * mosync://messageName?param1=value1&param2=value2...
+ *
+ * @param message A dictionary with the message parameters.
+ * The parameter "messageName" specifyes the name of the
+ * message selector (the "command name") and must always be
+ * included.
+ *
+ * @return A string that includes the message parameters
+ * formatted as a mosync:// url. Returns null on error.
+ */
+ self.createMessageUrl = function(message)
+ {
+ // The message must contain the parameter messageName.
+ var messageName = message["messageName"];
+ if (null == messageName)
+ {
+ return null;
+ }
+
+ var messageUrl = "mosync://" + messageName;
+ var addParamStartSeparator = true;
+
+ for (var key in message)
+ {
+ // Do not add the messageName parameter.
+ if ("messageName" == key)
+ {
+ continue;
+ }
+
+ if (addParamStartSeparator)
+ {
+ // First time, we should add the question mark that
+ // indicates start of the parameter list.
+ addParamStartSeparator = false;
+ messageUrl += "?";
+ }
+ else
+ {
+ // Otherwise, we add the paramater separator ampersand.
+ messageUrl += "&";
+ }
+
+ // Add parameter.
+ messageUrl += escape(key) + "=" + escape(message[key]);
+ }
+
+ return messageUrl;
+ };
+
+ /**
+ * Send a message to C++. If a callback function is
+ * supplied, a callbackId parameter will be added to
+ * the message, this id can be used when sending a reply
+ * back to JavaScript from C++.
+ *
+ * @param message A dictionary with the message parameters.
+ * The parameter "messageName" specifyes the name of the
+ * message selector (the "command name") and must always be
+ * included.
+ *
+ * @param callbackFun An optional function to receive the
+ * result of the message asynchronosly. Set to null if no
+ * callback is used.
+ */
+ self.send = function(message, callbackFun)
+ {
+
+ // If there is a callback function supplied, create
+ // a callbackId and add it to the callback table.
+ if (null != callbackFun)
+ {
+ callbackIdCounter = callbackIdCounter + 1;
+ callbackTable[callbackIdCounter] = callbackFun;
+ message["callbackId"] = callbackIdCounter;
+ }
+
+ // Create message url and invoke the url.
+ var messageUrl = self.createMessageUrl(message);
+
+ // Add message to queue.
+ messageQueue.push(messageUrl);
+ if (1 == messageQueue.length)
+ {
+ // No messages waiting, send it.
+ setTimeout(function() {
+ document.location = messageUrl; },
+ 1);
+ }
+ };
+
+ /**
+ * Call this function from C++ to tell the message
+ * handler that the last message sent has been processed.
+ */
+ self.processedMessage = function()
+ {
+ // Remove first message.
+ if (messageQueue.length > 0)
+ {
+ messageQueue.shift();
+ }
+
+ // If there are more messages, send the next
+ // message in the queue.
+ if (messageQueue.length > 0)
+ {
+ document.location = messageQueue[0];
+ }
+ };
+
+ /**
+ * This function is meant to be used to call back from C++ to
+ * JavaScript. The function takes a variable number of parameters.
+ *
+ * For example, to return the value 'Hello World' to the callback
+ * with id 82, you can use this code in a WebAppMoblet:
+ *
+ * callJS("bridge.messagehandler.reply(82, 'Hello World')");
+ *
+ * You can obtain the callbackId from the C++ WebViewMessage
+ * object, if you use that class to parse the message.
+ *
+ * @param callBackId The first parameter is the id of the
+ * callback function. Remaning parameters are applied to the
+ * function refered to by the callbackId.
+ */
+ self.reply = function(callbackId)
+ {
+ var callbackFun = callbackTable[callbackId];
+ if (undefined != callbackFun)
+ {
+ // Remove the first param, the callbackId.
+ var args = Array.prototype.slice.call(arguments);
+ args.shift();
+
+ // Call the function.
+ callbackFun.apply(null, args);
+ }
+ };
+
+ return self;
+ }();
+
+ // Return the library object.
+ return self;
+}();
386 OGLScreen.cpp
@@ -0,0 +1,386 @@
+/*
+ * OGLRendering.cpp
+ *
+ * Created on: Oct 13, 2011
+ * Author: iraklis
+ */
+
+#include <mastdlib.h>
+#include "OGLScreen.h"
+
+#include <madmath.h>
+#include <Wormhole/WebViewMessage.h>
+
+// Namespaces we want to access.
+using namespace MAUtil; // Class Moblet
+using namespace NativeUI; // WebView widget.
+using namespace Wormhole; // Class WebAppMoblet
+
+
+OGLScreen::OGLScreen(int maxParticles, int minFlow, int maxFlow,
+ int particleLifetime, float gravityScale, float initVelocity,
+ MAHandle particleImage):
+ Screen(),
+ MAX_PARTICLES(maxParticles),
+ MIN_FLOW(minFlow),
+ MAX_FLOW(maxFlow),
+ PARTICLE_LIFETIME(particleLifetime),
+ GRAVITY_SCALE(gravityScale),
+ INIT_VELOCITY(initVelocity)
+{
+ mParticleImageHandle = particleImage;
+ mGLViewInitialized = false;
+ mShouldRender = false;
+ ax = ay = az = 0;
+
+ mParticles = new particle[MAX_PARTICLES];
+ for(int i = 0; i < MAX_PARTICLES; i++)
+ {
+ mParticles[i].alive = false;
+ }
+
+ mFlow = MIN_FLOW;
+
+ createUI();
+ // Enable message sending from JavaScript to C++.
+ mWebView->enableWebViewMessages();
+
+ // Remove this line to enable the user to
+ // zoom the web page. To disable zoom is one
+ // way of making web pages display in a
+ // reasonable degault size on devices with
+ // different screen sizes.
+ mWebView->disableZoom();
+
+ mWebView->addWebViewListener(this);
+
+ // The page in the "LocalFiles" folder to
+ // show when the application starts.
+ mWebView->openURL("buttons.html");
+ mTimeToNextParticle = 0;
+ mPrevTime = maGetMilliSecondCount();
+ srand(mPrevTime);
+ Environment::getEnvironment().addTimer(this,10,0);
+}
+
+OGLScreen::~OGLScreen()
+{
+ delete mParticles;
+}
+
+void OGLScreen::createUI()
+{
+ mWebView = new WebView();
+ mWebView->fillSpaceHorizontally();
+ mWebView->setHeight(80);
+ mWebView->openURL("buttons.html");
+
+ mWebView->enableWebViewMessages();
+
+
+ mGLView = new GLView(MAW_GL_VIEW);
+ mGLView->addGLViewListener(this);
+
+ VerticalLayout* vLayout = new VerticalLayout();
+ vLayout->addChild(mWebView);
+ vLayout->addChild(mGLView);
+
+ setMainWidget(vLayout);
+ setTitle("Native Render/HTML Buttons");
+}
+
+/**
+ * This method handles messages sent from the WebView.
+ * @param webView The WebView that sent the message.
+ * @param urlData Data object that holds message content.
+ * Note that the data object will be valid only during
+ * the life-time of the call of this method, then it
+ * will be deallocated.
+ */
+void OGLScreen::webViewHookInvoked(WebView* webView, int hookType, MAHandle urlData)
+{
+ // Create message object. This parses the message.
+ WebViewMessage message(webView, urlData);
+ if (message.is("increaseFlow"))
+ {
+ if(mFlow < MAX_FLOW )
+ {
+ mFlow += 1;
+ }
+ }else if (message.is("decreaseFlow"))
+ {
+ if(mFlow > MIN_FLOW )
+ {
+ mFlow -= 1;
+ }
+ }
+
+ // Tell the WebView that we have processed the message, so that
+ // it can send the next one.
+ mWebView->callJS("bridge.messagehandler.processedMessage()");
+}
+
+void OGLScreen::glViewReady(GLView* glView)
+{
+ mGLView->bind();
+ // Create the texture we will use for rendering.
+ createTexture();
+
+ // Set the GL viewport.
+ int viewWidth = mInnerWidth = glView->getWidth();
+ int viewHeight = glView->getHeight();
+ setViewport(viewWidth, viewHeight);
+
+ // Initialize OpenGL.
+ initGL();
+
+ // Flag that the GLView has been initialized.
+ mGLViewInitialized = true;
+}
+
+/**
+ * Create the texture used for rendering.
+ */
+void OGLScreen::createTexture()
+{
+ // Create an OpenGL 2D texture from the image resource.
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, &mParticleTexture);
+ glBindTexture(GL_TEXTURE_2D, mParticleTexture);
+ maOpenGLTexImage2D(mParticleImageHandle);
+
+ // Set texture parameters.
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+/**
+ * Setup the projection matrix.
+ */
+void OGLScreen::setViewport(int width, int height)
+{
+ // Protect against divide by zero.
+ if (0 == height)
+ {
+ height = 1;
+ }
+ // Set viewport.
+ glViewport(0, 0, (GLint)width, (GLint)height);
+
+ // Select the projection matrix.
+ glMatrixMode(GL_PROJECTION);
+
+ // Reset the projection matrix.
+ glLoadIdentity();
+
+ // Set the perspective (updates the projection
+ // matrix to use the perspective we define).
+ //GLfloat ratio = (GLfloat)width / (GLfloat)height;
+ //gluPerspective(45.0f, ratio, 0.1f, 100.0f);
+
+ //Set an orthographic projection
+ glOrthof((GLfloat)(-width / 2),
+ (GLfloat)(+width / 2),
+ (GLfloat)(-height / 2),
+ (GLfloat)(+height / 2),
+ 0,1
+ );
+}
+
+/**
+ * Standard OpenGL initialization.
+ */
+void OGLScreen::initGL()
+{
+ // Enable texture mapping.
+ glEnable(GL_TEXTURE_2D);
+
+ // Enable smooth shading.
+ glShadeModel(GL_SMOOTH);
+
+ // Set the depth value used when clearing the depth buffer.
+ glClearDepthf(1.0f);
+
+ glEnable(GL_BLEND);
+
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ // Enable depth testing.
+ //glEnable(GL_DEPTH_TEST);
+
+ // Set the type of depth test.
+ //glDepthFunc(GL_LEQUAL);
+
+ // Use the best perspective correction method.
+ //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+}
+
+void OGLScreen::renderParticleObject()
+{
+ // Array used for object coordinates.
+ GLfloat vcoords[4][3];
+ // Array used for texture coordinates.
+ GLfloat tcoords[4][2];
+ // Array used to convert from QUAD to TRIANGLE_STRIP.
+ // QUAD is not available on the OpenGL implementation
+ // we are using.
+ GLubyte indices[4] = {0, 1, 3, 2};
+
+ // Select the texture to use when rendering the box.
+ glBindTexture(GL_TEXTURE_2D, mParticleTexture);
+
+ // Define the particle.
+ tcoords[0][0] = 1.0f; tcoords[0][1] = 0.0f;
+ vcoords[0][0] = -1.0f; vcoords[0][1] = -1.0f; vcoords[0][2] = 0.0f;
+ tcoords[1][0] = 0.0f; tcoords[1][1] = 0.0f;
+ vcoords[1][0] = 1.0f; vcoords[1][1] = -1.0f; vcoords[1][2] = 0.0f;
+ tcoords[2][0] = 0.0f; tcoords[2][1] = 1.0f;
+ vcoords[2][0] = 1.0f; vcoords[2][1] = 1.0f; vcoords[2][2] = 0.0f;
+ tcoords[3][0] = 1.0f; tcoords[3][1] = 1.0f;
+ vcoords[3][0] = -1.0f; vcoords[3][1] = 1.0f; vcoords[3][2] = 0.0f;
+
+ // Set pointers to vertex coordinates and texture coordinates.
+ glVertexPointer(3, GL_FLOAT, 0, vcoords);
+ glTexCoordPointer(2, GL_FLOAT, 0, tcoords);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ for(int i = 0; i < MAX_PARTICLES; i++) {
+ if(mParticles[i].alive)
+ {
+ glPushMatrix();
+ // Enable vertex and texture coord arrays.
+
+ glTranslatef(mParticles[i].x, mParticles[i].y, 0.0f);
+ glScalef(mParticles[i].z, mParticles[i].z, 0.0f);
+
+ // This draws the particle.
+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
+ // Disable texture and vertex arrays.
+
+ glPopMatrix();
+ }
+ }
+
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+
+}
+
+void OGLScreen::draw(int currentTime)
+{
+ // The GL_View must be initialized before we can do any drawing.
+ if (!mGLViewInitialized)
+ {
+ return;
+ }
+ // Set the background color to be used when clearing the screen.
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+ // Clear the screen and the depth buffer.
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // Use the model matrix.
+ glMatrixMode(GL_MODELVIEW);
+
+ // Reset the model matrix.
+ glLoadIdentity();
+
+ float twoPI = 2*M_PI;
+ int cycleTime = (currentTime - mPrevTime);
+ for(int i = 0; i < MAX_PARTICLES; i++) {
+
+ particle* p = mParticles + i;
+ if(p->alive == true)
+ {
+ int particleTime = cycleTime;
+ if(p->addTime > mPrevTime)
+ {
+ particleTime = (currentTime - p->addTime);
+ }
+ p->zv += az*particleTime;
+ p->xv += ax*particleTime;
+ p->yv += ay*particleTime;
+
+ p->z += p->zv*particleTime;
+ p->x += p->xv*particleTime;
+ p->y += p->yv*particleTime;
+ }
+ }
+
+ renderParticleObject();
+
+ // Wait (blocks) until all GL drawing commands to finish.
+ glFinish();
+
+ mGLView->redraw();
+}
+
+
+
+void OGLScreen::shouldRender(bool render)
+{
+ mShouldRender = render;
+}
+
+void OGLScreen::sensorEvent(MASensor a)
+{
+ ax = a.values[0] * GRAVITY_SCALE;
+ ay = a.values[1] * GRAVITY_SCALE;
+ az = a.values[2] * GRAVITY_SCALE;
+}
+
+void OGLScreen::runTimerEvent()
+{
+ if(mShouldRender)
+ {
+ int currentTime = maGetMilliSecondCount();
+ addNewParticles(currentTime);
+ draw(currentTime);
+ removeOldParticles(currentTime);
+ mPrevTime = currentTime;
+ }
+}
+
+void OGLScreen::addNewParticles(int currentTime)
+{
+ mTimeToNextParticle += currentTime - mPrevTime;
+ if(mTimeToNextParticle > 1000 / mFlow)
+ {
+ for(int i = 0; i < MAX_PARTICLES; i++)
+ {
+ if(!mParticles[i].alive)
+ {
+ mParticles[i].alive = true;
+ mParticles[i].addTime = currentTime;
+ float phi = 2*M_PI * rand() / (float)RAND_MAX;
+ float theta = (M_PI/16) * rand() / (float)RAND_MAX;
+ mParticles[i].xv = INIT_VELOCITY * sin(theta) * cos(phi);
+ mParticles[i].yv = INIT_VELOCITY * sin(theta) * sin(phi);
+ mParticles[i].zv = INIT_VELOCITY * cos(theta);
+ mParticles[i].x = 0;
+ mParticles[i].y = 0;
+ mParticles[i].z = 0;
+ break;
+ }
+ }
+ mTimeToNextParticle = 0;
+ }
+}
+
+void OGLScreen::removeOldParticles(int currentTime)
+{
+ for(int i = 0; i < MAX_PARTICLES; i++)
+ {
+ if(mParticles[i].alive == true &&
+ (mParticles[i].addTime + PARTICLE_LIFETIME < currentTime || mParticles[i].z < 0))
+ {
+ mParticles[i].alive = false;
+ }
+ }
+}
+
+
109 OGLScreen.h
@@ -0,0 +1,109 @@
+/*
+ * OGLScreen.h
+ *
+ * Created on: Oct 13, 2011
+ * Author: iraklis
+ */
+
+
+#include <NativeUI/Widgets.h>
+#include <GLES/gl.h>
+
+// Namespaces we want to access.
+using namespace MAUtil; // Class Moblet
+using namespace NativeUI; // WebView widget.
+
+#ifndef OGLSCREEN_H_
+#define OGLSCREEN_H_
+
+typedef struct particle{
+ bool alive;
+ int addTime;
+ float x;
+ float y;
+ float z;
+ float xv;
+ float yv;
+ float zv;
+
+};
+
+
+class OGLScreen : public Screen,
+ public GLViewListener,
+ public SensorListener,
+ public WebViewListener,
+ public TimerListener
+{
+public:
+ OGLScreen(int maxParticles, int minFlow, int maxFlow,
+ int particleLifetime, float gravityScale, float initVelocity,
+ MAHandle particleImage);
+
+ ~OGLScreen();
+
+ void createUI();
+
+ virtual void webViewHookInvoked(WebView* webView, int hookType, MAHandle urlData);
+
+ virtual void sensorEvent(MASensor a);
+
+ virtual void glViewReady(GLView* glView);
+
+ void createTexture();
+
+ void setViewport(int width, int height);
+
+ void initGL();
+
+ void draw(int currentTime);
+
+ void renderParticleObject();
+
+ void shouldRender(bool render);
+
+ virtual void runTimerEvent();
+
+ void addNewParticles(int currentTime);
+
+ void removeOldParticles(int currentTime);
+private:
+ WebView* mWebView;
+
+ MAHandle mParticleImageHandle;
+
+ GLuint mParticleTexture;
+
+ bool mGLViewInitialized;
+
+ GLView* mGLView;
+
+ particle* mParticles;
+
+ int mFlow;
+
+ int mInnerWidth;
+
+ bool mShouldRender;
+
+ int mPrevTime;
+
+ int mTimeToNextParticle;
+
+ float ax, ay, az;
+
+ int MAX_PARTICLES;
+
+ int MIN_FLOW;
+
+ int MAX_FLOW;
+
+ int PARTICLE_LIFETIME;
+
+ float GRAVITY_SCALE;
+
+ float INIT_VELOCITY;
+};
+
+
+#endif /* OGLSCREEN_H_ */
BIN Resources/.DS_Store
Binary file not shown.
BIN Resources/LocalFiles.bin
Binary file not shown.
6 Resources/Resources.lst
@@ -0,0 +1,6 @@
+.res LOCAL_FILES_BIN
+.ubin
+.include "LocalFiles.bin"
+
+.res PARTICLE_IMAGE
+.image "../LocalFiles/RES/particle.png"
109 main.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file main.cpp
+ *
+ * Sample application that illustrates how to call into C++
+ * from JavaScript.
+ */
+
+// Include Moblet for web applications.
+#include <Wormhole/WebAppMoblet.h>
+#include <NativeUI/Widgets.h>
+#include "HTMLScreen.h"
+#include "OGLScreen.h"
+#include "MAHeaders.h"
+
+// Namespaces we want to access.
+using namespace MAUtil; // Class Moblet
+using namespace NativeUI; // WebView widget.
+using namespace Wormhole; // Class WebAppMoblet
+
+/**
+ * The application class.
+ */
+class WebFountain : public Moblet, public TabScreenListener
+{
+public:
+ WebFountain()
+ {
+ // Create file utility object.
+ mFileUtil = new FileUtil();
+
+ // Extract bundled files to the local file system.
+ mFileUtil->extractLocalFiles();
+ mHTMLScreen = new HTMLScreen(MAX_PARTICLES, MIN_FLOW, MAX_FLOW,
+ PARTICLE_LIFETIME, GRAVITY_SCALE,
+ INIT_VELOCITY);
+ mOGLScreen = new OGLScreen(MAX_PARTICLES, MIN_FLOW, MAX_FLOW,
+ PARTICLE_LIFETIME, GRAVITY_SCALE,
+ INIT_VELOCITY, PARTICLE_IMAGE);
+ Environment::getEnvironment().addSensorListener(mHTMLScreen);
+ Environment::getEnvironment().addSensorListener(mOGLScreen);
+ maSensorStart(1, 100);
+
+ mTabScreen = new TabScreen();
+ mTabScreen->addTab(mHTMLScreen);
+ mTabScreen->addTab(mOGLScreen);
+ mTabScreen->addTabScreenListener(this);
+
+ mTabScreen->setActiveTab(0);
+ mTabScreen->show();
+ mHTMLScreen->shouldRender(true);
+ }
+
+ ~WebFountain()
+ {
+ delete mHTMLScreen;
+ delete mOGLScreen;
+ delete mFileUtil;
+ }
+
+ virtual void tabScreenTabChanged(
+ TabScreen* tabScreen,
+ const int tabScreenIndex)
+ {
+ if(tabScreenIndex == 0)
+ {
+ mHTMLScreen->shouldRender(true);
+ mOGLScreen->shouldRender(false);
+ }
+ else
+ {
+ mHTMLScreen->shouldRender(false);
+ mOGLScreen->shouldRender(true);
+ }
+ }
+
+
+
+private:
+ HTMLScreen* mHTMLScreen;
+
+ OGLScreen* mOGLScreen;
+
+ FileUtil* mFileUtil;
+
+ TabScreen* mTabScreen;
+
+ static const int MAX_PARTICLES = 65;
+
+ static const int MIN_FLOW = 1;
+
+ static const int MAX_FLOW = 10;
+
+ static const int PARTICLE_LIFETIME = 5000;
+
+ static const float GRAVITY_SCALE = 0.002;
+
+ static const float INIT_VELOCITY = 1.5;
+};
+
+/**
+ * Main function that is called when the program starts.
+ * Here an instance of the MyMoblet class is created and
+ * the program enters the main event loop.
+ */
+extern "C" int MAMain()
+{
+ Moblet::run(new WebFountain());
+ return 0;
+}

0 comments on commit a9e702b

Please sign in to comment.
Something went wrong with that request. Please try again.