summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/javascript/javascript_main.cpp148
-rw-r--r--platform/javascript/os_javascript.cpp493
-rw-r--r--platform/javascript/os_javascript.h26
-rw-r--r--platform/uwp/SCsub1
-rw-r--r--platform/uwp/app.h2
-rw-r--r--platform/uwp/export/export.cpp9
-rw-r--r--platform/uwp/os_uwp.cpp69
-rw-r--r--platform/uwp/os_uwp.h7
-rw-r--r--platform/uwp/power_uwp.cpp74
-rw-r--r--platform/uwp/power_uwp.h55
10 files changed, 458 insertions, 426 deletions
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index ff29c21b1c..6b1d574496 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -31,166 +31,50 @@
#include "io/resource_loader.h"
#include "main/main.h"
#include "os_javascript.h"
-#include <GL/glut.h>
-#include <string.h>
OS_JavaScript *os = NULL;
-static void _gfx_init(void *ud, bool gl2, int w, int h, bool fs) {
+static void main_loop() {
- glutInitWindowSize(w, h);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
- glutCreateWindow("godot");
+ os->main_loop_iterate();
}
-static uint32_t _mouse_button_mask = 0;
+extern "C" void main_after_fs_sync() {
-static void _glut_mouse_button(int button, int state, int x, int y) {
-
- InputEvent ev;
- ev.type = InputEvent::MOUSE_BUTTON;
- switch (button) {
- case GLUT_LEFT_BUTTON: ev.mouse_button.button_index = BUTTON_LEFT; break;
- case GLUT_MIDDLE_BUTTON: ev.mouse_button.button_index = BUTTON_MIDDLE; break;
- case GLUT_RIGHT_BUTTON: ev.mouse_button.button_index = BUTTON_RIGHT; break;
- case 3: ev.mouse_button.button_index = BUTTON_WHEEL_UP; break;
- case 4: ev.mouse_button.button_index = BUTTON_WHEEL_DOWN; break;
- }
-
- ev.mouse_button.pressed = state == GLUT_DOWN;
- ev.mouse_button.x = x;
- ev.mouse_button.y = y;
- ev.mouse_button.global_x = x;
- ev.mouse_button.global_y = y;
-
- if (ev.mouse_button.button_index < 4) {
- if (ev.mouse_button.pressed) {
- _mouse_button_mask |= 1 << (ev.mouse_button.button_index - 1);
- } else {
- _mouse_button_mask &= ~(1 << (ev.mouse_button.button_index - 1));
- }
- }
- ev.mouse_button.button_mask = _mouse_button_mask;
-
- uint32_t m = glutGetModifiers();
- ev.mouse_button.mod.alt = (m & GLUT_ACTIVE_ALT) != 0;
- ev.mouse_button.mod.shift = (m & GLUT_ACTIVE_SHIFT) != 0;
- ev.mouse_button.mod.control = (m & GLUT_ACTIVE_CTRL) != 0;
-
- os->push_input(ev);
-
- if (ev.mouse_button.button_index == BUTTON_WHEEL_UP || ev.mouse_button.button_index == BUTTON_WHEEL_DOWN) {
- // GLUT doesn't send release events for mouse wheel, so send manually
- ev.mouse_button.pressed = false;
- os->push_input(ev);
- }
-}
-
-static int _glut_prev_x = 0;
-static int _glut_prev_y = 0;
-
-static void _glut_mouse_motion(int x, int y) {
-
- InputEvent ev;
- ev.type = InputEvent::MOUSE_MOTION;
- ev.mouse_motion.button_mask = _mouse_button_mask;
- ev.mouse_motion.x = x;
- ev.mouse_motion.y = y;
- ev.mouse_motion.global_x = x;
- ev.mouse_motion.global_y = y;
- ev.mouse_motion.relative_x = x - _glut_prev_x;
- ev.mouse_motion.relative_y = y - _glut_prev_y;
- _glut_prev_x = x;
- _glut_prev_y = y;
-
- uint32_t m = glutGetModifiers();
- ev.mouse_motion.mod.alt = (m & GLUT_ACTIVE_ALT) != 0;
- ev.mouse_motion.mod.shift = (m & GLUT_ACTIVE_SHIFT) != 0;
- ev.mouse_motion.mod.control = (m & GLUT_ACTIVE_CTRL) != 0;
-
- os->push_input(ev);
-}
-
-static void _gfx_idle() {
-
- glutPostRedisplay();
-}
-
-int start_step = 0;
-
-static void _godot_draw(void) {
-
- if (start_step == 1) {
- start_step = 2;
- Main::start();
- os->main_loop_begin();
- }
-
- if (start_step == 2) {
- os->main_loop_iterate();
- }
-
- glutSwapBuffers();
-}
-
-extern "C" {
-
-void main_after_fs_sync() {
-
- start_step = 1;
-}
+ // Ease up compatibility
+ ResourceLoader::set_abort_on_missing_resources(false);
+ Main::start();
+ os->main_loop_begin();
+ emscripten_set_main_loop(main_loop, 0, false);
}
int main(int argc, char *argv[]) {
- /* Initialize the window */
printf("let it go dude!\n");
- glutInit(&argc, argv);
- os = new OS_JavaScript(argv[0], _gfx_init, NULL, NULL);
- Error err = Main::setup(argv[0], argc - 1, &argv[1]);
-
- ResourceLoader::set_abort_on_missing_resources(false); //ease up compatibility
-
- glutMouseFunc(_glut_mouse_button);
- glutMotionFunc(_glut_mouse_motion);
- glutPassiveMotionFunc(_glut_mouse_motion);
-
- /* Set up glut callback functions */
- glutIdleFunc(_gfx_idle);
- // glutReshapeFunc(gears_reshape);
- glutDisplayFunc(_godot_draw);
- //glutSpecialFunc(gears_special);
-
- //mount persistent file system
+ // sync from persistent state into memory and then
+ // run the 'main_after_fs_sync' function
/* clang-format off */
EM_ASM(
+ Module.noExitRuntime = true;
FS.mkdir('/userfs');
FS.mount(IDBFS, {}, '/userfs');
-
- // sync from persistent state into memory and then
- // run the 'main_after_fs_sync' function
FS.syncfs(true, function(err) {
-
if (err) {
Module.setStatus('Failed to load persistent data\nPlease allow (third-party) cookies');
Module.printErr('Failed to populate IDB file system: ' + err.message);
- Module.exit();
+ Module.noExitRuntime = false;
} else {
Module.print('Successfully populated IDB file system');
- ccall('main_after_fs_sync', 'void', []);
+ ccall('main_after_fs_sync', null);
}
});
);
/* clang-format on */
- glutMainLoop();
+ os = new OS_JavaScript(argv[0], NULL);
+ Error err = Main::setup(argv[0], argc - 1, &argv[1]);
return 0;
+ // continued async in main_after_fs_sync() from syncfs() callback
}
-
-/*
- *
- *09] <azakai|2__> reduz: yes, define TOTAL_MEMORY on Module. for example var Module = { TOTAL_MEMORY: 12345.. }; before the main
- *
- */
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 71754502cb..1cd1991608 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -41,6 +41,21 @@
#include <emscripten.h>
#include <stdlib.h>
+#define DOM_BUTTON_LEFT 0
+#define DOM_BUTTON_MIDDLE 1
+#define DOM_BUTTON_RIGHT 2
+
+template <typename T>
+static InputModifierState dom2godot_mod(T emscripten_event_ptr) {
+
+ InputModifierState mod;
+ mod.shift = emscripten_event_ptr->shiftKey;
+ mod.alt = emscripten_event_ptr->altKey;
+ mod.control = emscripten_event_ptr->ctrlKey;
+ mod.meta = emscripten_event_ptr->metaKey;
+ return mod;
+}
+
int OS_JavaScript::get_video_driver_count() const {
return 1;
@@ -130,15 +145,188 @@ static EM_BOOL _fullscreen_change_callback(int event_type, const EmscriptenFulls
return false;
}
+static InputDefault *_input;
+
+static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent *mouse_event, void *user_data) {
+
+ ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEDOWN && event_type != EMSCRIPTEN_EVENT_MOUSEUP, false);
+
+ InputEvent ev;
+ ev.type = InputEvent::MOUSE_BUTTON;
+ ev.mouse_button.pressed = event_type == EMSCRIPTEN_EVENT_MOUSEDOWN;
+ ev.mouse_button.global_x = ev.mouse_button.x = mouse_event->canvasX;
+ ev.mouse_button.global_y = ev.mouse_button.y = mouse_event->canvasY;
+ ev.mouse_button.mod = dom2godot_mod(mouse_event);
+
+ switch (mouse_event->button) {
+ case DOM_BUTTON_LEFT: ev.mouse_button.button_index = BUTTON_LEFT; break;
+ case DOM_BUTTON_MIDDLE: ev.mouse_button.button_index = BUTTON_MIDDLE; break;
+ case DOM_BUTTON_RIGHT: ev.mouse_button.button_index = BUTTON_RIGHT; break;
+ default: return false;
+ }
+
+ ev.mouse_button.button_mask = _input->get_mouse_button_mask();
+ if (ev.mouse_button.pressed)
+ ev.mouse_button.button_mask |= 1 << ev.mouse_button.button_index;
+ else
+ ev.mouse_button.button_mask &= ~(1 << ev.mouse_button.button_index);
+ ev.mouse_button.button_mask >>= 1;
+
+ _input->parse_input_event(ev);
+ return true;
+}
+
+static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *mouse_event, void *user_data) {
+
+ ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_MOUSEMOVE, false);
+
+ InputEvent ev;
+ ev.type = InputEvent::MOUSE_MOTION;
+ ev.mouse_motion.mod = dom2godot_mod(mouse_event);
+ ev.mouse_motion.button_mask = _input->get_mouse_button_mask() >> 1;
+
+ ev.mouse_motion.global_x = ev.mouse_motion.x = mouse_event->canvasX;
+ ev.mouse_motion.global_y = ev.mouse_motion.y = mouse_event->canvasY;
+
+ ev.mouse_motion.relative_x = _input->get_mouse_position().x - ev.mouse_motion.x;
+ ev.mouse_motion.relative_y = _input->get_mouse_position().y - ev.mouse_motion.y;
+
+ _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
+ ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x;
+ ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y;
+
+ _input->parse_input_event(ev);
+ return true;
+}
+
+static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel_event, void *user_data) {
+
+ ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_WHEEL, false);
+
+ InputEvent ev;
+ ev.type = InputEvent::MOUSE_BUTTON;
+ ev.mouse_button.button_mask = _input->get_mouse_button_mask() >> 1;
+ ev.mouse_button.global_x = ev.mouse_button.x = _input->get_mouse_position().x;
+ ev.mouse_button.global_y = ev.mouse_button.y = _input->get_mouse_position().y;
+ ev.mouse_button.mod.shift = _input->is_key_pressed(KEY_SHIFT);
+ ev.mouse_button.mod.alt = _input->is_key_pressed(KEY_ALT);
+ ev.mouse_button.mod.control = _input->is_key_pressed(KEY_CONTROL);
+ ev.mouse_button.mod.meta = _input->is_key_pressed(KEY_META);
+
+ if (wheel_event->deltaY < 0)
+ ev.mouse_button.button_index = BUTTON_WHEEL_UP;
+ else if (wheel_event->deltaY > 0)
+ ev.mouse_button.button_index = BUTTON_WHEEL_DOWN;
+ else if (wheel_event->deltaX > 0)
+ ev.mouse_button.button_index = BUTTON_WHEEL_LEFT;
+ else if (wheel_event->deltaX < 0)
+ ev.mouse_button.button_index = BUTTON_WHEEL_RIGHT;
+ else
+ return false;
+
+ ev.mouse_button.pressed = true;
+ _input->parse_input_event(ev);
+
+ ev.mouse_button.pressed = false;
+ _input->parse_input_event(ev);
+
+ return true;
+}
+
+static Point2 _prev_touches[32];
+
+static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent *touch_event, void *user_data) {
+
+ ERR_FAIL_COND_V(
+ event_type != EMSCRIPTEN_EVENT_TOUCHSTART &&
+ event_type != EMSCRIPTEN_EVENT_TOUCHEND &&
+ event_type != EMSCRIPTEN_EVENT_TOUCHCANCEL,
+ false);
+
+ InputEvent ev;
+ ev.type = InputEvent::SCREEN_TOUCH;
+ int lowest_id_index = -1;
+ for (int i = 0; i < touch_event->numTouches; ++i) {
+
+ const EmscriptenTouchPoint &touch = touch_event->touches[i];
+ if (lowest_id_index == -1 || touch.identifier < touch_event->touches[lowest_id_index].identifier)
+ lowest_id_index = i;
+ if (!touch.isChanged)
+ continue;
+ ev.screen_touch.index = touch.identifier;
+ _prev_touches[i].x = ev.screen_touch.x = touch.canvasX;
+ _prev_touches[i].y = ev.screen_touch.y = touch.canvasY;
+ ev.screen_touch.pressed = event_type == EMSCRIPTEN_EVENT_TOUCHSTART;
+
+ _input->parse_input_event(ev);
+ }
+
+ if (touch_event->touches[lowest_id_index].isChanged) {
+
+ ev.type = InputEvent::MOUSE_BUTTON;
+ ev.mouse_button.mod = dom2godot_mod(touch_event);
+ ev.mouse_button.button_mask = _input->get_mouse_button_mask() >> 1;
+ ev.mouse_button.global_x = ev.mouse_button.x = touch_event->touches[lowest_id_index].canvasX;
+ ev.mouse_button.global_y = ev.mouse_button.y = touch_event->touches[lowest_id_index].canvasY;
+ ev.mouse_button.button_index = BUTTON_LEFT;
+ ev.mouse_button.pressed = event_type == EMSCRIPTEN_EVENT_TOUCHSTART;
+
+ _input->parse_input_event(ev);
+ }
+ return true;
+}
+
+static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *touch_event, void *user_data) {
+
+ ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_TOUCHMOVE, false);
+
+ InputEvent ev;
+ ev.type = InputEvent::SCREEN_DRAG;
+ int lowest_id_index = -1;
+ for (int i = 0; i < touch_event->numTouches; ++i) {
+
+ const EmscriptenTouchPoint &touch = touch_event->touches[i];
+ if (lowest_id_index == -1 || touch.identifier < touch_event->touches[lowest_id_index].identifier)
+ lowest_id_index = i;
+ if (!touch.isChanged)
+ continue;
+ ev.screen_drag.index = touch.identifier;
+ ev.screen_drag.x = touch.canvasX;
+ ev.screen_drag.y = touch.canvasY;
+ Point2 &prev = _prev_touches[i];
+ ev.screen_drag.relative_x = touch.canvasX - prev.x;
+ ev.screen_drag.relative_y = touch.canvasY - prev.y;
+ prev.x = ev.screen_drag.x;
+ prev.y = ev.screen_drag.y;
+
+ _input->parse_input_event(ev);
+ }
+
+ if (touch_event->touches[lowest_id_index].isChanged) {
+
+ ev.type = InputEvent::MOUSE_MOTION;
+ ev.mouse_motion.mod = dom2godot_mod(touch_event);
+ ev.mouse_motion.button_mask = _input->get_mouse_button_mask() >> 1;
+ ev.mouse_motion.global_x = ev.mouse_motion.x = touch_event->touches[lowest_id_index].canvasX;
+ ev.mouse_motion.global_y = ev.mouse_motion.y = touch_event->touches[lowest_id_index].canvasY;
+ ev.mouse_motion.relative_x = _input->get_mouse_position().x - ev.mouse_motion.x;
+ ev.mouse_motion.relative_y = _input->get_mouse_position().y - ev.mouse_motion.y;
+
+ _input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
+ ev.mouse_motion.speed_x = _input->get_last_mouse_speed().x;
+ ev.mouse_motion.speed_y = _input->get_last_mouse_speed().y;
+
+ _input->parse_input_event(ev);
+ }
+ return true;
+}
+
static InputEvent _setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) {
InputEvent ev;
ev.type = InputEvent::KEY;
ev.key.echo = emscripten_event->repeat;
- ev.key.mod.alt = emscripten_event->altKey;
- ev.key.mod.shift = emscripten_event->shiftKey;
- ev.key.mod.control = emscripten_event->ctrlKey;
- ev.key.mod.meta = emscripten_event->metaKey;
+ ev.key.mod = dom2godot_mod(emscripten_event);
ev.key.scancode = dom2godot_scancode(emscripten_event->keyCode);
String unicode = String::utf8(emscripten_event->key);
@@ -167,7 +355,7 @@ static EM_BOOL _keydown_callback(int event_type, const EmscriptenKeyboardEvent *
deferred_key_event = ev;
return false; // do not suppress keypress event
}
- static_cast<OS_JavaScript *>(user_data)->push_input(ev);
+ _input->parse_input_event(ev);
return true;
}
@@ -176,7 +364,7 @@ static EM_BOOL _keypress_callback(int event_type, const EmscriptenKeyboardEvent
ERR_FAIL_COND_V(event_type != EMSCRIPTEN_EVENT_KEYPRESS, false);
deferred_key_event.key.unicode = key_event->charCode;
- static_cast<OS_JavaScript *>(user_data)->push_input(deferred_key_event);
+ _input->parse_input_event(deferred_key_event);
return true;
}
@@ -186,7 +374,7 @@ static EM_BOOL _keyup_callback(int event_type, const EmscriptenKeyboardEvent *ke
InputEvent ev = _setup_key_event(key_event);
ev.key.pressed = false;
- static_cast<OS_JavaScript *>(user_data)->push_input(ev);
+ _input->parse_input_event(ev);
return ev.key.scancode != KEY_UNKNOWN && ev.key.scancode != 0;
}
@@ -202,14 +390,18 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
print_line("Init OS");
- if (gfx_init_func)
- gfx_init_func(gfx_init_ud, use_gl2, p_desired.width, p_desired.height, p_desired.fullscreen);
+ EmscriptenWebGLContextAttributes attributes;
+ emscripten_webgl_init_context_attributes(&attributes);
+ attributes.alpha = false;
+ attributes.antialias = false;
+ attributes.majorVersion = 2;
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes);
+ ERR_FAIL_COND(emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS);
- // nothing to do here, can't fulfil fullscreen request due to
- // browser security, window size is already set from HTML
video_mode = p_desired;
+ // can't fulfil fullscreen request due to browser security
video_mode.fullscreen = false;
- _windowed_size = get_window_size();
+ set_window_size(Size2(p_desired.width, p_desired.height));
// find locale, emscripten only sets "C"
char locale_ptr[16];
@@ -257,25 +449,34 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
physics_2d_server->init();
input = memnew(InputDefault);
+ _input = input;
power_manager = memnew(PowerJavascript);
#define EM_CHECK(ev) \
if (result != EMSCRIPTEN_RESULT_SUCCESS) \
ERR_PRINTS("Error while setting " #ev " callback: Code " + itos(result))
-#define SET_EM_CALLBACK(ev, cb) \
- result = emscripten_set_##ev##_callback(NULL, this, true, &cb); \
+#define SET_EM_CALLBACK(target, ev, cb) \
+ result = emscripten_set_##ev##_callback(target, this, true, &cb); \
EM_CHECK(ev)
#define SET_EM_CALLBACK_NODATA(ev, cb) \
result = emscripten_set_##ev##_callback(NULL, true, &cb); \
EM_CHECK(ev)
EMSCRIPTEN_RESULT result;
- SET_EM_CALLBACK(keydown, _keydown_callback)
- SET_EM_CALLBACK(keypress, _keypress_callback)
- SET_EM_CALLBACK(keyup, _keyup_callback)
- SET_EM_CALLBACK(resize, _browser_resize_callback)
- SET_EM_CALLBACK(fullscreenchange, _fullscreen_change_callback)
+ SET_EM_CALLBACK("#canvas", mousemove, _mousemove_callback)
+ SET_EM_CALLBACK("#canvas", mousedown, _mousebutton_callback)
+ SET_EM_CALLBACK("#canvas", mouseup, _mousebutton_callback)
+ SET_EM_CALLBACK("#canvas", wheel, _wheel_callback)
+ SET_EM_CALLBACK("#canvas", touchstart, _touchpress_callback)
+ SET_EM_CALLBACK("#canvas", touchmove, _touchmove_callback)
+ SET_EM_CALLBACK("#canvas", touchend, _touchpress_callback)
+ SET_EM_CALLBACK("#canvas", touchcancel, _touchpress_callback)
+ SET_EM_CALLBACK(NULL, keydown, _keydown_callback)
+ SET_EM_CALLBACK(NULL, keypress, _keypress_callback)
+ SET_EM_CALLBACK(NULL, keyup, _keyup_callback)
+ SET_EM_CALLBACK(NULL, resize, _browser_resize_callback)
+ SET_EM_CALLBACK(NULL, fullscreenchange, _fullscreen_change_callback)
SET_EM_CALLBACK_NODATA(gamepadconnected, joy_callback_func)
SET_EM_CALLBACK_NODATA(gamepaddisconnected, joy_callback_func)
@@ -316,20 +517,62 @@ void OS_JavaScript::alert(const String &p_alert, const String &p_title) {
/* clang-format on */
}
-void OS_JavaScript::set_mouse_show(bool p_show) {
+void OS_JavaScript::set_css_cursor(const char *p_cursor) {
- //javascript has no mouse...
+ /* clang-format off */
+ EM_ASM_({
+ Module.canvas.style.cursor = Module.UTF8ToString($0);
+ }, p_cursor);
+ /* clang-format on */
}
-void OS_JavaScript::set_mouse_grab(bool p_grab) {
+const char *OS_JavaScript::get_css_cursor() const {
- //it really has no mouse...!
+ char cursor[16];
+ /* clang-format off */
+ EM_ASM_INT({
+ Module.stringToUTF8(Module.canvas.style.cursor ? Module.canvas.style.cursor : 'auto', $0, 16);
+ }, cursor);
+ /* clang-format on */
+ return cursor;
}
-bool OS_JavaScript::is_mouse_grab_enabled() const {
+void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) {
- //*sigh* technology has evolved so much since i was a kid..
- return false;
+ ERR_FAIL_INDEX(p_mode, MOUSE_MODE_CONFINED + 1);
+ ERR_EXPLAIN("MOUSE_MODE_CONFINED is not supported for the HTML5 platform");
+ ERR_FAIL_COND(p_mode == MOUSE_MODE_CONFINED);
+ if (p_mode == get_mouse_mode())
+ return;
+
+ if (p_mode == MOUSE_MODE_VISIBLE) {
+
+ set_css_cursor("auto");
+ emscripten_exit_pointerlock();
+
+ } else if (p_mode == MOUSE_MODE_HIDDEN) {
+
+ set_css_cursor("none");
+ emscripten_exit_pointerlock();
+
+ } else if (p_mode == MOUSE_MODE_CAPTURED) {
+
+ EMSCRIPTEN_RESULT result = emscripten_request_pointerlock("canvas", false);
+ ERR_EXPLAIN("MOUSE_MODE_CAPTURED can only be entered from within an appropriate input callback");
+ ERR_FAIL_COND(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED);
+ ERR_FAIL_COND(result != EMSCRIPTEN_RESULT_SUCCESS);
+ set_css_cursor("auto");
+ }
+}
+
+OS::MouseMode OS_JavaScript::get_mouse_mode() const {
+
+ if (!strcmp(get_css_cursor(), "none"))
+ return MOUSE_MODE_HIDDEN;
+
+ EmscriptenPointerlockChangeEvent ev;
+ emscripten_get_pointerlock_status(&ev);
+ return ev.isActive && (strcmp(ev.id, "canvas") == 0) ? MOUSE_MODE_CAPTURED : MOUSE_MODE_VISIBLE;
}
Point2 OS_JavaScript::get_mouse_position() const {
@@ -339,7 +582,7 @@ Point2 OS_JavaScript::get_mouse_position() const {
int OS_JavaScript::get_mouse_button_state() const {
- return last_button_mask;
+ return input->get_mouse_button_mask();
}
void OS_JavaScript::set_window_title(const String &p_title) {
@@ -518,197 +761,6 @@ void OS_JavaScript::main_loop_focusin() {
//audio_driver_javascript.set_pause(false);
}
-void OS_JavaScript::push_input(const InputEvent &p_ev) {
-
- InputEvent ev = p_ev;
- if (ev.type == InputEvent::MOUSE_MOTION) {
- input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
- } else if (ev.type == InputEvent::MOUSE_BUTTON) {
- last_button_mask = ev.mouse_button.button_mask;
- }
- input->parse_input_event(p_ev);
-}
-
-void OS_JavaScript::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) {
-
- //print_line("ev: "+itos(p_what)+" pnt: "+itos(p_pointer)+" pointc: "+itos(p_points.size()));
-
- switch (p_what) {
- case 0: { //gesture begin
-
- if (touch.size()) {
- //end all if exist
- InputEvent ev;
- ev.type = InputEvent::MOUSE_BUTTON;
- ev.mouse_button.button_index = BUTTON_LEFT;
- ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
- ev.mouse_button.pressed = false;
- ev.mouse_button.x = touch[0].pos.x;
- ev.mouse_button.y = touch[0].pos.y;
- ev.mouse_button.global_x = touch[0].pos.x;
- ev.mouse_button.global_y = touch[0].pos.y;
- input->parse_input_event(ev);
-
- for (int i = 0; i < touch.size(); i++) {
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_TOUCH;
- ev.screen_touch.index = touch[i].id;
- ev.screen_touch.pressed = false;
- ev.screen_touch.x = touch[i].pos.x;
- ev.screen_touch.y = touch[i].pos.y;
- input->parse_input_event(ev);
- }
- }
-
- touch.resize(p_points.size());
- for (int i = 0; i < p_points.size(); i++) {
- touch[i].id = p_points[i].id;
- touch[i].pos = p_points[i].pos;
- }
-
- {
- //send mouse
- InputEvent ev;
- ev.type = InputEvent::MOUSE_BUTTON;
- ev.mouse_button.button_index = BUTTON_LEFT;
- ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
- ev.mouse_button.pressed = true;
- ev.mouse_button.x = touch[0].pos.x;
- ev.mouse_button.y = touch[0].pos.y;
- ev.mouse_button.global_x = touch[0].pos.x;
- ev.mouse_button.global_y = touch[0].pos.y;
- last_mouse = touch[0].pos;
- input->parse_input_event(ev);
- }
-
- //send touch
- for (int i = 0; i < touch.size(); i++) {
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_TOUCH;
- ev.screen_touch.index = touch[i].id;
- ev.screen_touch.pressed = true;
- ev.screen_touch.x = touch[i].pos.x;
- ev.screen_touch.y = touch[i].pos.y;
- input->parse_input_event(ev);
- }
-
- } break;
- case 1: { //motion
-
- if (p_points.size()) {
- //send mouse, should look for point 0?
- InputEvent ev;
- ev.type = InputEvent::MOUSE_MOTION;
- ev.mouse_motion.button_mask = BUTTON_MASK_LEFT;
- ev.mouse_motion.x = p_points[0].pos.x;
- ev.mouse_motion.y = p_points[0].pos.y;
- input->set_mouse_position(Point2(ev.mouse_motion.x, ev.mouse_motion.y));
- ev.mouse_motion.speed_x = input->get_last_mouse_speed().x;
- ev.mouse_motion.speed_y = input->get_last_mouse_speed().y;
- ev.mouse_motion.relative_x = p_points[0].pos.x - last_mouse.x;
- ev.mouse_motion.relative_y = p_points[0].pos.y - last_mouse.y;
- last_mouse = p_points[0].pos;
- input->parse_input_event(ev);
- }
-
- ERR_FAIL_COND(touch.size() != p_points.size());
-
- for (int i = 0; i < touch.size(); i++) {
-
- int idx = -1;
- for (int j = 0; j < p_points.size(); j++) {
-
- if (touch[i].id == p_points[j].id) {
- idx = j;
- break;
- }
- }
-
- ERR_CONTINUE(idx == -1);
-
- if (touch[i].pos == p_points[idx].pos)
- continue; //no move unncesearily
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_DRAG;
- ev.screen_drag.index = touch[i].id;
- ev.screen_drag.x = p_points[idx].pos.x;
- ev.screen_drag.y = p_points[idx].pos.y;
- ev.screen_drag.relative_x = p_points[idx].pos.x - touch[i].pos.x;
- ev.screen_drag.relative_y = p_points[idx].pos.y - touch[i].pos.y;
- input->parse_input_event(ev);
- touch[i].pos = p_points[idx].pos;
- }
-
- } break;
- case 2: { //release
-
- if (touch.size()) {
- //end all if exist
- InputEvent ev;
- ev.type = InputEvent::MOUSE_BUTTON;
- ev.mouse_button.button_index = BUTTON_LEFT;
- ev.mouse_button.button_mask = BUTTON_MASK_LEFT;
- ev.mouse_button.pressed = false;
- ev.mouse_button.x = touch[0].pos.x;
- ev.mouse_button.y = touch[0].pos.y;
- ev.mouse_button.global_x = touch[0].pos.x;
- ev.mouse_button.global_y = touch[0].pos.y;
- input->parse_input_event(ev);
-
- for (int i = 0; i < touch.size(); i++) {
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_TOUCH;
- ev.screen_touch.index = touch[i].id;
- ev.screen_touch.pressed = false;
- ev.screen_touch.x = touch[i].pos.x;
- ev.screen_touch.y = touch[i].pos.y;
- input->parse_input_event(ev);
- }
- touch.clear();
- }
-
- } break;
- case 3: { // add tuchi
-
- ERR_FAIL_INDEX(p_pointer, p_points.size());
-
- TouchPos tp = p_points[p_pointer];
- touch.push_back(tp);
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_TOUCH;
- ev.screen_touch.index = tp.id;
- ev.screen_touch.pressed = true;
- ev.screen_touch.x = tp.pos.x;
- ev.screen_touch.y = tp.pos.y;
- input->parse_input_event(ev);
-
- } break;
- case 4: {
-
- for (int i = 0; i < touch.size(); i++) {
- if (touch[i].id == p_pointer) {
-
- InputEvent ev;
- ev.type = InputEvent::SCREEN_TOUCH;
- ev.screen_touch.index = touch[i].id;
- ev.screen_touch.pressed = false;
- ev.screen_touch.x = touch[i].pos.x;
- ev.screen_touch.y = touch[i].pos.y;
- input->parse_input_event(ev);
- touch.remove(i);
- i--;
- }
- }
-
- } break;
- }
-}
-
void OS_JavaScript::process_accelerometer(const Vector3 &p_accelerometer) {
input->set_accelerometer(p_accelerometer);
@@ -829,11 +881,8 @@ int OS_JavaScript::get_power_percent_left() {
return power_manager->get_power_percent_left();
}
-OS_JavaScript::OS_JavaScript(const char *p_execpath, GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func) {
+OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func) {
set_cmdline(p_execpath, get_cmdline_args());
- gfx_init_func = p_gfx_init_func;
- gfx_init_ud = p_gfx_init_ud;
- last_button_mask = 0;
main_loop = NULL;
gl_extensions = NULL;
window_maximized = false;
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index ea906c560f..ffd269b512 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -45,24 +45,9 @@
#include <emscripten/html5.h>
-typedef void (*GFXInitFunc)(void *ud, bool gl2, int w, int h, bool fs);
typedef String (*GetDataDirFunc)();
class OS_JavaScript : public OS_Unix {
-public:
- struct TouchPos {
- int id;
- Point2 pos;
- };
-
-private:
- Vector<TouchPos> touch;
- Point2 last_mouse;
- int last_button_mask;
- GFXInitFunc gfx_init_func;
- void *gfx_init_ud;
-
- bool use_gl2;
int64_t time_to_save_sync;
int64_t last_sync_time;
@@ -90,6 +75,9 @@ private:
void process_joypads();
+ void set_css_cursor(const char *);
+ const char *get_css_cursor() const;
+
public:
// functions used by main to initialize/deintialize the OS
virtual int get_video_driver_count() const;
@@ -119,9 +107,8 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
- virtual void set_mouse_show(bool p_show);
- virtual void set_mouse_grab(bool p_grab);
- virtual bool is_mouse_grab_enabled() const;
+ virtual void set_mouse_mode(MouseMode p_mode);
+ virtual MouseMode get_mouse_mode() const;
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
@@ -166,7 +153,6 @@ public:
virtual String get_resource_dir() const;
void process_accelerometer(const Vector3 &p_accelerometer);
- void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
void push_input(const InputEvent &p_ev);
virtual bool is_joy_known(int p_device);
@@ -177,7 +163,7 @@ public:
virtual int get_power_seconds_left();
virtual int get_power_percent_left();
- OS_JavaScript(const char *p_execpath, GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func);
+ OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func);
~OS_JavaScript();
};
diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub
index 0167ea9e02..7ee5aa2ac3 100644
--- a/platform/uwp/SCsub
+++ b/platform/uwp/SCsub
@@ -9,6 +9,7 @@ files = [
'#platform/windows/stream_peer_winsock.cpp',
'#platform/windows/key_mapping_win.cpp',
'joypad_uwp.cpp',
+ 'power_uwp.cpp',
'gl_context_egl.cpp',
'app.cpp',
'os_uwp.cpp',
diff --git a/platform/uwp/app.h b/platform/uwp/app.h
index 647ef0261b..9cbe7669c9 100644
--- a/platform/uwp/app.h
+++ b/platform/uwp/app.h
@@ -107,7 +107,7 @@ namespace GodotUWP
int last_touch_y[32];
int number_of_contacts;
Windows::Foundation::Point last_mouse_pos;
- }
+ };
}
/* clang-format on */
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 4a164e5ba1..976e6208ee 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -72,17 +72,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "editor/editor_import_export.h"
#include "editor/editor_node.h"
#include "global_config.h"
-#include "io/base64.h"
#include "io/marshalls.h"
-#include "io/sha256.h"
-#include "io/unzip.h"
-#include "io/zip.h"
#include "io/zip_io.h"
#include "object.h"
#include "os/file_access.h"
#include "platform/uwp/logo.h"
#include "version.h"
+#include "thirdparty/minizip/unzip.h"
+#include "thirdparty/minizip/zip.h"
+#include "thirdparty/misc/base64.h"
+#include "thirdparty/misc/sha256.h"
+
#include <zlib.h>
// Capabilities
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 8b7e821ab3..818b827e83 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -28,24 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "os_uwp.h"
-#include "drivers/gles2/rasterizer_gles2.h"
+#include "drivers/gles3/rasterizer_gles3.h"
+#include "drivers/unix/ip_unix.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
#include "drivers/windows/mutex_windows.h"
+#include "drivers/windows/rw_lock_windows.h"
#include "drivers/windows/semaphore_windows.h"
-#include "main/main.h"
-#include "os/memory_pool_dynamic_static.h"
-#include "servers/audio_server.h"
-#include "servers/visual/visual_server_raster.h"
-#include "thread_uwp.h"
-//#include "servers/visual/visual_server_wrap_mt.h"
-#include "drivers/unix/ip_unix.h"
#include "global_config.h"
#include "io/marshalls.h"
-#include "os/memory_pool_dynamic_prealloc.h"
+#include "main/main.h"
#include "platform/windows/packet_peer_udp_winsock.h"
#include "platform/windows/stream_peer_winsock.h"
#include "platform/windows/tcp_server_winsock.h"
+#include "servers/audio_server.h"
+#include "servers/visual/visual_server_raster.h"
+#include "thread_uwp.h"
#include <ppltasks.h>
#include <wrl.h>
@@ -149,9 +147,6 @@ const char *OSUWP::get_audio_driver_name(int p_driver) const {
return AudioDriverManager::get_driver(p_driver)->get_name();
}
-static MemoryPoolStatic *mempool_static = NULL;
-static MemoryPoolDynamic *mempool_dynamic = NULL;
-
void OSUWP::initialize_core() {
last_button_state = 0;
@@ -161,32 +156,19 @@ void OSUWP::initialize_core() {
ThreadUWP::make_default();
SemaphoreWindows::make_default();
MutexWindows::make_default();
+ RWLockWindows::make_default();
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessWindows>::make_default();
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
- //TCPServerWinsock::make_default();
- //StreamPeerWinsock::make_default();
-
TCPServerWinsock::make_default();
StreamPeerWinsock::make_default();
PacketPeerUDPWinsock::make_default();
- mempool_static = new MemoryPoolStaticMalloc;
-#if 1
- mempool_dynamic = memnew(MemoryPoolDynamicStatic);
-#else
-#define DYNPOOL_SIZE 4 * 1024 * 1024
- void *buffer = malloc(DYNPOOL_SIZE);
- mempool_dynamic = memnew(MemoryPoolDynamicPrealloc(buffer, DYNPOOL_SIZE));
-
-#endif
-
// We need to know how often the clock is updated
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
ticks_per_second = 1000;
@@ -259,13 +241,18 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
set_video_mode(vm);
gl_context->make_current();
- rasterizer = memnew(RasterizerGLES2);
- visual_server = memnew(VisualServerRaster(rasterizer));
+ RasterizerGLES3::register_config();
+ RasterizerGLES3::make_current();
+
+ visual_server = memnew(VisualServerRaster);
+ // FIXME: Reimplement threaded rendering? Or remove?
+ /*
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
+ */
//
physics_server = memnew(PhysicsServerSW);
@@ -288,7 +275,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
ERR_PRINT("Initializing audio failed.");
}
- power_manager = memnew(PowerWinRT);
+ power_manager = memnew(PowerUWP);
managed_object->update_clipboard();
@@ -381,14 +368,6 @@ void OSUWP::finalize() {
if (gl_context)
memdelete(gl_context);
#endif
- if (rasterizer)
- memdelete(rasterizer);
-
- /*
- if (debugger_connection_console) {
- memdelete(debugger_connection_console);
- }
- */
memdelete(input);
@@ -400,11 +379,8 @@ void OSUWP::finalize() {
joypad = nullptr;
}
-void OSUWP::finalize_core() {
- if (mempool_dynamic)
- memdelete(mempool_dynamic);
- delete mempool_static;
+void OSUWP::finalize_core() {
}
void OSUWP::vprint(const char *p_format, va_list p_list, bool p_stderr) {
@@ -880,15 +856,20 @@ String OSUWP::get_data_dir() const {
return String(data_folder->Path->Data()).replace("\\", "/");
}
-PowerState OSWinrt::get_power_state() {
+bool OSUWP::check_feature_support(const String &p_feature) {
+
+ return VisualServer::get_singleton()->has_os_feature(p_feature);
+}
+
+PowerState OSUWP::get_power_state() {
return power_manager->get_power_state();
}
-int OSWinrt::get_power_seconds_left() {
+int OSUWP::get_power_seconds_left() {
return power_manager->get_power_seconds_left();
}
-int OSWinrt::get_power_percent_left() {
+int OSUWP::get_power_percent_left() {
return power_manager->get_power_percent_left();
}
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 88a1dddae3..7d9e681da1 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -38,7 +38,7 @@
#include "main/input_default.h"
#include "os/input.h"
#include "os/os.h"
-#include "power_winrt.h"
+#include "power_uwp.h"
#include "servers/audio_server.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
@@ -94,7 +94,6 @@ private:
int old_x, old_y;
Point2i center;
VisualServer *visual_server;
- Rasterizer *rasterizer;
PhysicsServer *physics_server;
Physics2DServer *physics_2d_server;
int pressrc;
@@ -107,7 +106,7 @@ private:
AudioDriverXAudio2 audio_driver;
- PowerWinRT *power_manager;
+ PowerUWP *power_manager;
MouseMode mouse_mode;
bool alt_mem;
@@ -237,6 +236,8 @@ public:
virtual void move_window_to_foreground();
virtual String get_data_dir() const;
+ virtual bool check_feature_support(const String &p_feature);
+
void set_gl_context(ContextEGL *p_context);
void screen_size_changed();
diff --git a/platform/uwp/power_uwp.cpp b/platform/uwp/power_uwp.cpp
new file mode 100644
index 0000000000..a8f0f5ba6d
--- /dev/null
+++ b/platform/uwp/power_uwp.cpp
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* power_uwp.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 "power_uwp.h"
+
+PowerUWP::PowerUWP()
+ : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+}
+
+PowerUWP::~PowerUWP() {
+}
+
+bool PowerUWP::UpdatePowerInfo() {
+ // TODO, WinRT: Battery info is available on at least one WinRT platform (Windows Phone 8). Implement UpdatePowerInfo as appropriate. */
+ /* Notes from SDL:
+ - the Win32 function, GetSystemPowerStatus, is not available for use on WinRT
+ - Windows Phone 8 has a 'Battery' class, which is documented as available for C++
+ - More info on WP8's Battery class can be found at http://msdn.microsoft.com/library/windowsphone/develop/jj207231
+ */
+ return false;
+}
+
+PowerState PowerUWP::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ } else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN");
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerUWP::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ } else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+int PowerUWP::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ } else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
diff --git a/platform/uwp/power_uwp.h b/platform/uwp/power_uwp.h
new file mode 100644
index 0000000000..465473bc1d
--- /dev/null
+++ b/platform/uwp/power_uwp.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* power_uwp.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 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 PLATFORM_UWP_POWER_UWP_H_
+#define PLATFORM_UWP_POWER_UWP_H_
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/power.h"
+
+class PowerUWP {
+
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool UpdatePowerInfo();
+
+public:
+ PowerUWP();
+ virtual ~PowerUWP();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_UWP_POWER_UWP_H_ */