aboutsummaryrefslogtreecommitdiff
path: root/platform/bb10
diff options
context:
space:
mode:
authorJuan Linietsky2014-02-09 22:10:30 -0300
committerJuan Linietsky2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /platform/bb10
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
downloadgodot-0b806ee.tar.gz
godot-0b806ee.tar.zst
godot-0b806ee.zip
GODOT IS OPEN SOURCE
Diffstat (limited to 'platform/bb10')
-rw-r--r--platform/bb10/SCsub30
-rw-r--r--platform/bb10/audio_driver_bb10.cpp255
-rw-r--r--platform/bb10/audio_driver_bb10.h78
-rw-r--r--platform/bb10/bar/bar-descriptor.xml65
-rw-r--r--platform/bb10/bar/icon.pngbin0 -> 8188 bytes
-rw-r--r--platform/bb10/bbutil.c513
-rw-r--r--platform/bb10/bbutil.h96
-rw-r--r--platform/bb10/detect.py91
-rw-r--r--platform/bb10/export/export.cpp805
-rw-r--r--platform/bb10/export/export.h3
-rw-r--r--platform/bb10/godot_bb10.cpp48
-rw-r--r--platform/bb10/logo.pngbin0 -> 1852 bytes
-rw-r--r--platform/bb10/os_bb10.cpp630
-rw-r--r--platform/bb10/os_bb10.h157
-rw-r--r--platform/bb10/payment_service.cpp150
-rw-r--r--platform/bb10/payment_service.h69
-rw-r--r--platform/bb10/platform_config.h29
17 files changed, 3019 insertions, 0 deletions
diff --git a/platform/bb10/SCsub b/platform/bb10/SCsub
new file mode 100644
index 000000000..2e8ef4700
--- /dev/null
+++ b/platform/bb10/SCsub
@@ -0,0 +1,30 @@
+Import('env')
+
+bb10_lib = [
+
+ 'bbutil.c',
+ 'os_bb10.cpp',
+ 'audio_driver_bb10.cpp',
+ 'godot_bb10.cpp',
+ 'payment_service.cpp',
+]
+
+env_bps = env.Clone()
+if env['bb10_payment_service'] == "yes":
+ env_bps.Append(CPPFLAGS=['-DPAYMENT_SERVICE_ENABLED'])
+
+if env['bb10_lgles_override'] == "yes":
+ env_bps.Append(CPPFLAGS=['-DBB10_LGLES_OVERRIDE'])
+
+
+prog = None
+if env["target"]=="release":
+ prog = env_bps.Program('#platform/bb10/godot_bb10_opt', bb10_lib)
+else:
+ prog = env_bps.Program('#platform/bb10/godot_bb10', bb10_lib)
+
+import os
+fname = os.path.basename(str(prog[0]))
+
+env.Command('#bin/'+fname, prog, Copy('bin/'+fname, prog[0]))
+
diff --git a/platform/bb10/audio_driver_bb10.cpp b/platform/bb10/audio_driver_bb10.cpp
new file mode 100644
index 000000000..ac6a008a0
--- /dev/null
+++ b/platform/bb10/audio_driver_bb10.cpp
@@ -0,0 +1,255 @@
+/*************************************************************************/
+/* audio_driver_bb10.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "audio_driver_bb10.h"
+
+#include <errno.h>
+
+Error AudioDriverBB10::init() {
+ return init(NULL);
+};
+
+Error AudioDriverBB10::init(const char* p_name) {
+
+ active=false;
+ thread_exited=false;
+ exit_thread=false;
+ pcm_open = false;
+ samples_in = NULL;
+ samples_out = NULL;
+
+ mix_rate = 44100;
+ output_format = OUTPUT_STEREO;
+
+ char* dev_name;
+ if (p_name == NULL) {
+ dev_name = "pcmPreferred";
+ } else {
+ dev_name = (char *) p_name;
+ }
+ printf("******** reconnecting to device %s\n", dev_name);
+ int card, dev;
+ int ret = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK);
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+ pcm_open = true;
+
+ snd_pcm_channel_info_t cinfo;
+ zeromem(&cinfo, sizeof (cinfo));
+ cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
+ snd_pcm_plugin_info(pcm_handle, &cinfo);
+
+ printf("rates %i, %i, %i, %i, %i\n", cinfo.rates, cinfo.rates & SND_PCM_RATE_44100, cinfo.rates & SND_PCM_RATE_32000, cinfo.rates & SND_PCM_RATE_22050, cinfo.max_rate);
+
+ mix_rate = cinfo.max_rate;
+
+ printf("formats %i, %i, %i\n", cinfo.formats, cinfo.formats & SND_PCM_FMT_S16_BE, cinfo.formats & SND_PCM_FMT_S16_LE);
+ ERR_FAIL_COND_V(!(cinfo.formats & SND_PCM_FMT_S16_LE), FAILED);
+
+ printf("voices %i\n", cinfo.max_voices);
+ output_format = cinfo.max_voices >= 2 ? OUTPUT_STEREO : OUTPUT_MONO;
+
+ snd_pcm_channel_params_t cp;
+ zeromem(&cp, sizeof(cp));
+ cp.mode = SND_PCM_MODE_BLOCK;
+ cp.channel = SND_PCM_CHANNEL_PLAYBACK;
+ cp.start_mode = SND_PCM_START_DATA;
+ cp.stop_mode = SND_PCM_STOP_STOP;
+ //cp.buf.block.frag_size = cinfo.max_fragment_size;
+ cp.buf.block.frag_size = 512;
+ cp.buf.block.frags_max = 1;
+ cp.buf.block.frags_min = 1;
+ cp.format.interleave = 1;
+ cp.format.rate = mix_rate;
+ cp.format.voices = output_format == OUTPUT_MONO ? 1 : 2;
+ cp.format.format = SND_PCM_SFMT_S16_LE;
+
+ ret = snd_pcm_plugin_params(pcm_handle, &cp);
+ printf("ret is %i, %i\n", ret, cp.why_failed);
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+
+ ret = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+
+ snd_mixer_group_t group;
+ zeromem(&group, sizeof(group));
+ snd_pcm_channel_setup_t setup;
+ zeromem(&setup, sizeof(setup));
+ setup.channel = SND_PCM_CHANNEL_PLAYBACK;
+ setup.mode = SND_PCM_MODE_BLOCK;
+ setup.mixer_gid = &group.gid;
+ ret = snd_pcm_plugin_setup(pcm_handle, &setup);
+ ERR_FAIL_COND_V(ret < 0, FAILED);
+
+ pcm_frag_size = setup.buf.block.frag_size;
+ pcm_max_frags = 1;
+
+ sample_buf_count = pcm_frag_size * pcm_max_frags / 2;
+ printf("sample count %i, %i, %i\n", sample_buf_count, pcm_frag_size, pcm_max_frags);
+ samples_in = memnew_arr(int32_t, sample_buf_count);
+ samples_out = memnew_arr(int16_t, sample_buf_count);
+
+ thread = Thread::create(AudioDriverBB10::thread_func, this);
+
+ return OK;
+};
+
+void AudioDriverBB10::thread_func(void* p_udata) {
+
+ AudioDriverBB10* ad = (AudioDriverBB10*)p_udata;
+
+ int channels = (ad->output_format == OUTPUT_MONO ? 1 : 2);
+ int frame_count = ad->sample_buf_count / channels;
+ int bytes_out = frame_count * channels * 2;
+
+ while (!ad->exit_thread) {
+
+
+ if (!ad->active) {
+
+ for (int i=0; i < ad->sample_buf_count; i++) {
+
+ ad->samples_out[i] = 0;
+ };
+ } else {
+
+ ad->lock();
+
+ ad->audio_server_process(frame_count, ad->samples_in);
+
+ ad->unlock();
+
+ for(int i=0;i<frame_count*channels;i++) {
+
+ ad->samples_out[i]=ad->samples_in[i]>>16;
+ }
+ };
+
+
+ int todo = bytes_out;
+ int total = 0;
+
+ while (todo) {
+
+ uint8_t* src = (uint8_t*)ad->samples_out;
+ int wrote = snd_pcm_plugin_write(ad->pcm_handle, (void*)(src + total), todo);
+ if (wrote < 0) {
+ // error?
+ break;
+ };
+ total += wrote;
+ todo -= wrote;
+ if (wrote < todo) {
+ if (ad->thread_exited) {
+ break;
+ };
+ printf("pcm_write underrun %i, errno %i\n", (int)ad->thread_exited, errno);
+ snd_pcm_channel_status_t status;
+ zeromem(&status, sizeof(status));
+ // put in non-blocking mode
+ snd_pcm_nonblock_mode(ad->pcm_handle, 1);
+ status.channel = SND_PCM_CHANNEL_PLAYBACK;
+ int ret = snd_pcm_plugin_status(ad->pcm_handle, &status);
+ //printf("status return %i, %i, %i, %i, %i\n", ret, errno, status.status, SND_PCM_STATUS_READY, SND_PCM_STATUS_UNDERRUN);
+ snd_pcm_nonblock_mode(ad->pcm_handle, 0);
+ if (ret < 0) {
+ break;
+ };
+ if (status.status == SND_PCM_STATUS_READY ||
+ status.status == SND_PCM_STATUS_UNDERRUN) {
+ snd_pcm_plugin_prepare(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+ } else {
+ break;
+ };
+ };
+ };
+ };
+
+ snd_pcm_plugin_flush (ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+
+ ad->thread_exited=true;
+ printf("**************** audio thread exit\n");
+};
+
+void AudioDriverBB10::start() {
+
+ active = true;
+};
+
+int AudioDriverBB10::get_mix_rate() const {
+
+ return mix_rate;
+};
+
+AudioDriverSW::OutputFormat AudioDriverBB10::get_output_format() const {
+
+ return output_format;
+};
+void AudioDriverBB10::lock() {
+
+ if (!thread)
+ return;
+ mutex->lock();
+};
+void AudioDriverBB10::unlock() {
+
+ if (!thread)
+ return;
+ mutex->unlock();
+};
+
+void AudioDriverBB10::finish() {
+
+ if (!thread)
+ return;
+
+ exit_thread = true;
+ Thread::wait_to_finish(thread);
+
+ if (pcm_open)
+ snd_pcm_close(pcm_handle);
+
+ if (samples_in) {
+ memdelete_arr(samples_in);
+ memdelete_arr(samples_out);
+ };
+
+ memdelete(thread);
+ thread = NULL;
+};
+
+AudioDriverBB10::AudioDriverBB10() {
+
+ mutex = Mutex::create();
+};
+
+AudioDriverBB10::~AudioDriverBB10() {
+
+ memdelete(mutex);
+ mutex = NULL;
+};
+
diff --git a/platform/bb10/audio_driver_bb10.h b/platform/bb10/audio_driver_bb10.h
new file mode 100644
index 000000000..98b99107d
--- /dev/null
+++ b/platform/bb10/audio_driver_bb10.h
@@ -0,0 +1,78 @@
+/*************************************************************************/
+/* audio_driver_bb10.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "servers/audio/audio_server_sw.h"
+
+#include "core/os/thread.h"
+#include "core/os/mutex.h"
+
+#include <sys/asoundlib.h>
+
+class AudioDriverBB10 : public AudioDriverSW {
+
+ Thread* thread;
+ Mutex* mutex;
+
+ snd_pcm_t* pcm_handle;
+
+ int32_t* samples_in;
+ int16_t* samples_out;
+ int sample_buf_count;
+
+ static void thread_func(void* p_udata);
+
+ int mix_rate;
+ OutputFormat output_format;
+
+ int pcm_frag_size;
+ int pcm_max_frags;
+
+ bool active;
+ bool thread_exited;
+ mutable bool exit_thread;
+ bool pcm_open;
+
+public:
+
+ const char* get_name() const {
+ return "BB10";
+ };
+
+ virtual Error init();
+ virtual Error init(const char* p_name);
+ virtual void start();
+ virtual int get_mix_rate() const;
+ virtual OutputFormat get_output_format() const;
+ virtual void lock();
+ virtual void unlock();
+ virtual void finish();
+
+ AudioDriverBB10();
+ ~AudioDriverBB10();
+};
+
diff --git a/platform/bb10/bar/bar-descriptor.xml b/platform/bb10/bar/bar-descriptor.xml
new file mode 100644
index 000000000..df5d34e07
--- /dev/null
+++ b/platform/bb10/bar/bar-descriptor.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<qnx xmlns="http://www.qnx.com/schemas/application/1.0">
+
+<!-- BlackBerry® 10 application descriptor file.
+
+ Specifies parameters for identifying, installing, and launching native applications on BlackBerry® 10 OS.
+-->
+
+ <!-- A universally unique application identifier. Must be unique across all BlackBerry applications.
+ Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
+ <id>com.godot.game</id>
+
+ <!-- The name that is displayed in the BlackBerry application installer.
+ May have multiple values for each language. See samples or xsd schema file. Optional. -->
+ <name>Godot Game</name>
+
+ <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade.
+ Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
+ An updated version of application must have a versionNumber value higher than the previous version. Required. -->
+ <versionNumber>0.0.1</versionNumber>
+
+ <!-- Fourth digit segment of the package version. First three segments are taken from the
+ <versionNumber> element. Must be an integer from 0 to 2^16-1 -->
+ <buildId>0</buildId>
+
+ <!-- Description, displayed in the BlackBerry application installer.
+ May have multiple values for each language. See samples or xsd schema file. Optional. -->
+ <description>Game made with Godot Engine</description>
+
+ <!-- Name of author which is used for signing. Must match the developer name of your development certificate. -->
+ <author>You Name or Company</author>
+ <authorId>authorIDherePlease</authorId>
+
+ <!-- Unique author ID assigned by signing authority. Required if using debug tokens. -->
+ <!-- <authorId>ABC1234YjsnUk235h</authorId> -->
+
+ <initialWindow>
+ <aspectRatio>landscape</aspectRatio>
+ <autoOrients>false</autoOrients>
+ <systemChrome>none</systemChrome>
+ <transparent>false</transparent>
+ </initialWindow>
+
+ <!-- The category where the application appears. Either core.games or core.media. -->
+ <category>core.games</category>
+ <permission>read_device_identifying_information</permission>
+ <permission>access_internet</permission>
+ <asset path="assets">assets</asset>
+ <configuration name="Device-Debug">
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset path="godot_bb10.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10.qnx.armle</asset>
+ </configuration>
+ <configuration name="Device-Release">
+ <platformArchitecture>armle-v7</platformArchitecture>
+ <asset path="godot_bb10_opt.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10_opt.qnx.armle</asset>
+ </configuration>
+ <!-- The icon for the application. -->
+ <icon>
+ <image>icon.png</image>
+ </icon>
+
+ <!-- Ensure that shared libraries in the package are found at run-time. -->
+ <env var="LD_LIBRARY_PATH" value="app/native/lib:/usr/lib/qt4/lib"/>
+
+</qnx>
diff --git a/platform/bb10/bar/icon.png b/platform/bb10/bar/icon.png
new file mode 100644
index 000000000..a837c8009
--- /dev/null
+++ b/platform/bb10/bar/icon.png
Binary files differ
diff --git a/platform/bb10/bbutil.c b/platform/bb10/bbutil.c
new file mode 100644
index 000000000..fce52c5b8
--- /dev/null
+++ b/platform/bb10/bbutil.c
@@ -0,0 +1,513 @@
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/keycodes.h>
+#include <time.h>
+
+#include "bbutil.h"
+
+EGLDisplay egl_disp;
+EGLSurface egl_surf;
+
+static EGLConfig egl_conf;
+static EGLContext egl_ctx;
+
+static screen_context_t screen_ctx;
+static screen_window_t screen_win;
+static screen_display_t screen_disp;
+
+
+static void
+bbutil_egl_perror(const char *msg) {
+ static const char *errmsg[] = {
+ "function succeeded",
+ "EGL is not initialized, or could not be initialized, for the specified display",
+ "cannot access a requested resource",
+ "failed to allocate resources for the requested operation",
+ "an unrecognized attribute or attribute value was passed in an attribute list",
+ "an EGLConfig argument does not name a valid EGLConfig",
+ "an EGLContext argument does not name a valid EGLContext",
+ "the current surface of the calling thread is no longer valid",
+ "an EGLDisplay argument does not name a valid EGLDisplay",
+ "arguments are inconsistent",
+ "an EGLNativePixmapType argument does not refer to a valid native pixmap",
+ "an EGLNativeWindowType argument does not refer to a valid native window",
+ "one or more argument values are invalid",
+ "an EGLSurface argument does not name a valid surface configured for rendering",
+ "a power management event has occurred",
+ };
+
+ fprintf(stderr, "%s: %s\n", msg, errmsg[eglGetError() - EGL_SUCCESS]);
+}
+EGLConfig bbutil_choose_config(EGLDisplay egl_disp, enum RENDERING_API api) {
+ EGLConfig egl_conf = (EGLConfig)0;
+ EGLConfig *egl_configs;
+ EGLint egl_num_configs;
+ EGLint val;
+ EGLBoolean rc;
+ EGLint i;
+
+ rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglGetConfigs");
+ return egl_conf;
+ }
+ if (egl_num_configs == 0) {
+ fprintf(stderr, "eglGetConfigs: could not find a configuration\n");
+ return egl_conf;
+ }
+
+ egl_configs = malloc(egl_num_configs * sizeof(*egl_configs));
+ if (egl_configs == NULL) {
+ fprintf(stderr, "could not allocate memory for %d EGL configs\n", egl_num_configs);
+ return egl_conf;
+ }
+
+ rc = eglGetConfigs(egl_disp, egl_configs,
+ egl_num_configs, &egl_num_configs);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglGetConfigs");
+ free(egl_configs);
+ return egl_conf;
+ }
+
+ for (i = 0; i < egl_num_configs; i++) {
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
+ if (!(val & EGL_WINDOW_BIT)) {
+ continue;
+ }
+
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
+ if (!(val & api)) {
+ continue;
+ }
+
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
+ if ((api & (GL_ES_1|GL_ES_2)) && (val == 0)) {
+ continue;
+ }
+
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RED_SIZE, &val);
+ if (val != 8) {
+ continue;
+ }
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_GREEN_SIZE, &val);
+ if (val != 8) {
+ continue;
+ }
+
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_BLUE_SIZE, &val);
+ if (val != 8) {
+ continue;
+ }
+
+ eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_BUFFER_SIZE, &val);
+ if (val != 32) {
+ continue;
+ }
+
+ egl_conf = egl_configs[i];
+ break;
+ }
+
+ free(egl_configs);
+
+ if (egl_conf == (EGLConfig)0) {
+ fprintf(stderr, "bbutil_choose_config: could not find a matching configuration\n");
+ }
+
+ return egl_conf;
+}
+
+int
+bbutil_init_egl(screen_context_t ctx, enum RENDERING_API api) {
+ int usage;
+ int format = SCREEN_FORMAT_RGBX8888;
+ int nbuffers = 2;
+ EGLint interval = 1;
+ int rc;
+ EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+
+ if (api == GL_ES_1) {
+ usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION;
+ } else if (api == GL_ES_2) {
+ usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION;
+ } else if (api == VG) {
+ usage = SCREEN_USAGE_OPENVG | SCREEN_USAGE_ROTATION;
+ } else {
+ fprintf(stderr, "invalid api setting\n");
+ return EXIT_FAILURE;
+ }
+
+ //Simple egl initialization
+ screen_ctx = ctx;
+
+ egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (egl_disp == EGL_NO_DISPLAY) {
+ bbutil_egl_perror("eglGetDisplay");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglInitialize(egl_disp, NULL, NULL);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglInitialize");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ if ((api == GL_ES_1) || (api == GL_ES_2)) {
+ rc = eglBindAPI(EGL_OPENGL_ES_API);
+ } else if (api == VG) {
+ rc = eglBindAPI(EGL_OPENVG_API);
+ }
+
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglBindApi");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ egl_conf = bbutil_choose_config(egl_disp, api);
+ if (egl_conf == (EGLConfig)0) {
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ if (api == GL_ES_2) {
+ egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes);
+ } else {
+ egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, NULL);
+ }
+
+ if (egl_ctx == EGL_NO_CONTEXT) {
+ bbutil_egl_perror("eglCreateContext");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_create_window(&screen_win, screen_ctx);
+ if (rc) {
+ perror("screen_create_window");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format);
+ if (rc) {
+ perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
+ if (rc) {
+ perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp);
+ if (rc) {
+ perror("screen_get_window_property_pv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int screen_resolution[2];
+
+ rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution);
+ if (rc) {
+ perror("screen_get_display_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int angle = atoi(getenv("ORIENTATION"));
+
+ screen_display_mode_t screen_mode;
+ rc = screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode);
+ if (rc) {
+ perror("screen_get_display_property_pv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int size[2];
+ rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_get_window_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ int buffer_size[2] = {size[0], size[1]};
+
+ if ((angle == 0) || (angle == 180)) {
+ if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) ||
+ ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) {
+ buffer_size[1] = size[0];
+ buffer_size[0] = size[1];
+ }
+ } else if ((angle == 90) || (angle == 270)){
+ if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) ||
+ ((screen_mode.width < screen_mode.height && size[0] < size[1]))) {
+ buffer_size[1] = size[0];
+ buffer_size[0] = size[1];
+ }
+ } else {
+ fprintf(stderr, "Navigator returned an unexpected orientation angle.\n");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_create_window_buffers(screen_win, nbuffers);
+ if (rc) {
+ perror("screen_create_window_buffers");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_create_window_group(screen_win, get_window_group_id());
+ if (rc) {
+ perror("screen_create_window_group");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+ /* if (screen_create_window_group(screen_win, get_window_group_id()) != 0) goto fail; */
+
+ int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
+ screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode);
+
+ egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
+ if (egl_surf == EGL_NO_SURFACE) {
+ bbutil_egl_perror("eglCreateWindowSurface");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ rc = eglSwapInterval(egl_disp, interval);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapInterval");
+ bbutil_terminate();
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int
+bbutil_init_gl2d() {
+#if 0
+ EGLint surface_width, surface_height;
+
+ if ((egl_disp == EGL_NO_DISPLAY) || (egl_surf == EGL_NO_SURFACE) ){
+ return EXIT_FAILURE;
+ }
+
+ eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
+ eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
+
+ glShadeModel(GL_SMOOTH);
+
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ glViewport(0, 0, surface_width, surface_height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glOrthof(0.0f, (float)(surface_width) / (float)(surface_height), 0.0f, 1.0f, -1.0f, 1.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+#endif
+
+ return EXIT_SUCCESS;
+}
+
+int
+bbutil_init(screen_context_t ctx, enum RENDERING_API api) {
+ if (EXIT_SUCCESS != bbutil_init_egl(ctx, api)) {
+ return EXIT_FAILURE;
+ }
+
+ if ((GL_ES_1 == api) && (EXIT_SUCCESS != bbutil_init_gl2d())) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int bbutil_is_flipped() {
+
+ int ret;
+ screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_FLIP, &ret);
+ return ret;
+};
+
+int bbutil_get_rotation() {
+
+ int ret;
+ screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &ret);
+ return ret;
+};
+
+
+void
+bbutil_terminate() {
+ //Typical EGL cleanup
+ if (egl_disp != EGL_NO_DISPLAY) {
+ eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (egl_surf != EGL_NO_SURFACE) {
+ eglDestroySurface(egl_disp, egl_surf);
+ egl_surf = EGL_NO_SURFACE;
+ }
+ if (egl_ctx != EGL_NO_CONTEXT) {
+ eglDestroyContext(egl_disp, egl_ctx);
+ egl_ctx = EGL_NO_CONTEXT;
+ }
+ if (screen_win != NULL) {
+ screen_destroy_window(screen_win);
+ screen_win = NULL;
+ }
+ eglTerminate(egl_disp);
+ egl_disp = EGL_NO_DISPLAY;
+ }
+ eglReleaseThread();
+}
+
+void
+bbutil_swap() {
+ int rc = eglSwapBuffers(egl_disp, egl_surf);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapBuffers");
+ }
+}
+
+void
+bbutil_clear() {
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+char *
+get_window_group_id()
+{
+ static char s_window_group_id[16] = "";
+
+ if (s_window_group_id[0] == '\0') {
+ snprintf(s_window_group_id, sizeof(s_window_group_id), "%d", getpid());
+ }
+
+ return s_window_group_id;
+}
+
+
+int bbutil_rotate_screen_surface(int angle) {
+ int rc, rotation, skip = 1, temp;;
+ EGLint interval = 1;
+ int size[2];
+
+ if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
+ fprintf(stderr, "Invalid angle\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &rotation);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ switch (angle - rotation) {
+ case -270:
+ case -90:
+ case 90:
+ case 270:
+ temp = size[0];
+ size[0] = size[1];
+ size[1] = temp;
+ skip = 0;
+ break;
+ }
+
+ if (!skip) {
+ rc = eglMakeCurrent(egl_disp, NULL, NULL, NULL);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglDestroySurface(egl_disp, egl_surf);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+ egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
+ if (egl_surf == EGL_NO_SURFACE) {
+ bbutil_egl_perror("eglCreateWindowSurface");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglMakeCurrent");
+ return EXIT_FAILURE;
+ }
+
+ rc = eglSwapInterval(egl_disp, interval);
+ if (rc != EGL_TRUE) {
+ bbutil_egl_perror("eglSwapInterval");
+ return EXIT_FAILURE;
+ }
+ }
+
+ rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle);
+ if (rc) {
+ perror("screen_set_window_property_iv");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/platform/bb10/bbutil.h b/platform/bb10/bbutil.h
new file mode 100644
index 000000000..8df513cb7
--- /dev/null
+++ b/platform/bb10/bbutil.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* bbutil.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef _UTILITY_H_INCLUDED
+#define _UTILITY_H_INCLUDED
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <screen/screen.h>
+#include <sys/platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern EGLDisplay egl_disp;
+extern EGLSurface egl_surf;
+
+enum RENDERING_API {GL_ES_1 = EGL_OPENGL_ES_BIT, GL_ES_2 = EGL_OPENGL_ES2_BIT, VG = EGL_OPENVG_BIT};
+
+/**
+ * Initializes EGL, GL and loads a default font
+ *
+ * \param libscreen context that will be used for EGL setup
+ * \return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE
+ */
+int bbutil_init(screen_context_t ctx, enum RENDERING_API api);
+
+/**
+ * Initializes EGL
+ *
+ * \param libscreen context that will be used for EGL setup
+ * \return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE
+ */
+int bbutil_init_egl(screen_context_t ctx, enum RENDERING_API api);
+
+/**
+ * Initializes GL 1.1 for simple 2D rendering. GL2 initialization will be added at a later point.
+ *
+ * \return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE
+ */
+int bbutil_init_gl2d();
+
+int bbutil_is_flipped();
+int bbutil_get_rotation();
+
+char *get_window_group_id();
+
+int bbutil_rotate_screen_surface(int angle);
+
+/**
+ * Terminates EGL
+ */
+void bbutil_terminate();
+
+/**
+ * Swaps default bbutil window surface to the screen
+ */
+void bbutil_swap();
+
+/**
+ * Clears the screen of any existing text.
+ * NOTE: must be called after a successful return from bbutil_init() or bbutil_init_egl() call
+ */
+void bbutil_clear();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py
new file mode 100644
index 000000000..22940c0f2
--- /dev/null
+++ b/platform/bb10/detect.py
@@ -0,0 +1,91 @@
+import os
+import sys
+import string
+import methods
+
+
+def is_active():
+ return True
+
+def get_name():
+ return "BlackBerry 10"
+
+def can_build():
+
+ import os
+ if (not os.environ.has_key("QNX_TARGET")):
+ return False
+ return True
+
+def get_opts():
+
+ return [
+ ('QNX_HOST', 'path to qnx host', os.environ.get("QNX_HOST", 0)),
+ ('QNX_TARGET', 'path to qnx target', os.environ.get("QNX_TARGET", 0)),
+ ('QNX_CONFIGURATION', 'path to qnx configuration', os.environ.get("QNX_CONFIGURATION", 0)),
+ ('qnx_target', 'Qnx target (armle or x86', 'armle'),
+ ('bb10_payment_service', 'Enable Payment Service for BlackBerry10', 'yes'),
+ ('bb10_lgles_override', 'Force legacy GLES (1.1) on iOS', 'no'),
+ ('bb10_exceptions', 'Use exceptions when compiling on bb10', 'no'),
+ ]
+
+def get_flags():
+
+ return [
+ ('lua', 'no'),
+ ('tools', 'no'),
+ ('nedmalloc', 'no'),
+ ]
+
+def configure(env):
+
+ if env['PLATFORM'] == 'win32':
+ env.Tool('mingw')
+ env['SPAWN'] = methods.win32_spawn
+
+ env['qnx_target_ver'] = env['qnx_target']
+ if env['qnx_target'] == "armle":
+ env['qnx_prefix'] = 'ntoarmv7'
+ env['qnx_target_ver'] = 'armle-v7'
+ else:
+ env['qnx_prefix'] = 'ntox86'
+
+ env['OBJSUFFIX'] = ".qnx.${qnx_target}.o"
+ env['LIBSUFFIX'] = ".qnx.${qnx_target}.a"
+ env['PROGSUFFIX'] = ".qnx.${qnx_target}"
+ print("PROGSUFFIX: "+env['PROGSUFFIX']+" target: "+env['qnx_target'])
+
+ env.PrependENVPath('PATH', env['QNX_CONFIGURATION'] + '/bin')
+ env.PrependENVPath('PATH', env['QNX_CONFIGURATION'] + '/usr/bin')
+ env['ENV']['QNX_HOST'] = env['QNX_HOST']
+ env['ENV']['QNX_TARGET'] = env['QNX_TARGET']
+ env['ENV']['QNX_CONFIGURATION'] = env['QNX_CONFIGURATION']
+
+ env['CC'] = '$qnx_prefix-gcc'
+ env['CXX'] = '$qnx_prefix-g++'
+ env['AR'] = '$qnx_prefix-ar'
+ env['RANLIB'] = '$qnx_prefix-ranlib'
+
+ env.Append(CPPPATH = ['#platform/bb10'])
+ env.Append(LIBPATH = ['#platform/bb10/lib/$qnx_target', '#platform/bb10/lib/$qnx_target_ver'])
+ env.Append(CCFLAGS = string.split('-DBB10_ENABLED -DUNIX_ENABLED -DGLES2_ENABLED -DGLES1_ENABLED -D_LITTLE_ENDIAN -DNO_THREADS -DNO_FCNTL'))
+ if env['bb10_exceptions']=="yes":
+ env.Append(CCFLAGS = ['-fexceptions'])
+ else:
+ env.Append(CCFLAGS = ['-fno-exceptions'])
+
+ #env.Append(LINKFLAGS = string.split()
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['-O3','-DRELEASE_BUILD'])
+ env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['-g', '-O0','-DDEBUG_ENABLED', '-D_DEBUG'])
+ env.Append(LINKFLAGS=['-g'])
+
+ env.Append(LIBS=['bps', 'pps', 'screen', 'socket', 'EGL', 'GLESv2', 'GLESv1_CM', 'm', 'asound'])
+
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
new file mode 100644
index 000000000..0a19e71f0
--- /dev/null
+++ b/platform/bb10/export/export.cpp
@@ -0,0 +1,805 @@
+#include "version.h"
+#include "export.h"
+#include "tools/editor/editor_settings.h"
+#include "tools/editor/editor_import_export.h"
+#include "tools/editor/editor_node.h"
+#include "io/zip_io.h"
+#include "io/marshalls.h"
+#include "globals.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "platform/bb10/logo.h"
+#include "io/xml_parser.h"
+
+#define MAX_DEVICES 5
+
+class EditorExportPlatformBB10 : public EditorExportPlatform {
+
+ OBJ_TYPE( EditorExportPlatformBB10,EditorExportPlatform );
+
+ String custom_package;
+
+ int version_code;
+ String version_name;
+ String package;
+ String name;
+ String category;
+ String description;
+ String author_name;
+ String author_id;
+ String icon;
+
+
+
+ struct Device {
+
+ int index;
+ String name;
+ String description;
+ };
+
+ Vector<Device> devices;
+ bool devices_changed;
+ Mutex *device_lock;
+ Thread *device_thread;
+ Ref<ImageTexture> logo;
+
+ volatile bool quit_request;
+
+
+ static void _device_poll_thread(void *ud);
+
+ void _fix_descriptor(Vector<uint8_t>& p_manifest);
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ virtual String get_name() const { return "BlackBerry 10"; }
+ virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_ETC1; }
+ virtual Ref<Texture> get_logo() const { return logo; }
+
+
+ virtual bool poll_devices();
+ virtual int get_device_count() const;
+ virtual String get_device_name(int p_device) const;
+ virtual String get_device_info(int p_device) const;
+ virtual Error run(int p_device);
+
+ virtual bool requieres_password(bool p_debug) const { return !p_debug; }
+ virtual String get_binary_extension() const { return "bar"; }
+ virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+
+ virtual bool can_export(String *r_error=NULL) const;
+
+ EditorExportPlatformBB10();
+ ~EditorExportPlatformBB10();
+};
+
+bool EditorExportPlatformBB10::_set(const StringName& p_name, const Variant& p_value) {
+
+ String n=p_name;
+
+ if (n=="version/code")
+ version_code=p_value;
+ else if (n=="version/name")
+ version_name=p_value;
+ else if (n=="package/unique_name")
+ package=p_value;
+ else if (n=="package/category")
+ category=p_value;
+ else if (n=="package/name")
+ name=p_value;
+ else if (n=="package/description")
+ description=p_value;
+ else if (n=="package/icon")
+ icon=p_value;
+ else if (n=="package/custom_template")
+ custom_package=p_value;
+ else if (n=="release/author")
+ author_name=p_value;
+ else if (n=="release/author_id")
+ author_id=p_value;
+ else
+ return false;
+
+ return true;
+}
+
+bool EditorExportPlatformBB10::_get(const StringName& p_name,Variant &r_ret) const{
+
+ String n=p_name;
+
+ if (n=="version/code")
+ r_ret=version_code;
+ else if (n=="version/name")
+ r_ret=version_name;
+ else if (n=="package/unique_name")
+ r_ret=package;
+ else if (n=="package/category")
+ r_ret=category;
+ else if (n=="package/name")
+ r_ret=name;
+ else if (n=="package/description")
+ r_ret=description;
+ else if (n=="package/icon")
+ r_ret=icon;
+ else if (n=="package/custom_template")
+ r_ret=custom_package;
+ else if (n=="release/author")
+ r_ret=author_name;
+ else if (n=="release/author_id")
+ r_ret=author_id;
+ else
+ return false;
+
+ return true;
+}
+void EditorExportPlatformBB10::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ p_list->push_back( PropertyInfo( Variant::INT, "version/code", PROPERTY_HINT_RANGE,"1,65535,1"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "version/name") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/unique_name") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/category") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/name") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/description",PROPERTY_HINT_MULTILINE_TEXT) );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/custom_template", PROPERTY_HINT_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "release/author") );
+ p_list->push_back( PropertyInfo( Variant::STRING, "release/author_id") );
+
+ //p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
+
+}
+
+void EditorExportPlatformBB10::_fix_descriptor(Vector<uint8_t>& p_descriptor) {
+
+ String fpath = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp_bar-settings.xml");
+ {
+ FileAccessRef f = FileAccess::open(fpath,FileAccess::WRITE);
+ f->store_buffer(p_descriptor.ptr(),p_descriptor.size());
+ }
+
+ Ref<XMLParser> parser = memnew( XMLParser );
+ Error err = parser->open(fpath);
+ ERR_FAIL_COND(err!=OK);
+
+ String txt;
+ err = parser->read();
+ Vector<String> depth;
+
+ while(err!=ERR_FILE_EOF) {
+
+ ERR_FAIL_COND(err!=OK);
+
+ switch(parser->get_node_type()) {
+
+ case XMLParser::NODE_NONE: {
+ print_line("???");
+ } break;
+ case XMLParser::NODE_ELEMENT: {
+ String e="<";
+ e+=parser->get_node_name();
+ for(int i=0;i<parser->get_attribute_count();i++) {
+ e+=" ";
+ e+=parser->get_attribute_name(i)+"=\"";
+ e+=parser->get_attribute_value(i)+"\" ";
+ }
+
+
+
+ if (parser->is_empty()) {
+ e+="/";
+ } else {
+ depth.push_back(parser->get_node_name());
+ }
+
+ e+=">";
+ txt+=e;
+
+ } break;
+ case XMLParser::NODE_ELEMENT_END: {
+
+ txt+="</"+parser->get_node_name()+">";
+ if (depth.size() && depth[depth.size()-1]==parser->get_node_name()) {
+ depth.resize(depth.size()-1);
+ }
+
+
+ } break;
+ case XMLParser::NODE_TEXT: {
+ if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="id") {
+
+ txt+=package;
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="name") {
+
+ String aname;
+ if (this->name!="") {
+ aname=this->name;
+ } else {
+ aname = Globals::get_singleton()->get("application/name");
+
+ }
+
+ if (aname=="") {
+ aname=_MKSTR(VERSION_NAME);
+ }
+
+ txt+=aname;
+
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="versionNumber") {
+ txt+=itos(version_code);
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="description") {
+ txt+=description;
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="author") {
+ txt+=author_name;
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="authorId") {
+ txt+=author_id;
+ } else if (depth.size()==2 && depth[0]=="qnx" && depth[1]=="category") {
+ txt+=category;
+ } else {
+ txt+=parser->get_node_data();
+ }
+ } break;
+ case XMLParser::NODE_COMMENT: {
+ txt+="<!--"+parser->get_node_name()+"-->";
+ } break;
+ case XMLParser::NODE_CDATA: {
+ //ignore
+ //print_line("cdata");
+ } break;
+ case XMLParser::NODE_UNKNOWN: {
+ //ignore
+ txt+="<"+parser->get_node_name()+">";
+ } break;
+ }
+
+ err = parser->read();
+ }
+
+
+ CharString cs = txt.utf8();
+ p_descriptor.resize(cs.length());
+ for(int i=0;i<cs.length();i++)
+ p_descriptor[i]=cs[i];
+
+}
+
+
+
+Error EditorExportPlatformBB10::export_project(const String& p_path,bool p_debug,const String& p_password) {
+
+
+ EditorProgress ep("export","Exporting for BlackBerry 10",104);
+
+ String template_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
+
+ String src_template=custom_package!=""?custom_package:template_path.plus_file("bb10.zip");
+
+
+ FileAccess *src_f=NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+
+ ep.step("Creating FileSystem for BAR",0);
+
+ unzFile pkg = unzOpen2(src_template.utf8().get_data(), &io);
+ if (!pkg) {
+
+ EditorNode::add_io_error("Could not find template zip to export:\n"+src_template);
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->change_dir(EditorSettings::get_singleton()->get_settings_path());
+
+
+ if (da->change_dir("tmp")!=OK) {
+ da->make_dir("tmp");
+ if (da->change_dir("tmp")!=OK)
+ return ERR_CANT_CREATE;
+ }
+
+ if (da->change_dir("bb10_export")!=OK) {
+ da->make_dir("bb10_export");
+ if (da->change_dir("bb10_export")!=OK) {
+ return ERR_CANT_CREATE;
+ }
+ }
+
+
+ String bar_dir = da->get_current_dir();
+ if (bar_dir.ends_with("/")) {
+ bar_dir=bar_dir.substr(0,bar_dir.length()-1);
+ }
+
+ //THIS IS SUPER, SUPER DANGEROUS!!!!
+ //CAREFUL WITH THIS CODE, MIGHT DELETE USERS HARD DRIVE OR HOME DIR
+ //EXTRA CHECKS ARE IN PLACE EVERYWERE TO MAKE SURE NOTHING BAD HAPPENS BUT STILL....
+ //BE SUPER CAREFUL WITH THIS PLEASE!!!
+ //BLACKBERRY THIS IS YOUR FAULT FOR NOT MAKING A BETTER WAY!!
+
+ if (bar_dir.ends_with("bb10_export")) {
+ Error err = da->erase_contents_recursive();
+ if (err!=OK) {
+ EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
+ ERR_FAIL_COND_V(err!=OK,err);
+ }
+
+ } else {
+ print_line("ARE YOU CRAZY??? THIS IS A SERIOUS BUG HERE!!!");
+ ERR_FAIL_V(ERR_OMFG_THIS_IS_VERY_VERY_BAD);
+ }
+
+
+ ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
+ int ret = unzGoToFirstFile(pkg);
+
+
+
+ while(ret==UNZ_OK) {
+
+ //get filename
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
+
+ String file=fname;
+
+ Vector<uint8_t> data;
+ data.resize(info.uncompressed_size);
+
+ //read
+ unzOpenCurrentFile(pkg);
+ unzReadCurrentFile(pkg,data.ptr(),data.size());
+ unzCloseCurrentFile(pkg);
+
+ //write
+
+ if (file=="bar-descriptor.xml") {
+
+ _fix_descriptor(data);
+ }
+
+ if (file=="icon.png") {
+ bool found=false;
+
+ if (this->icon!="" && this->icon.ends_with(".png")) {
+
+ FileAccess *f = FileAccess::open(this->icon,FileAccess::READ);
+ if (f) {
+
+ data.resize(f->get_len());
+ f->get_buffer(data.ptr(),data.size());
+ memdelete(f);
+ found=true;
+ }
+
+ }
+
+ if (!found) {
+
+ String appicon = Globals::get_singleton()->get("application/icon");
+ if (appicon!="" && appicon.ends_with(".png")) {
+ FileAccess*f = FileAccess::open(appicon,FileAccess::READ);
+ if (f) {
+ data.resize(f->get_len());
+ f->get_buffer(data.ptr(),data.size());
+ memdelete(f);
+ }
+ }
+ }
+ }
+
+
+ if (file.find("/")) {
+
+ da->make_dir_recursive(file.get_base_dir());
+ }
+
+ FileAccessRef wf = FileAccess::open(bar_dir.plus_file(file),FileAccess::WRITE);
+ wf->store_buffer(data.ptr(),data.size());
+
+ ret = unzGoToNextFile(pkg);
+ }
+
+ ep.step("Finding Files..",1);
+
+ Vector<StringName> files=get_dependencies(false);
+
+ ep.step("Adding Files..",2);
+
+ da->change_dir(bar_dir);
+ da->make_dir("assets");
+ Error err = da->change_dir("assets");
+ ERR_FAIL_COND_V(err,err);
+
+ String asset_dir=da->get_current_dir();
+ if (!asset_dir.ends_with("/"))
+ asset_dir+="/";
+
+ for(int i=0;i<files.size();i++) {
+
+ String fname=files[i];
+ Vector<uint8_t> data = get_exported_file(fname);
+ /*
+ FileAccess *f=FileAccess::open(files[i],FileAccess::READ);
+ if (!f) {
+ EditorNode::add_io_error("Couldn't read: "+String(files[i]));
+ }
+ ERR_CONTINUE(!f);
+ data.resize(f->get_len());
+ f->get_buffer(data.ptr(),data.size());
+*/
+ String dst_path=fname;
+ dst_path=dst_path.replace_first("res://",asset_dir);
+
+ da->make_dir_recursive(dst_path.get_base_dir());
+
+ ep.step("Adding File: "+String(files[i]).get_file(),3+i*100/files.size());
+
+ FileAccessRef fr = FileAccess::open(dst_path,FileAccess::WRITE);
+ fr->store_buffer(data.ptr(),data.size());
+ }
+
+
+ ep.step("Creating BAR Package..",104);
+
+ String bb_packager=EditorSettings::get_singleton()->get("blackberry/host_tools");
+ bb_packager=bb_packager.plus_file("blackberry-nativepackager");
+ if (OS::get_singleton()->get_name()=="Windows")
+ bb_packager+=".exe";
+
+
+ if (!FileAccess::exists(bb_packager)) {
+ EditorNode::add_io_error("Can't find packager:\n"+bb_packager);
+ return ERR_CANT_OPEN;
+ }
+
+ List<String> args;
+ args.push_back("-package");
+ args.push_back(p_path);
+ if (p_debug) {
+
+ String debug_token=EditorSettings::get_singleton()->get("blackberry/debug_token");
+ if (!FileAccess::exists(debug_token)) {
+ EditorNode::add_io_error("Debug token not found!");
+ } else {
+ args.push_back("-debugToken");
+ args.push_back(debug_token);
+ }
+ args.push_back("-devMode");
+ args.push_back("-configuration");
+ args.push_back("Device-Debug");
+ } else {
+
+ args.push_back("-configuration");
+ args.push_back("Device-Release");
+ }
+ args.push_back(bar_dir.plus_file("bar-descriptor.xml"));
+
+ int ec;
+
+ err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
+
+ if (err!=OK)
+ return err;
+ if (ec!=0)
+ return ERR_CANT_CREATE;
+
+ return OK;
+
+}
+
+
+bool EditorExportPlatformBB10::poll_devices() {
+
+ bool dc=devices_changed;
+ devices_changed=false;
+ return dc;
+}
+
+int EditorExportPlatformBB10::get_device_count() const {
+
+ device_lock->lock();
+ int dc=devices.size();
+ device_lock->unlock();
+
+ return dc;
+
+}
+String EditorExportPlatformBB10::get_device_name(int p_device) const {
+
+ ERR_FAIL_INDEX_V(p_device,devices.size(),"");
+ device_lock->lock();
+ String s=devices[p_device].name;
+ device_lock->unlock();
+ return s;
+}
+String EditorExportPlatformBB10::get_device_info(int p_device) const {
+
+ ERR_FAIL_INDEX_V(p_device,devices.size(),"");
+ device_lock->lock();
+ String s=devices[p_device].description;
+ device_lock->unlock();
+ return s;
+}
+
+void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
+
+ EditorExportPlatformBB10 *ea=(EditorExportPlatformBB10 *)ud;
+
+ while(!ea->quit_request) {
+
+ String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
+ bb_deploy=bb_deploy.plus_file("blackberry-deploy");
+ bool windows = OS::get_singleton()->get_name()=="Windows";
+ if (windows)
+ bb_deploy+=".exe";
+
+ if (!FileAccess::exists(bb_deploy)) {
+ OS::get_singleton()->delay_usec(3000000);
+ continue; //adb not configured
+ }
+
+ Vector<Device> devices;
+
+
+ for (int i=0;i<MAX_DEVICES;i++) {
+
+ String host = EditorSettings::get_singleton()->get("blackberry/device_"+itos(i+1)+"/host");
+ if (host==String())
+ continue;
+ String pass = EditorSettings::get_singleton()->get("blackberry/device_"+itos(i+1)+"/password");
+ if (pass==String())
+ continue;
+
+ List<String> args;
+ args.push_back("-listDeviceInfo");
+ args.push_back(host);
+ args.push_back("-password");
+ args.push_back(pass);
+
+
+ int ec;
+ String dp;
+
+ Error err = OS::get_singleton()->execute(bb_deploy,args,true,NULL,&dp,&ec);
+
+ if (err==OK && ec==0) {
+
+ Device dev;
+ dev.index=i;
+ String descr;
+ Vector<String> ls=dp.split("\n");
+
+ for(int i=0;i<ls.size();i++) {
+
+ String l = ls[i].strip_edges();
+ if (l.begins_with("modelfullname::")) {
+ dev.name=l.get_slice("::",1);
+ descr+="Model: "+dev.name+"\n";
+ }
+ if (l.begins_with("modelnumber::")) {
+ String s = l.get_slice("::",1);
+ dev.name+=" ("+s+")";
+ descr+="Model Number: "+s+"\n";
+ }
+ if (l.begins_with("scmbundle::"))
+ descr+="OS Version: "+l.get_slice("::",1)+"\n";
+ if (l.begins_with("[n]debug_token_expiration::"))
+ descr+="Debug Token Expires:: "+l.get_slice("::",1)+"\n";
+
+ }
+
+ dev.description=descr;
+ devices.push_back(dev);
+ }
+
+ }
+
+ bool changed=false;
+
+
+ ea->device_lock->lock();
+
+ if (ea->devices.size()!=devices.size()) {
+ changed=true;
+ } else {
+
+ for(int i=0;i<ea->devices.size();i++) {
+
+ if (ea->devices[i].index!=devices[i].index) {
+ changed=true;
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+
+ ea->devices=devices;
+ ea->devices_changed=true;
+ }
+
+ ea->device_lock->unlock();
+
+ OS::get_singleton()->delay_usec(3000000);
+
+ }
+
+}
+
+Error EditorExportPlatformBB10::run(int p_device) {
+
+ ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
+
+ String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
+ bb_deploy=bb_deploy.plus_file("blackberry-deploy");
+ if (OS::get_singleton()->get_name()=="Windows")
+ bb_deploy+=".exe";
+
+ if (!FileAccess::exists(bb_deploy)) {
+ EditorNode::add_io_error("Blackberry Deploy not found:\n"+bb_deploy);
+ return ERR_FILE_NOT_FOUND;
+ }
+
+
+ device_lock->lock();
+
+
+ EditorProgress ep("run","Running on "+devices[p_device].name,3);
+
+ //export_temp
+ ep.step("Exporting APK",0);
+
+ String export_to=EditorSettings::get_singleton()->get_settings_path().plus_file("/tmp/tmpexport.bar");
+ Error err = export_project(export_to,true);
+ if (err) {
+ device_lock->unlock();
+ return err;
+ }
+#if 0
+ ep.step("Uninstalling..",1);
+
+ print_line("Uninstalling previous version: "+devices[p_device].name);
+ List<String> args;
+ args.push_back("-s");
+ args.push_back(devices[p_device].id);
+ args.push_back("uninstall");
+ args.push_back(package);
+ int rv;
+ err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv);
+
+ if (err || rv!=0) {
+ EditorNode::add_io_error("Could not install to device.");
+ device_lock->unlock();
+ return ERR_CANT_CREATE;
+ }
+
+ print_line("Installing into device (please wait..): "+devices[p_device].name);
+
+#endif
+ ep.step("Installing to Device (please wait..)..",2);
+
+ List<String> args;
+ args.clear();
+ args.push_back("-installApp");
+ args.push_back("-launchApp");
+ args.push_back("-device");
+ int idx = devices[p_device].index;
+ String host = EditorSettings::get_singleton()->get("blackberry/device_"+itos(p_device+1)+"/host");
+ String pass = EditorSettings::get_singleton()->get("blackberry/device_"+itos(p_device+1)+"/password");
+ args.push_back(host);
+ args.push_back("-password");
+ args.push_back(pass);
+ args.push_back(export_to);
+
+ int rv;
+ err = OS::get_singleton()->execute(bb_deploy,args,true,NULL,NULL,&rv);
+ if (err || rv!=0) {
+ EditorNode::add_io_error("Could not install to device.");
+ device_lock->unlock();
+ return ERR_CANT_CREATE;
+ }
+
+ device_lock->unlock();
+ return OK;
+
+
+}
+
+
+EditorExportPlatformBB10::EditorExportPlatformBB10() {
+
+ version_code=1;
+ version_name="1.0";
+ package="com.godot.noname";
+ category="core.games";
+ name="";
+ author_name="Cert. Name";
+ author_id="Cert. ID";
+ description="Game made with Godot Engine";
+
+ device_lock = Mutex::create();
+ quit_request=false;
+
+ device_thread=Thread::create(_device_poll_thread,this);
+ devices_changed=true;
+
+ Image img( _bb10_logo );
+ logo = Ref<ImageTexture>( memnew( ImageTexture ));
+ logo->create_from_image(img);
+}
+
+bool EditorExportPlatformBB10::can_export(String *r_error) const {
+
+ bool valid=true;
+ String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
+ String err;
+
+ if (!FileAccess::exists(bb_deploy.plus_file("blackberry-deploy"))) {
+
+ valid=false;
+ err+="Blackberry host tools not configured in editor settings.\n";
+ }
+
+ String exe_path = EditorSettings::get_singleton()->get_settings_path()+"/templates/";
+
+ if (!FileAccess::exists(exe_path+"bb10.zip")) {
+ valid=false;
+ err+="No export template found.\nDownload and install export templates.\n";
+ }
+
+ String debug_token=EditorSettings::get_singleton()->get("blackberry/debug_token");
+
+ if (!FileAccess::exists(debug_token)) {
+ valid=false;
+ err+="No debug token set, will not be able to test on device.\n";
+ }
+
+
+ if (custom_package!="" && !FileAccess::exists(custom_package)) {
+ valid=false;
+ err+="Custom release package not found.\n";
+ }
+
+ if (r_error)
+ *r_error=err;
+
+ return valid;
+}
+
+
+EditorExportPlatformBB10::~EditorExportPlatformBB10() {
+
+ quit_request=true;
+ Thread::wait_to_finish(device_thread);
+}
+
+
+void register_bb10_exporter() {
+
+ EDITOR_DEF("blackberry/host_tools","");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"blackberry/host_tools",PROPERTY_HINT_GLOBAL_DIR));
+ EDITOR_DEF("blackberry/debug_token","");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"blackberry/debug_token",PROPERTY_HINT_GLOBAL_FILE,"bar"));
+ EDITOR_DEF("blackberry/device_1/host","");
+ EDITOR_DEF("blackberry/device_1/password","");
+ EDITOR_DEF("blackberry/device_2/host","");
+ EDITOR_DEF("blackberry/device_2/password","");
+ EDITOR_DEF("blackberry/device_3/host","");
+ EDITOR_DEF("blackberry/device_3/password","");
+ EDITOR_DEF("blackberry/device_4/host","");
+ EDITOR_DEF("blackberry/device_4/password","");
+ EDITOR_DEF("blackberry/device_5/host","");
+ EDITOR_DEF("blackberry/device_5/password","");
+
+ Ref<EditorExportPlatformBB10> exporter = Ref<EditorExportPlatformBB10>( memnew(EditorExportPlatformBB10) );
+ EditorImportExport::get_singleton()->add_export_platform(exporter);
+
+
+}
+
diff --git a/platform/bb10/export/export.h b/platform/bb10/export/export.h
new file mode 100644
index 000000000..06c7a681b
--- /dev/null
+++ b/platform/bb10/export/export.h
@@ -0,0 +1,3 @@
+
+
+void register_bb10_exporter();
diff --git a/platform/bb10/godot_bb10.cpp b/platform/bb10/godot_bb10.cpp
new file mode 100644
index 000000000..f7e154d64
--- /dev/null
+++ b/platform/bb10/godot_bb10.cpp
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* godot_bb10.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "main/main.h"
+#include "os_bb10.h"
+
+#include <unistd.h>
+
+int main(int argc, char* argv[]) {
+
+ OSBB10 os;
+
+ Error err = Main::setup(argv[0],argc-1,&argv[1]);
+ if (err!=OK)
+ return 255;
+
+ if (Main::start())
+ os.run(); // it is actually the OS that decides how to run
+ Main::cleanup();
+
+ return os.get_exit_code();
+}
+
diff --git a/platform/bb10/logo.png b/platform/bb10/logo.png
new file mode 100644
index 000000000..d0fb1966a
--- /dev/null
+++ b/platform/bb10/logo.png
Binary files differ
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
new file mode 100644
index 000000000..ff43a68b1
--- /dev/null
+++ b/platform/bb10/os_bb10.cpp
@@ -0,0 +1,630 @@
+/*************************************************************************/
+/* os_bb10.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "os_bb10.h"
+
+#include "drivers/gles2/rasterizer_gles2.h"
+#include "drivers/gles1/rasterizer_gles1.h"
+#include "servers/visual/visual_server_raster.h"
+#include "core/os/dir_access.h"
+
+#include "core/globals.h"
+#include "main/main.h"
+#include "bbutil.h"
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include "core/os/keyboard.h"
+
+#include "bps/bps.h"
+#include "bps/screen.h"
+#include "bps/navigator.h"
+#include "bps/accelerometer.h"
+#include "bps/orientation.h"
+#include "bps/virtualkeyboard.h"
+#include "bps/audiodevice.h"
+
+#ifdef BB10_SCORELOOP_ENABLED
+#include "modules/scoreloop/scoreloop_bb10.h"
+#endif
+
+static char launch_dir[512];
+char* launch_dir_ptr;
+
+int OSBB10::get_video_driver_count() const {
+
+ return 1;
+}
+const char * OSBB10::get_video_driver_name(int p_driver) const {
+
+ return "GLES2";
+}
+
+OS::VideoMode OSBB10::get_default_video_mode() const {
+
+ return OS::VideoMode();
+}
+
+int OSBB10::get_audio_driver_count() const {
+
+ return 1;
+}
+const char * OSBB10::get_audio_driver_name(int p_driver) const {
+
+ return "BB10";
+}
+
+void OSBB10::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
+
+ data_dir = getenv("HOME");
+
+ //Create a screen context that will be used to create an EGL surface to to receive libscreen events
+ screen_create_context(&screen_cxt,0);
+
+ //Initialize BPS library
+ bps_initialize();
+
+ //Use utility code to initialize EGL for 2D rendering with GL ES 1.1
+ enum RENDERING_API api = GL_ES_2;
+ #ifdef BB10_LGLES_OVERRIDE
+ api = GL_ES_1;
+ #endif
+ if (EXIT_SUCCESS != bbutil_init(screen_cxt, api)) {
+ bbutil_terminate();
+ screen_destroy_context(screen_cxt);
+ return;
+ };
+
+ EGLint surface_width, surface_height;
+
+ eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
+ eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
+ printf("screen size: %ix%i\n", surface_width, surface_height);
+ VideoMode mode;
+ mode.width = surface_width;
+ mode.height = surface_height;
+ mode.fullscreen = true;
+ mode.resizable = false;
+ set_video_mode(mode);
+
+ //Signal BPS library that navigator and screen events will be requested
+ screen_request_events(screen_cxt);
+ navigator_request_events(0);
+ virtualkeyboard_request_events(0);
+ audiodevice_request_events(0);
+
+ #ifdef DEBUG_ENABLED
+ bps_set_verbosity(3);
+ #endif
+
+ accel_supported = accelerometer_is_supported();
+ if (accel_supported)
+ accelerometer_set_update_frequency(FREQ_40_HZ);
+ pitch = 0;
+ roll = 0;
+
+ #ifdef BB10_LGLES_OVERRIDE
+ rasterizer = memnew( RasterizerGLES1(false) );
+ #else
+ rasterizer = memnew( RasterizerGLES2(false, false) );
+ #endif
+
+ visual_server = memnew( VisualServerRaster(rasterizer) );
+ visual_server->init();
+ visual_server->cursor_set_visible(false, 0);
+
+ audio_driver = memnew(AudioDriverBB10);
+ audio_driver->set_singleton();
+ audio_driver->init(NULL);
+
+ sample_manager = memnew( SampleManagerMallocSW );
+ audio_server = memnew( AudioServerSW(sample_manager) );
+ audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
+ audio_server->init();
+
+ spatial_sound_server = memnew( SpatialSoundServerSW );
+ spatial_sound_server->init();
+
+ spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
+ spatial_sound_2d_server->init();
+
+ //
+ physics_server = memnew( PhysicsServerSW );
+ physics_server->init();
+ physics_2d_server = memnew( Physics2DServerSW );
+ physics_2d_server->init();
+
+ input = memnew( InputDefault );
+
+ #ifdef PAYMENT_SERVICE_ENABLED
+ payment_service = memnew(PaymentService);
+ Globals::get_singleton()->add_singleton(Globals::Singleton("InAppStore", payment_service));
+ #endif
+
+}
+
+void OSBB10::set_main_loop( MainLoop * p_main_loop ) {
+
+ input->set_main_loop(p_main_loop);
+ main_loop=p_main_loop;
+}
+
+void OSBB10::delete_main_loop() {
+
+ memdelete( main_loop );
+ main_loop = NULL;
+}
+
+void OSBB10::finalize() {
+
+ if(main_loop)
+ memdelete(main_loop);
+ main_loop=NULL;
+
+ spatial_sound_server->finish();
+ memdelete(spatial_sound_server);
+ spatial_sound_2d_server->finish();
+ memdelete(spatial_sound_2d_server);
+
+ //if (debugger_connection_console) {
+// memdelete(debugger_connection_console);
+//}
+
+ audio_server->finish();
+ memdelete(audio_server);
+ memdelete(sample_manager);
+
+ visual_server->finish();
+ memdelete(visual_server);
+ memdelete(rasterizer);
+
+ physics_server->finish();
+ memdelete(physics_server);
+
+ physics_2d_server->finish();
+ memdelete(physics_2d_server);
+
+ #ifdef PAYMENT_SERVICE_ENABLED
+ memdelete(payment_service);
+ #endif
+
+ memdelete(input);
+
+ bbutil_terminate();
+ screen_destroy_context(screen_cxt);
+
+ bps_shutdown();
+}
+
+void OSBB10::set_mouse_show(bool p_show) {
+
+ //android has no mouse...
+}
+
+void OSBB10::set_mouse_grab(bool p_grab) {
+
+ //it really has no mouse...!
+}
+
+bool OSBB10::is_mouse_grab_enabled() const {
+
+ //*sigh* technology has evolved so much since i was a kid..
+ return false;
+}
+Point2 OSBB10::get_mouse_pos() const {
+
+ return Point2();
+}
+int OSBB10::get_mouse_button_state() const {
+
+ return 0;
+}
+void OSBB10::set_window_title(const String& p_title) {
+
+
+}
+
+//interesting byt not yet
+//void set_clipboard(const String& p_text);
+//String get_clipboard() const;
+
+void OSBB10::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
+
+ default_videomode = p_video_mode;
+}
+
+OS::VideoMode OSBB10::get_video_mode(int p_screen) const {
+
+ return default_videomode;
+}
+void OSBB10::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
+
+ p_list->push_back(default_videomode);
+}
+
+String OSBB10::get_name() {
+
+ return "BlackBerry 10";
+}
+
+MainLoop *OSBB10::get_main_loop() const {
+
+ return main_loop;
+}
+
+bool OSBB10::can_draw() const {
+
+ return !minimized;
+}
+
+void OSBB10::set_cursor_shape(CursorShape p_shape) {
+
+ //android really really really has no mouse.. how amazing..
+}
+
+void OSBB10::handle_screen_event(bps_event_t *event) {
+
+ screen_event_t screen_event = screen_event_get_event(event);
+
+ int screen_val;
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val);
+
+ int pos[2];
+
+ switch (screen_val) {
+ case SCREEN_EVENT_MTOUCH_TOUCH:
+ case SCREEN_EVENT_MTOUCH_RELEASE: {
+
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_POSITION, pos);
+
+ InputEvent ievent;
+ ievent.type = InputEvent::SCREEN_TOUCH;
+ ievent.ID = ++last_id;
+ ievent.device = 0;
+ ievent.screen_touch.pressed = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH);
+ ievent.screen_touch.x = pos[0];
+ ievent.screen_touch.y = pos[1];
+ Point2 mpos(ievent.screen_touch.x, ievent.screen_touch.y);
+
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pos[0]);
+ ievent.screen_touch.index = pos[0];
+
+ last_touch_x[pos[0]] = ievent.screen_touch.x;
+ last_touch_y[pos[0]] = ievent.screen_touch.y;
+
+ input->parse_input_event( ievent );
+
+ if (ievent.screen_touch.index == 0) {
+
+ InputEvent ievent;
+ ievent.type = InputEvent::MOUSE_BUTTON;
+ ievent.ID = ++last_id;
+ ievent.device = 0;
+ ievent.mouse_button.pressed = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH);
+ ievent.mouse_button.button_index = BUTTON_LEFT;
+ ievent.mouse_button.doubleclick = 0;
+ ievent.mouse_button.x = ievent.mouse_button.global_x = mpos.x;
+ ievent.mouse_button.y = ievent.mouse_button.global_y = mpos.y;
+ input->parse_input_event( ievent );
+ };
+
+
+ } break;
+ case SCREEN_EVENT_MTOUCH_MOVE: {
+
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_POSITION, pos);
+
+ InputEvent ievent;
+ ievent.type = InputEvent::SCREEN_DRAG;
+ ievent.ID = ++last_id;
+ ievent.device = 0;
+ ievent.screen_drag.x = pos[0];
+ ievent.screen_drag.y = pos[1];
+
+ /*
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pos);
+ ievent.screen_drag.relative_x = ievent.screen_drag.x - pos[0];
+ ievent.screen_drag.relative_y = ievent.screen_drag.y - pos[1];
+ */
+
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pos[0]);
+ ievent.screen_drag.index = pos[0];
+
+
+ ievent.screen_drag.relative_x = ievent.screen_drag.x - last_touch_x[ievent.screen_drag.index];
+ ievent.screen_drag.relative_y = ievent.screen_drag.y - last_touch_y[ievent.screen_drag.index];
+
+ last_touch_x[ievent.screen_drag.index] = ievent.screen_drag.x;
+ last_touch_y[ievent.screen_drag.index] = ievent.screen_drag.y;
+
+ Point2 mpos(ievent.screen_drag.x, ievent.screen_drag.y);
+ Point2 mrel(ievent.screen_drag.relative_x, ievent.screen_drag.relative_y);
+
+ input->parse_input_event( ievent );
+
+ if (ievent.screen_touch.index == 0) {
+
+ InputEvent ievent;
+ ievent.type = InputEvent::MOUSE_MOTION;
+ ievent.ID = ++last_id;
+ ievent.device = 0;
+ ievent.mouse_motion.x = ievent.mouse_motion.global_x = mpos.x;
+ ievent.mouse_motion.y = ievent.mouse_motion.global_y = mpos.y;
+ input->set_mouse_pos(Point2(ievent.mouse_motion.x,ievent.mouse_motion.y));
+ ievent.mouse_motion.speed_x=input->get_mouse_speed().x;
+ ievent.mouse_motion.speed_y=input->get_mouse_speed().y;
+ ievent.mouse_motion.relative_x = mrel.x;
+ ievent.mouse_motion.relative_y = mrel.y;
+ ievent.mouse_motion.button_mask = 1; // pressed
+
+ input->parse_input_event( ievent );
+ };
+ } break;
+
+ case SCREEN_EVENT_KEYBOARD: {
+
+ InputEvent ievent;
+ ievent.type = InputEvent::KEY;
+ ievent.ID = ++last_id;
+ ievent.device = 0;
+ int val = 0;
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SCAN, &val);
+ ievent.key.scancode = val;
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &val);
+ ievent.key.unicode = val;
+ if (val == 61448) {
+ ievent.key.scancode = KEY_BACKSPACE;
+ ievent.key.unicode = KEY_BACKSPACE;
+ };
+ if (val == 61453) {
+ ievent.key.scancode = KEY_ENTER;
+ ievent.key.unicode = KEY_ENTER;
+ };
+
+ int flags;
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
+ ievent.key.pressed = flags & 1; // bit 1 is pressed apparently
+
+ int mod;
+ screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
+
+ input->parse_input_event( ievent );
+ } break;
+
+ default:
+ break;
+
+ }
+};
+
+void OSBB10::handle_accelerometer() {
+
+ if (!accel_supported)
+ return;
+
+ if (!fullscreen)
+ return;
+
+ double force_x, force_y, force_z;
+ accelerometer_read_forces(&force_x, &force_y, &force_z);
+ Vector3 accel = Vector3(force_x, flip_accelerometer ? force_y : -force_y, force_z);
+ input->set_accelerometer(accel);
+ // rotate 90 degrees
+ //input->set_accelerometer(Vector3(force_y, flip_accelerometer?force_x:(-force_x), force_z));
+};
+
+
+void OSBB10::_resize(bps_event_t* event) {
+
+ int angle = navigator_event_get_orientation_angle(event);
+ bbutil_rotate_screen_surface(angle);
+
+ EGLint surface_width, surface_height;
+ eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
+ eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
+
+ VideoMode mode;
+ mode.width = surface_width;
+ mode.height = surface_height;
+ mode.fullscreen = true;
+ mode.resizable = false;
+ set_video_mode(mode);
+};
+
+void OSBB10::process_events() {
+
+ handle_accelerometer();
+
+ bps_event_t *event = NULL;
+
+ do {
+ int rc = bps_get_event(&event, 0);
+ assert(rc == BPS_SUCCESS);
+
+ if (!event) break;
+
+ #ifdef BB10_SCORELOOP_ENABLED
+ ScoreloopBB10* sc = Globals::get_singleton()->get_singleton_object("Scoreloop")->cast_to<ScoreloopBB10>();
+ if (sc->handle_event(event))
+ continue;
+ #endif
+
+ #ifdef PAYMENT_SERVICE_ENABLED
+ if (payment_service->handle_event(event))
+ continue;
+ #endif
+
+ int domain = bps_event_get_domain(event);
+ if (domain == screen_get_domain()) {
+
+ handle_screen_event(event);
+
+ } else if (domain == navigator_get_domain()) {
+
+ if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
+ if (main_loop)
+ main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
+ bps_event_destroy(event);
+ exit(0);
+ return;
+ /*
+ } else if (bps_event_get_code(event) == NAVIGATOR_ORIENTATION_CHECK) {
+
+ int angle = navigator_event_get_orientation_angle(event);
+ navigator_orientation_check_response(event, false);
+
+ } else if (bps_event_get_code(event) == NAVIGATOR_ORIENTATION) {
+
+ _resize(event);
+ */
+ } else if (bps_event_get_code(event) == NAVIGATOR_WINDOW_STATE) {
+
+ int state = navigator_event_get_window_state(event);
+ bool was_fullscreen = fullscreen;
+ minimized = state == NAVIGATOR_WINDOW_INVISIBLE;
+ fullscreen = state == NAVIGATOR_WINDOW_FULLSCREEN;
+ set_low_processor_usage_mode(!fullscreen);
+ if (fullscreen != was_fullscreen) {
+ if (fullscreen) {
+ audio_server->set_fx_global_volume_scale(fullscreen_mixer_volume);
+ audio_server->set_stream_global_volume_scale(fullscreen_stream_volume);
+ } else {
+ fullscreen_mixer_volume = audio_server->get_fx_global_volume_scale();
+ fullscreen_stream_volume = audio_server->get_stream_global_volume_scale();
+ audio_server->set_fx_global_volume_scale(0);
+ audio_server->set_stream_global_volume_scale(0);
+ };
+ };
+ };
+ } else if (domain == audiodevice_get_domain()) {
+
+ const char * audiodevice_path = audiodevice_event_get_path(event);
+ printf("************* got audiodevice event, path %s\n", audiodevice_path);
+ audio_driver->finish();
+ audio_driver->init(audiodevice_path);
+ audio_driver->start();
+ };
+
+ //bps_event_destroy(event);
+ } while (event);
+};
+
+bool OSBB10::has_virtual_keyboard() const {
+
+ return true;
+};
+
+void OSBB10::show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect) {
+
+ virtualkeyboard_show();
+};
+
+void OSBB10::hide_virtual_keyboard() {
+
+ virtualkeyboard_hide();
+};
+
+void OSBB10::run() {
+
+ if (!main_loop)
+ return;
+
+ main_loop->init();
+
+ int flip = bbutil_is_flipped();
+ int rot = bbutil_get_rotation();
+ flip_accelerometer = rot == 90;
+ printf("**************** rot is %i, flip %i\n", rot, (int)flip_accelerometer);
+ /*
+ orientation_direction_t orientation;
+ int angle;
+ orientation_get(&orientation, &angle);
+ printf("******************** orientation %i, %i, %i\n", orientation, ORIENTATION_BOTTOM_UP, ORIENTATION_TOP_UP);
+ if (orientation == ORIENTATION_BOTTOM_UP) {
+ flip_accelerometer = true;
+ };
+ */
+
+
+ while (true) {
+
+ process_events(); // get rid of pending events
+ if (Main::iteration()==true)
+ break;
+ bbutil_swap();
+ //#ifdef DEBUG_ENABLED
+ fflush(stdout);
+ //#endif
+ };
+
+ main_loop->finish();
+
+};
+
+bool OSBB10::has_touchscreen_ui_hint() const {
+
+ return true;
+}
+
+Error OSBB10::shell_open(String p_uri) {
+
+ char* msg = NULL;
+ int ret = navigator_invoke(p_uri.utf8().get_data(), &msg);
+
+ return ret == BPS_SUCCESS ? OK : FAILED;
+};
+
+String OSBB10::get_data_dir() const {
+
+ return data_dir;
+};
+
+
+OSBB10::OSBB10() {
+
+ main_loop=NULL;
+ last_id=1;
+ minimized = false;
+ fullscreen = true;
+ flip_accelerometer = true;
+ fullscreen_mixer_volume = 1;
+ fullscreen_stream_volume = 1;
+
+
+ printf("godot bb10!\n");
+ getcwd(launch_dir, sizeof(launch_dir));
+ printf("launch dir %s\n", launch_dir);
+ chdir("app/native/assets");
+ launch_dir_ptr = launch_dir;
+}
+
+OSBB10::~OSBB10() {
+
+
+}
+
diff --git a/platform/bb10/os_bb10.h b/platform/bb10/os_bb10.h
new file mode 100644
index 000000000..28149c15b
--- /dev/null
+++ b/platform/bb10/os_bb10.h
@@ -0,0 +1,157 @@
+/*************************************************************************/
+/* os_bb10.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef OS_BB10_H
+#define OS_BB10_H
+
+#include "os/input.h"
+#include "drivers/unix/os_unix.h"
+#include "os/main_loop.h"
+#include "servers/physics/physics_server_sw.h"
+#include "servers/spatial_sound/spatial_sound_server_sw.h"
+#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
+#include "servers/audio/audio_server_sw.h"
+#include "servers/physics_2d/physics_2d_server_sw.h"
+#include "servers/visual/rasterizer.h"
+#include "audio_driver_bb10.h"
+#include "payment_service.h"
+
+#include <screen/screen.h>
+#include <sys/platform.h>
+#include "bps/event.h"
+
+#include <stdint.h>
+
+class OSBB10 : public OS_Unix {
+
+ unsigned int last_id;
+
+ screen_context_t screen_cxt;
+ float fullscreen_mixer_volume;
+ float fullscreen_stream_volume;
+
+ Rasterizer *rasterizer;
+ VisualServer *visual_server;
+// AudioDriverPSP audio_driver_psp;
+ AudioServerSW *audio_server;
+ SampleManagerMallocSW *sample_manager;
+ SpatialSoundServerSW *spatial_sound_server;
+ SpatialSound2DServerSW *spatial_sound_2d_server;
+ PhysicsServer *physics_server;
+ Physics2DServer *physics_2d_server;
+ AudioDriverBB10* audio_driver;
+
+#ifdef PAYMENT_SERVICE_ENABLED
+ PaymentService* payment_service;
+#endif
+
+ VideoMode default_videomode;
+ MainLoop * main_loop;
+
+ void process_events();
+
+ void _resize(bps_event_t *event);
+ void handle_screen_event(bps_event_t *event);
+ void handle_accelerometer();
+
+ int last_touch_x[16];
+ int last_touch_y[16];
+
+ bool accel_supported;
+ float pitch;
+ float roll;
+
+ bool minimized;
+ bool fullscreen;
+ bool flip_accelerometer;
+ String data_dir;
+
+ InputDefault *input;
+public:
+
+ // functions used by main to initialize/deintialize the OS
+ virtual int get_video_driver_count() const;
+ virtual const char * get_video_driver_name(int p_driver) const;
+
+ virtual VideoMode get_default_video_mode() const;
+
+ virtual String get_data_dir() const;
+
+ virtual int get_audio_driver_count() const;
+ virtual const char * get_audio_driver_name(int p_driver) const;
+
+ virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver);
+
+ virtual void set_main_loop( MainLoop * p_main_loop );
+ virtual void delete_main_loop();
+
+ virtual void finalize();
+
+ typedef int64_t ProcessID;
+
+ static OS* get_singleton();
+
+ virtual void set_mouse_show(bool p_show);
+ virtual void set_mouse_grab(bool p_grab);
+ virtual bool is_mouse_grab_enabled() const;
+ virtual Point2 get_mouse_pos() const;
+ virtual int get_mouse_button_state() const;
+ virtual void set_window_title(const String& p_title);
+
+ //virtual void set_clipboard(const String& p_text);
+ //virtual String get_clipboard() const;
+
+
+ virtual bool has_virtual_keyboard() const;
+ virtual void show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect);
+ virtual void hide_virtual_keyboard();
+
+ virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0);
+ virtual VideoMode get_video_mode(int p_screen=0) const;
+ virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+
+ virtual String get_name();
+ virtual MainLoop *get_main_loop() const;
+
+ virtual bool can_draw() const;
+
+ virtual void set_cursor_shape(CursorShape p_shape);
+
+ virtual bool has_touchscreen_ui_hint() const;
+
+ virtual Error shell_open(String p_uri);
+
+ void run();
+
+ OSBB10();
+ ~OSBB10();
+
+};
+
+#endif
+
diff --git a/platform/bb10/payment_service.cpp b/platform/bb10/payment_service.cpp
new file mode 100644
index 000000000..f6ffffd83
--- /dev/null
+++ b/platform/bb10/payment_service.cpp
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* payment_service.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef PAYMENT_SERVICE_ENABLED
+
+#include "payment_service.h"
+
+#include "bbutil.h"
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+extern char* launch_dir_ptr;
+
+void PaymentService::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("request_product_info"),&PaymentService::request_product_info);
+ ObjectTypeDB::bind_method(_MD("purchase"),&PaymentService::purchase);
+
+ ObjectTypeDB::bind_method(_MD("get_pending_event_count"),&PaymentService::get_pending_event_count);
+ ObjectTypeDB::bind_method(_MD("pop_pending_event"),&PaymentService::pop_pending_event);
+};
+
+Error PaymentService::request_product_info(Variant p_params) {
+
+ return ERR_UNAVAILABLE;
+};
+
+Error PaymentService::purchase(Variant p_params) {
+
+ Dictionary params = p_params;
+ ERR_FAIL_COND_V((!params.has("product_id")) && (!params.has("product_sku")), ERR_INVALID_PARAMETER);
+
+ char* id = NULL;
+ char* sku = NULL;
+
+ CharString p_id = params.has("product_id")?String(params["product_id"]).ascii():CharString();
+ CharString p_sku = params.has("product_sku")?String(params["product_sku"]).ascii():CharString();
+ unsigned int request_id;
+ chdir(launch_dir_ptr);
+ int ret = paymentservice_purchase_request(params.has("product_sku") ? NULL : p_id.get_data(),
+ params.has("product_sku") ? p_sku.get_data() : NULL,
+ NULL, NULL, NULL, NULL, get_window_group_id(), &request_id);
+ chdir("app/native");
+
+ if (ret != BPS_SUCCESS) {
+ int eret = errno;
+ printf("purchase error %i, %x, %i, %x\n", ret, ret, eret, eret);
+ ERR_FAIL_V((Error)eret);
+ return (Error)eret;
+ };
+ return OK;
+};
+
+
+bool PaymentService::handle_event(bps_event_t* p_event) {
+
+ if (bps_event_get_domain(p_event) != paymentservice_get_domain()) {
+ return false;
+ };
+
+ Dictionary dict;
+ int res = paymentservice_event_get_response_code(p_event);
+ if (res == SUCCESS_RESPONSE) {
+ dict["result"] = "ok";
+
+ res = bps_event_get_code(p_event);
+ if (res == PURCHASE_RESPONSE) {
+ dict["type"] = "purchase";
+ const char* pid = paymentservice_event_get_digital_good_id(p_event, 0);
+ dict["product_id"] = String(pid?pid:"");
+ };
+
+ } else {
+ const char* desc = paymentservice_event_get_error_text(p_event);
+ if (strcmp(desc, "alreadyPurchased") == 0) {
+ dict["result"] = "ok";
+ } else {
+ dict["result"] = "error";
+ dict["error_description"] = paymentservice_event_get_error_text(p_event);
+ dict["error_code"] = paymentservice_event_get_error_id(p_event);
+ printf("error code is %i\n", paymentservice_event_get_error_id(p_event));
+ printf("error description is %s\n", paymentservice_event_get_error_text(p_event));
+ };
+ dict["product_id"] = "";
+ };
+
+ res = bps_event_get_code(p_event);
+ if (res == PURCHASE_RESPONSE) {
+ dict["type"] = "purchase";
+ };
+
+ printf("********** adding event with result %ls\n", String(dict["result"]).c_str());
+ pending_events.push_back(dict);
+
+ return true;
+};
+
+int PaymentService::get_pending_event_count() {
+ return pending_events.size();
+};
+
+Variant PaymentService::pop_pending_event() {
+
+ Variant front = pending_events.front()->get();
+ pending_events.pop_front();
+
+ return front;
+};
+
+PaymentService::PaymentService() {
+
+ paymentservice_request_events(0);
+#ifdef DEBUG_ENABLED
+ paymentservice_set_connection_mode(true);
+#else
+ paymentservice_set_connection_mode(false);
+#endif
+};
+
+PaymentService::~PaymentService() {
+
+};
+
+
+#endif
diff --git a/platform/bb10/payment_service.h b/platform/bb10/payment_service.h
new file mode 100644
index 000000000..09eda11d2
--- /dev/null
+++ b/platform/bb10/payment_service.h
@@ -0,0 +1,69 @@
+/*************************************************************************/
+/* payment_service.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef PAYMENT_SERVICE_ENABLED
+
+#ifndef PAYMENT_SERVICE_H
+#define PAYMENT_SERVICE_H
+
+#include <bps/bps.h>
+#include <bps/event.h>
+#include <bps/paymentservice.h>
+
+#include "core/object.h"
+
+class PaymentService : public Object {
+
+ OBJ_TYPE(PaymentService, Object);
+
+ static void _bind_methods();
+
+ List<Variant> pending_events;
+
+public:
+
+ Error request_product_info(Variant p_params);
+ Error purchase(Variant p_params);
+
+ int get_pending_event_count();
+ Variant pop_pending_event();
+
+ bool handle_event(bps_event_t* p_event);
+
+ PaymentService();
+ ~PaymentService();
+};
+
+
+
+#endif
+
+
+#endif
+
+
diff --git a/platform/bb10/platform_config.h b/platform/bb10/platform_config.h
new file mode 100644
index 000000000..38fc934ae
--- /dev/null
+++ b/platform/bb10/platform_config.h
@@ -0,0 +1,29 @@
+/*************************************************************************/
+/* platform_config.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include <alloca.h>