summaryrefslogtreecommitdiff
path: root/core/os
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /core/os
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
GODOT IS OPEN SOURCE
Diffstat (limited to 'core/os')
-rw-r--r--core/os/SCsub7
-rw-r--r--core/os/copymem.cpp42
-rw-r--r--core/os/copymem.h119
-rw-r--r--core/os/dir_access.cpp401
-rw-r--r--core/os/dir_access.h143
-rw-r--r--core/os/file_access.cpp497
-rw-r--r--core/os/file_access.h175
-rw-r--r--core/os/input.cpp311
-rw-r--r--core/os/input.h140
-rw-r--r--core/os/input_event.cpp190
-rw-r--r--core/os/input_event.h299
-rw-r--r--core/os/keyboard.cpp355
-rw-r--r--core/os/keyboard.h332
-rw-r--r--core/os/main_loop.cpp104
-rw-r--r--core/os/main_loop.h72
-rw-r--r--core/os/memory.cpp134
-rw-r--r--core/os/memory.h362
-rw-r--r--core/os/memory_pool_dynamic.cpp50
-rw-r--r--core/os/memory_pool_dynamic.h79
-rw-r--r--core/os/memory_pool_dynamic_prealloc.cpp116
-rw-r--r--core/os/memory_pool_dynamic_prealloc.h60
-rw-r--r--core/os/memory_pool_dynamic_static.cpp272
-rw-r--r--core/os/memory_pool_dynamic_static.h86
-rw-r--r--core/os/memory_pool_static.cpp49
-rw-r--r--core/os/memory_pool_static.h69
-rw-r--r--core/os/mutex.cpp62
-rw-r--r--core/os/mutex.h70
-rw-r--r--core/os/os.cpp461
-rw-r--r--core/os/os.h328
-rw-r--r--core/os/pc_joystick_map.h86
-rw-r--r--core/os/semaphore.cpp44
-rw-r--r--core/os/semaphore.h53
-rw-r--r--core/os/shell.cpp51
-rw-r--r--core/os/shell.h50
-rw-r--r--core/os/thread.cpp70
-rw-r--r--core/os/thread.h89
-rw-r--r--core/os/thread_dummy.cpp59
-rw-r--r--core/os/thread_dummy.h72
-rw-r--r--core/os/thread_safe.cpp46
-rw-r--r--core/os/thread_safe.h82
40 files changed, 6087 insertions, 0 deletions
diff --git a/core/os/SCsub b/core/os/SCsub
new file mode 100644
index 0000000000..c6ba1fa537
--- /dev/null
+++ b/core/os/SCsub
@@ -0,0 +1,7 @@
+Import('env')
+
+env.add_source_files(env.core_sources,"*.cpp")
+
+Export('env')
+
+
diff --git a/core/os/copymem.cpp b/core/os/copymem.cpp
new file mode 100644
index 0000000000..4a36b6f6d1
--- /dev/null
+++ b/core/os/copymem.cpp
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* copymem.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 "copymem.h"
+
+#include <string.h>
+
+void movemem_system(void *to, void *from,int amount) {
+
+ memmove(to,from,amount);
+
+}
+
+void zeromem(void* p_mem,size_t p_bytes) {
+
+ memset(p_mem,0,p_bytes);
+}
diff --git a/core/os/copymem.h b/core/os/copymem.h
new file mode 100644
index 0000000000..09e8c6903e
--- /dev/null
+++ b/core/os/copymem.h
@@ -0,0 +1,119 @@
+/*************************************************************************/
+/* copymem.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 COPYMEM_H
+#define COPYMEM_H
+
+#include "typedefs.h"
+
+///@TODO use optimized routines for this, depending on platform. these are just the standard ones
+
+#define copymem(m_to,m_from,m_count) \
+ do { \
+ unsigned char * _from=(unsigned char*)m_from; \
+ unsigned char * _to=(unsigned char*)m_to; \
+ int _count=m_count; \
+ for (int _i=0;_i<_count;_i++) \
+ _to[_i]=_from[_i]; \
+ } while (0);
+ /*
+ case 0: *_dto++ = *_dfrom++; \
+ case 7: *_dto++ = *_dfrom++; \
+ case 6: *_dto++ = *_dfrom++; \
+ case 5: *_dto++ = *_dfrom++; \
+ case 4: *_dto++ = *_dfrom++; \
+ case 3: *_dto++ = *_dfrom++; \
+ case 2: *_dto++ = *_dfrom++; \
+ case 1: *_dto++ = *_dfrom++; \
+ */
+#define movemem_duff(m_to, m_from, m_count) \
+ do { \
+ if (m_to<m_from) { \
+ unsigned char* _dto = (unsigned char*)m_to; \
+ unsigned char* _dfrom = (unsigned char*)m_from; \
+ int n = (m_count + 7) / 8; \
+ switch (m_count % 8) { \
+ do { \
+ case 0: *_dto++ = *_dfrom++; \
+ case 7: *_dto++ = *_dfrom++; \
+ case 6: *_dto++ = *_dfrom++; \
+ case 5: *_dto++ = *_dfrom++; \
+ case 4: *_dto++ = *_dfrom++; \
+ case 3: *_dto++ = *_dfrom++; \
+ case 2: *_dto++ = *_dfrom++; \
+ case 1: *_dto++ = *_dfrom++; \
+ } while (--n > 0); \
+ }; \
+ } else if (m_to>m_from) { \
+ unsigned char* _dto = &((unsigned char*)m_to)[m_count-1]; \
+ unsigned char* _dfrom = &((unsigned char*)m_from)[m_count-1]; \
+ int n = (m_count + 7) / 8; \
+ switch (m_count % 8) { \
+ do { \
+ case 0: *_dto-- = *_dfrom--; \
+ case 7: *_dto-- = *_dfrom--; \
+ case 6: *_dto-- = *_dfrom--; \
+ case 5: *_dto-- = *_dfrom--; \
+ case 4: *_dto-- = *_dfrom--; \
+ case 3: *_dto-- = *_dfrom--; \
+ case 2: *_dto-- = *_dfrom--; \
+ case 1: *_dto-- = *_dfrom--; \
+ } while (--n > 0); \
+ }; \
+ } \
+ } while(0) \
+
+#define movemem_conventional(m_to,m_from,m_count) \
+ do { \
+ if (m_to<m_from) { \
+ unsigned char * _from=(unsigned char*)m_from; \
+ unsigned char * _to=(unsigned char*)m_to; \
+ int _count=m_count; \
+ for (int _i=0;_i<_count;_i++) \
+ _to[_i]=_from[_i]; \
+ \
+ } else if (m_to>m_from) { \
+ unsigned char * _from=(unsigned char*)m_from; \
+ unsigned char * _to=(unsigned char*)m_to; \
+ int _count=m_count; \
+ while (_count--) \
+ _to[_count]=_from[_count]; \
+ \
+ \
+ } \
+ } while (0); \
+
+void movemem_system(void*,void*,int);
+
+#define movemem movemem_system
+
+
+void zeromem(void* p_mem,size_t p_bytes);
+
+#endif
+
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
new file mode 100644
index 0000000000..496ebdfa27
--- /dev/null
+++ b/core/os/dir_access.cpp
@@ -0,0 +1,401 @@
+/*************************************************************************/
+/* dir_access.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 "dir_access.h"
+#include "os/file_access.h"
+#include "os/memory.h"
+#include "os/os.h"
+#include "globals.h"
+
+
+String DirAccess::_get_root_path() const {
+
+ switch(_access_type) {
+
+ case ACCESS_RESOURCES: return Globals::get_singleton()->get_resource_path();
+ case ACCESS_USERDATA: return OS::get_singleton()->get_data_dir();
+ default: return "";
+ }
+
+ return "";
+}
+String DirAccess::_get_root_string() const {
+
+ switch(_access_type) {
+
+ case ACCESS_RESOURCES: return "res://";
+ case ACCESS_USERDATA: return "user://";
+ default: return "";
+ }
+
+ return "";
+}
+
+
+static Error _erase_recursive(DirAccess *da) {
+
+ List<String> dirs;
+ List<String> files;
+
+ da->list_dir_begin();
+ String n = da->get_next();
+ while(n!=String()) {
+
+ if (n!="." && n!="..") {
+
+ if (da->current_is_dir())
+ dirs.push_back(n);
+ else
+ files.push_back(n);
+ }
+
+ n=da->get_next();
+ }
+
+ da->list_dir_end();
+
+ for(List<String>::Element *E=dirs.front();E;E=E->next()) {
+
+ Error err = da->change_dir(E->get());
+ if (err==OK) {
+
+ err = _erase_recursive(da);
+ if (err) {
+ print_line("err recurso "+E->get());
+ return err;
+ }
+ err = da->change_dir("..");
+ if (err) {
+ print_line("no go back "+E->get());
+ return err;
+ }
+ err = da->remove(da->get_current_dir().plus_file(E->get()));
+ if (err) {
+ print_line("no remove dir"+E->get());
+ return err;
+ }
+ } else {
+ print_line("no change to "+E->get());
+ return err;
+ }
+ }
+
+ for(List<String>::Element *E=files.front();E;E=E->next()) {
+
+ Error err = da->remove(da->get_current_dir().plus_file(E->get()));
+ if (err) {
+
+ print_line("no remove file"+E->get());
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+
+Error DirAccess::erase_contents_recursive() {
+
+ return _erase_recursive(this);
+}
+
+
+Error DirAccess::make_dir_recursive(String p_dir) {
+
+ if (p_dir.length() < 1) {
+ return OK;
+ };
+ Globals* g = Globals::get_singleton();
+ String cur = normalize_path(g->globalize_path(get_current_dir()));
+ if (cur[cur.length()-1] != '/') {
+ cur = cur + "/";
+ };
+
+ String dir = normalize_path(g->globalize_path(p_dir));
+ if (dir.length() < 1) {
+ return OK;
+ };
+ if (dir[dir.length()-1] != '/') {
+ dir = dir + "/";
+ };
+
+ ERR_FAIL_COND_V(dir.find(cur) != 0, FAILED);
+
+ String rel = dir.substr(cur.length(), (dir.length() - cur.length()));
+
+ int pos = 0;
+ while (pos < rel.length()) {
+
+ int n = rel.find("/", pos);
+ if (n < 0) {
+ n = rel.length();
+ };
+ pos = n + 1;
+
+ if (pos > 1) {
+ Error err = make_dir(rel.substr(0, pos -1));
+ if (err != OK && err != ERR_ALREADY_EXISTS) {
+
+ ERR_FAIL_V(err);
+ };
+ };
+ };
+
+ return OK;
+};
+
+
+String DirAccess::normalize_path(const String &p_path) {
+
+ static const int max_depth = 64;
+ int pos_stack[max_depth];
+ int curr = 0;
+
+ int pos = 0;
+ String cur_dir;
+
+ do {
+
+ if (curr >= max_depth) {
+
+ ERR_PRINT("Directory depth too deep.");
+ return "";
+ };
+
+ int start = pos;
+
+ int next = p_path.find("/", pos);
+ if (next < 0) {
+ next = p_path.length() - 1;
+ };
+
+ pos = next + 1;
+
+ cur_dir = p_path.substr(start, next - start);
+
+ if (cur_dir == "" || cur_dir == ".") {
+ continue;
+ };
+ if (cur_dir == "..") {
+
+ if (curr > 0) { // pop a dir
+ curr -= 2;
+ };
+ continue;
+ };
+
+ pos_stack[curr++] = start;
+ pos_stack[curr++] = next;
+
+ } while (pos < p_path.length());
+
+ String path;
+ if (p_path[0] == '/') {
+ path = "/";
+ };
+
+ int i=0;
+ while (i < curr) {
+
+ int start = pos_stack[i++];
+
+ while ( ((i+1)<curr) && (pos_stack[i] == pos_stack[i+1]) ) {
+
+ ++i;
+ };
+ path = path + p_path.substr(start, (pos_stack[i++] - start) + 1);
+ };
+
+ return path;
+};
+
+String DirAccess::get_next(bool* p_is_dir) {
+
+ String next=get_next();
+ if (p_is_dir)
+ *p_is_dir=current_is_dir();
+ return next;
+}
+
+String DirAccess::fix_path(String p_path) const {
+
+ switch(_access_type) {
+
+ case ACCESS_RESOURCES: {
+
+ if (Globals::get_singleton()) {
+ if (p_path.begins_with("res://")) {
+
+ String resource_path = Globals::get_singleton()->get_resource_path();
+ if (resource_path != "") {
+
+ return p_path.replace("res:/",resource_path);
+ };
+ return p_path.replace("res://", "");
+ }
+ }
+
+
+ } break;
+ case ACCESS_USERDATA: {
+
+
+ if (p_path.begins_with("user://")) {
+
+ String data_dir=OS::get_singleton()->get_data_dir();
+ if (data_dir != "") {
+
+ return p_path.replace("user:/",data_dir);
+ };
+ return p_path.replace("user://", "");
+ }
+
+ } break;
+ case ACCESS_FILESYSTEM: {
+
+ return p_path;
+ } break;
+ }
+
+ return p_path;
+}
+
+
+DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX]={0,0,0};
+
+DirAccess *DirAccess::create_for_path(const String& p_path) {
+
+ DirAccess *da=NULL;
+ if (p_path.begins_with("res://")) {
+
+ da=create(ACCESS_RESOURCES);
+ } else if (p_path.begins_with("user://")) {
+
+ da=create(ACCESS_USERDATA);
+ } else {
+
+ da=create(ACCESS_FILESYSTEM);
+ }
+
+ return da;
+}
+
+DirAccess *DirAccess::open(const String& p_path,Error *r_error) {
+
+ DirAccess *da=create_for_path(p_path);
+
+ ERR_FAIL_COND_V(!da,NULL);
+ Error err = da->change_dir(p_path);
+ if (r_error)
+ *r_error=err;
+ if (err!=OK) {
+ memdelete(da);
+ return NULL;
+ }
+
+ return da;
+}
+
+DirAccess *DirAccess::create(AccessType p_access) {
+
+ DirAccess * da = create_func[p_access]?create_func[p_access]():NULL;
+ if (da) {
+ da->_access_type=p_access;
+ }
+
+ return da;
+};
+
+
+String DirAccess::get_full_path(const String& p_path,AccessType p_access) {
+
+ DirAccess *d=DirAccess::create(p_access);
+ if (!d)
+ return p_path;
+
+ d->change_dir(p_path);
+ String full=d->get_current_dir();
+ memdelete(d);
+ return full;
+}
+
+Error DirAccess::copy(String p_from,String p_to) {
+
+ //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
+ Error err;
+ FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ,&err);
+
+ if (err) {
+
+ ERR_FAIL_COND_V( err, err );
+ }
+
+
+ FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE,&err );
+ if (err) {
+
+ fsrc->close();
+ memdelete( fsrc );
+ ERR_FAIL_COND_V( err, err );
+ }
+
+ fsrc->seek_end(0);
+ int size = fsrc->get_pos();
+ fsrc->seek(0);
+ err = OK;
+ while(size--) {
+
+ if (fsrc->get_error()!=OK) {
+ err= fsrc->get_error();
+ break;
+ }
+ if (fdst->get_error()!=OK) {
+ err= fdst->get_error();
+ break;
+ }
+
+ fdst->store_8( fsrc->get_8() );
+ }
+
+ memdelete(fsrc);
+ memdelete(fdst);
+
+ return err;
+}
+
+DirAccess::DirAccess(){
+
+ _access_type=ACCESS_FILESYSTEM;
+}
+
+
+DirAccess::~DirAccess() {
+
+}
+
+
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
new file mode 100644
index 0000000000..58a925465a
--- /dev/null
+++ b/core/os/dir_access.h
@@ -0,0 +1,143 @@
+/*************************************************************************/
+/* dir_access.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 DIR_ACCESS_H
+#define DIR_ACCESS_H
+
+
+#include "typedefs.h"
+#include "ustring.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+//@ TOOD, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
+class DirAccess {
+public:
+
+ enum AccessType {
+ ACCESS_RESOURCES,
+ ACCESS_USERDATA,
+ ACCESS_FILESYSTEM,
+ ACCESS_MAX
+ };
+
+
+
+ typedef DirAccess*(*CreateFunc)();
+
+private:
+
+
+ AccessType _access_type;
+ static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+protected:
+ String _get_root_path() const;
+ String _get_root_string() const;
+
+ String fix_path(String p_path) const;
+ bool next_is_dir;
+
+ template<class T>
+ static DirAccess* _create_builtin() {
+
+ return memnew( T );
+ }
+
+public:
+
+ static String normalize_path(const String& p_path);
+
+ virtual bool list_dir_begin()=0; ///< This starts dir listing
+ virtual String get_next(bool* p_is_dir); // compatibility
+ virtual String get_next()=0;
+ virtual bool current_is_dir() const=0;
+
+ virtual void list_dir_end()=0; ///<
+
+ virtual int get_drive_count()=0;
+ virtual String get_drive(int p_drive)=0;
+
+ virtual Error change_dir(String p_dir)=0; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir()=0; ///< return current dir location
+ virtual Error make_dir(String p_dir)=0;
+ virtual Error make_dir_recursive(String p_dir);
+ virtual Error erase_contents_recursive(); //super dangerous, use with care!
+
+ virtual bool file_exists(String p_file)=0;
+
+
+ virtual size_t get_space_left()=0;
+
+ virtual Error copy(String p_from,String p_to);
+ virtual Error rename(String p_from, String p_to)=0;
+ virtual Error remove(String p_name)=0;
+
+ static String get_full_path(const String& p_path,AccessType p_access);
+ static DirAccess *create_for_path(const String& p_path);
+
+/*
+ enum DirType {
+
+ FILE_TYPE_INVALID,
+ FILE_TYPE_FILE,
+ FILE_TYPE_DIR,
+ };
+
+ //virtual DirType get_file_type() const=0;
+*/
+ static DirAccess *create(AccessType p_access);
+
+ template<class T>
+ static void make_default(AccessType p_access) {
+
+ create_func[p_access]=_create_builtin<T>;
+ }
+
+ static DirAccess *open(const String& p_path,Error *r_error=NULL);
+
+ DirAccess();
+ virtual ~DirAccess();
+
+};
+
+struct DirAccessRef {
+
+ _FORCE_INLINE_ DirAccess* operator->() {
+
+ return f;
+ }
+
+ operator bool() const { return f!=NULL; }
+ DirAccess *f;
+ DirAccessRef(DirAccess *fa) { f = fa; }
+ ~DirAccessRef() { if (f) memdelete(f); }
+};
+
+#endif
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
new file mode 100644
index 0000000000..23250a7345
--- /dev/null
+++ b/core/os/file_access.cpp
@@ -0,0 +1,497 @@
+/*************************************************************************/
+/* file_access.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 "file_access.h"
+#include "globals.h"
+#include "os/os.h"
+#include "core/io/marshalls.h"
+#include "io/md5.h"
+#include "core/io/file_access_pack.h"
+
+FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX]={0,0};
+
+
+bool FileAccess::backup_save=false;
+
+FileAccess *FileAccess::create(AccessType p_access){
+
+ ERR_FAIL_COND_V( !create_func, 0 );
+ ERR_FAIL_INDEX_V( p_access,ACCESS_MAX, 0 );
+
+ FileAccess *ret = create_func[p_access]();
+ ret->_set_access_type(p_access);
+ return ret;
+}
+
+bool FileAccess::exists(const String& p_name) {
+
+ if (PackedData::get_singleton()->has_path(p_name))
+ return true;
+
+ FileAccess *f=open(p_name,READ);
+ if (!f)
+ return false;
+ memdelete(f);
+ return true;
+
+
+}
+
+void FileAccess::_set_access_type(AccessType p_access) {
+
+ _access_type = p_access;
+};
+
+FileAccess *FileAccess::create_for_path(const String& p_path) {
+
+ FileAccess *ret=NULL;
+ if (p_path.begins_with("res://")) {
+
+ ret = create(ACCESS_RESOURCES);
+ } else if (p_path.begins_with("user://")) {
+
+ ret = create(ACCESS_USERDATA);
+
+ } else {
+
+ ret = create(ACCESS_FILESYSTEM);
+ }
+
+ return ret;
+
+
+}
+
+Error FileAccess::reopen(const String& p_path, int p_mode_flags) {
+
+ return _open(p_path, p_mode_flags);
+};
+
+
+FileAccess *FileAccess::open(const String& p_path, int p_mode_flags, Error *r_error) {
+
+ //try packed data first
+
+ FileAccess *ret=NULL;
+ if (!(p_mode_flags&WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
+ ret = PackedData::get_singleton()->try_open_path(p_path);
+ if (ret) {
+ if (r_error)
+ *r_error=OK;
+ return ret;
+ }
+ }
+
+ ret=create_for_path(p_path);
+ Error err = ret->_open(p_path,p_mode_flags);
+
+ if (r_error)
+ *r_error=err;
+ if (err!=OK) {
+
+ memdelete(ret);
+ ret=NULL;
+ }
+
+ return ret;
+}
+
+
+FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) {
+
+ return create_func[p_access];
+};
+
+String FileAccess::fix_path(const String& p_path) const {
+ //helper used by file accesses that use a single filesystem
+
+ String r_path = p_path.replace("\\", "/");
+
+ switch(_access_type) {
+
+ case ACCESS_RESOURCES: {
+
+ if (Globals::get_singleton()) {
+ if (r_path.begins_with("res://")) {
+
+ String resource_path = Globals::get_singleton()->get_resource_path();
+ if (resource_path != "") {
+
+ return r_path.replace("res:/",resource_path);
+ };
+ return r_path.replace("res://", "");
+ }
+ }
+
+
+ } break;
+ case ACCESS_USERDATA: {
+
+
+ if (r_path.begins_with("user://")) {
+
+ String data_dir=OS::get_singleton()->get_data_dir();
+ if (data_dir != "") {
+
+ return r_path.replace("user:/",data_dir);
+ };
+ return r_path.replace("user://", "");
+ }
+
+ } break;
+ case ACCESS_FILESYSTEM: {
+
+ return r_path;
+ } break;
+ }
+
+ return r_path;
+}
+
+/* these are all implemented for ease of porting, then can later be optimized */
+
+uint16_t FileAccess::get_16()const {
+
+ uint16_t res;
+ uint8_t a,b;
+
+ a=get_8();
+ b=get_8();
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ res=b;
+ res<<=8;
+ res|=a;
+
+ return res;
+}
+uint32_t FileAccess::get_32() const{
+
+ uint32_t res;
+ uint16_t a,b;
+
+ a=get_16();
+ b=get_16();
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ res=b;
+ res<<=16;
+ res|=a;
+
+ return res;
+}
+uint64_t FileAccess::get_64()const {
+
+ uint64_t res;
+ uint32_t a,b;
+
+ a=get_32();
+ b=get_32();
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ res=b;
+ res<<=32;
+ res|=a;
+
+ return res;
+
+}
+
+float FileAccess::get_float() const {
+
+ MarshallFloat m;
+ m.i = get_32();
+ return m.f;
+};
+
+real_t FileAccess::get_real() const {
+
+ if (real_is_double)
+ return get_double();
+ else
+ return get_float();
+
+}
+
+double FileAccess::get_double() const {
+
+ MarshallDouble m;
+ m.l = get_64();
+ return m.d;
+};
+
+String FileAccess::get_line() const {
+
+ CharString line;
+
+ CharType c=get_8();
+
+ while(!eof_reached()) {
+
+ if (c=='\n' || c=='\0') {
+ line.push_back(0);
+ return String::utf8(line.get_data());
+ } else if (c!='\r')
+ line.push_back(c);
+
+ c=get_8();
+ }
+ line.push_back(0);
+ return String::utf8(line.get_data());
+}
+
+Vector<String> FileAccess::get_csv_line() const {
+
+ String l;
+ int qc=0;
+ do {
+ l+=get_line();
+ qc=0;
+ for(int i=0;i<l.length();i++) {
+
+ if (l[i]=='"')
+ qc++;
+ }
+
+
+ } while (qc%2);
+
+ Vector<String> strings;
+
+ bool in_quote=false;
+ String current;
+ for(int i=0;i<l.length();i++) {
+
+ CharType c = l[i];
+ CharType s[2]={0,0};
+
+
+ if (!in_quote && c==',') {
+ strings.push_back(current);
+ current=String();
+ } else if (c=='"') {
+ if (l[i+1]=='"') {
+ s[0]='"';
+ current+=s;
+ i++;
+ } else {
+
+ in_quote=!in_quote;
+ }
+ } else {
+ s[0]=c;
+ current+=s;
+ }
+
+ }
+
+ strings.push_back(current);
+
+ return strings;
+}
+
+
+int FileAccess::get_buffer(uint8_t *p_dst,int p_length) const{
+
+ int i=0;
+ for (i=0; i<p_length && !eof_reached(); i++)
+ p_dst[i]=get_8();
+
+ return i;
+}
+
+void FileAccess::store_16(uint16_t p_dest) {
+
+ uint8_t a,b;
+
+ a=p_dest&0xFF;
+ b=p_dest>>8;
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ store_8(a);
+ store_8(b);
+
+}
+void FileAccess::store_32(uint32_t p_dest) {
+
+
+ uint16_t a,b;
+
+ a=p_dest&0xFFFF;
+ b=p_dest>>16;
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ store_16(a);
+ store_16(b);
+
+}
+void FileAccess::store_64(uint64_t p_dest) {
+
+ uint32_t a,b;
+
+ a=p_dest&0xFFFFFFFF;
+ b=p_dest>>32;
+
+ if (endian_swap) {
+
+ SWAP( a,b );
+ }
+
+ store_32(a);
+ store_32(b);
+
+}
+
+void FileAccess::store_real(real_t p_real) {
+
+ if (sizeof(real_t)==4)
+ store_float(p_real);
+ else
+ store_double(p_real);
+
+}
+
+void FileAccess::store_float(float p_dest) {
+
+ MarshallFloat m;
+ m.f = p_dest;
+ store_32(m.i);
+};
+
+void FileAccess::store_double(double p_dest) {
+
+ MarshallDouble m;
+ m.d = p_dest;
+ store_64(m.l);
+};
+
+uint64_t FileAccess::get_modified_time(const String& p_file) {
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V(!fa,0);
+
+ uint64_t mt = fa->_get_modified_time(p_file);
+ memdelete(fa);
+ return mt;
+}
+
+void FileAccess::store_string(const String& p_string) {
+
+ if (p_string.length()==0)
+ return;
+
+ CharString cs=p_string.utf8();
+ store_buffer((uint8_t*)&cs[0],cs.length());
+
+
+}
+void FileAccess::store_line(const String& p_line) {
+
+ store_string(p_line);
+ store_8('\n');
+}
+
+void FileAccess::store_buffer(const uint8_t *p_src,int p_length) {
+
+ for (int i=0;i<p_length;i++)
+ store_8(p_src[i]);
+}
+
+Vector<uint8_t> FileAccess::get_file_as_array(const String& p_file) {
+
+ FileAccess *f=FileAccess::open(p_file,READ);
+ ERR_FAIL_COND_V(!f,Vector<uint8_t>());
+ Vector<uint8_t> data;
+ data.resize(f->get_len());
+ f->get_buffer(data.ptr(),data.size());
+ memdelete(f);
+ return data;
+
+
+}
+
+String FileAccess::get_md5(const String& p_file) {
+
+ FileAccess *f=FileAccess::open(p_file,READ);
+ if (!f)
+ return String();
+
+ MD5_CTX md5;
+ MD5Init(&md5);
+
+ unsigned char step[32768];
+
+ while(true) {
+
+ int br = f->get_buffer(step,32768);
+ if (br>0) {
+
+ MD5Update(&md5,step,br);
+ }
+ if (br < 4096)
+ break;
+
+ }
+
+ MD5Final(&md5);
+
+ String ret = String::md5(md5.digest);
+
+
+
+ memdelete(f);
+ return ret;
+
+}
+
+FileAccess::FileAccess() {
+
+ endian_swap=false;
+ real_is_double=false;
+ _access_type=ACCESS_FILESYSTEM;
+};
diff --git a/core/os/file_access.h b/core/os/file_access.h
new file mode 100644
index 0000000000..bcdae61487
--- /dev/null
+++ b/core/os/file_access.h
@@ -0,0 +1,175 @@
+/*************************************************************************/
+/* file_access.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 FILE_ACCESS_H
+#define FILE_ACCESS_H
+
+#include "typedefs.h"
+#include "ustring.h"
+#include "os/memory.h"
+#include "math_defs.h"
+/**
+ * Multi-Platform abstraction for accessing to files.
+ */
+
+class FileAccess {
+
+public:
+ enum AccessType {
+ ACCESS_RESOURCES,
+ ACCESS_USERDATA,
+ ACCESS_FILESYSTEM,
+ ACCESS_MAX
+ };
+
+ typedef FileAccess*(*CreateFunc)();
+ bool endian_swap;
+ bool real_is_double;
+protected:
+
+ String fix_path(const String& p_path) const;
+ virtual Error _open(const String& p_path, int p_mode_flags)=0; ///< open a file
+ virtual uint64_t _get_modified_time(const String& p_file)=0;
+
+
+private:
+
+ static bool backup_save;
+
+ AccessType _access_type;
+ static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
+ template<class T>
+ static FileAccess* _create_builtin() {
+
+ return memnew( T );
+ }
+
+public:
+
+ virtual void _set_access_type(AccessType p_access);
+
+ enum ModeFlags {
+
+ READ=1,
+ WRITE=2,
+ READ_WRITE=3,
+ };
+
+ virtual void close()=0; ///< close a file
+ virtual bool is_open() const=0; ///< true when file is open
+
+ virtual void seek(size_t p_position)=0; ///< seek to a given position
+ virtual void seek_end(int64_t p_position=0)=0; ///< seek from the end of file
+ virtual size_t get_pos() const=0; ///< get position in the file
+ virtual size_t get_len() const=0; ///< get size of the file
+
+ virtual bool eof_reached() const=0; ///< reading passed EOF
+
+ virtual uint8_t get_8() const=0; ///< get a byte
+ virtual uint16_t get_16() const; ///< get 16 bits uint
+ virtual uint32_t get_32() const; ///< get 32 bits uint
+ virtual uint64_t get_64() const; ///< get 64 bits uint
+
+ virtual float get_float() const;
+ virtual double get_double() const;
+ virtual real_t get_real() const;
+
+ virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
+ virtual String get_line() const;
+ virtual Vector<String> get_csv_line() const;
+
+ /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
+ * It's not about the current CPU type but file formats.
+ * this flags get reset to false (little endian) on each open
+ */
+
+ virtual void set_endian_swap(bool p_swap) { endian_swap=p_swap; }
+ inline bool get_endian_swap() const { return endian_swap; }
+
+ virtual Error get_error() const=0; ///< get last error
+
+ virtual void store_8(uint8_t p_dest)=0; ///< store a byte
+ virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
+ virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
+ virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
+
+ virtual void store_float(float p_dest);
+ virtual void store_double(double p_dest);
+ virtual void store_real(real_t p_real);
+
+ virtual void store_string(const String& p_string);
+ virtual void store_line(const String& p_string);
+
+ virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes
+
+ virtual bool file_exists(const String& p_name)=0; ///< return true if a file exists
+
+ virtual Error reopen(const String& p_path, int p_mode_flags); ///< does not change the AccessType
+
+ static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static FileAccess *create_for_path(const String& p_path);
+ static FileAccess *open(const String& p_path, int p_mode_flags, Error *r_error=NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static CreateFunc get_create_func(AccessType p_access);
+ static bool exists(const String& p_name); ///< return true if a file exists
+ static uint64_t get_modified_time(const String& p_file);
+
+
+ static void set_backup_save(bool p_enable) { backup_save=p_enable; };
+ static bool is_backup_save_enabled() { return backup_save; };
+
+ static String get_md5(const String& p_file);
+
+ static Vector<uint8_t> get_file_as_array(const String& p_path);
+
+
+ template<class T>
+ static void make_default(AccessType p_access) {
+
+ create_func[p_access]=_create_builtin<T>;
+ }
+
+ FileAccess();
+ virtual ~FileAccess(){}
+
+};
+
+
+struct FileAccessRef {
+
+ _FORCE_INLINE_ FileAccess* operator->() {
+
+ return f;
+ }
+
+ operator bool() const { return f!=NULL; }
+ FileAccess *f;
+ FileAccessRef(FileAccess *fa) { f = fa; }
+ ~FileAccessRef() { if (f) memdelete(f); }
+};
+
+#endif
diff --git a/core/os/input.cpp b/core/os/input.cpp
new file mode 100644
index 0000000000..3266e4cc10
--- /dev/null
+++ b/core/os/input.cpp
@@ -0,0 +1,311 @@
+/*************************************************************************/
+/* input.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 "input.h"
+#include "input_map.h"
+#include "os/os.h"
+Input *Input::singleton=NULL;
+
+Input *Input::get_singleton() {
+
+ return singleton;
+}
+
+void Input::set_mouse_mode(MouseMode p_mode) {
+ ERR_FAIL_INDEX(p_mode,3);
+ OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode);
+}
+
+Input::MouseMode Input::get_mouse_mode() const {
+
+ return (MouseMode)OS::get_singleton()->get_mouse_mode();
+}
+
+void Input::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("is_key_pressed","scancode"),&Input::is_key_pressed);
+ ObjectTypeDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
+ ObjectTypeDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
+ ObjectTypeDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed);
+ ObjectTypeDB::bind_method(_MD("get_joy_axis","device","axis"),&Input::get_joy_axis);
+ ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer);
+ ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos);
+ ObjectTypeDB::bind_method(_MD("get_mouse_speed"),&Input::get_mouse_speed);
+ ObjectTypeDB::bind_method(_MD("set_mouse_mode","mode"),&Input::set_mouse_mode);
+ ObjectTypeDB::bind_method(_MD("get_mouse_mode"),&Input::get_mouse_mode);
+
+ BIND_CONSTANT( MOUSE_MODE_VISIBLE );
+ BIND_CONSTANT( MOUSE_MODE_HIDDEN );
+ BIND_CONSTANT( MOUSE_MODE_CAPTURED );
+
+}
+
+Input::Input() {
+
+ singleton=this;
+}
+
+
+//////////////////////////////////////////////////////////
+
+
+void InputDefault::SpeedTrack::update(const Vector2& p_delta_p) {
+
+ uint64_t tick = OS::get_singleton()->get_ticks_usec();
+ uint32_t tdiff = tick-last_tick;
+ float delta_t = tdiff / 1000000.0;
+ last_tick=tick;
+
+
+ accum+=p_delta_p;
+ accum_t+=delta_t;
+
+ if (accum_t>max_ref_frame*10)
+ accum_t=max_ref_frame*10;
+
+ while( accum_t>=min_ref_frame ) {
+
+ float slice_t = min_ref_frame / accum_t;
+ Vector2 slice = accum*slice_t;
+ accum=accum-slice;
+ accum_t-=min_ref_frame;
+
+ speed=(slice/min_ref_frame).linear_interpolate(speed,min_ref_frame/max_ref_frame);
+ }
+
+
+
+}
+
+void InputDefault::SpeedTrack::reset() {
+ last_tick = OS::get_singleton()->get_ticks_usec();
+ speed=Vector2();
+ accum_t=0;
+}
+
+InputDefault::SpeedTrack::SpeedTrack() {
+
+ min_ref_frame=0.1;
+ max_ref_frame=0.3;
+ reset();
+}
+
+bool InputDefault::is_key_pressed(int p_scancode) {
+
+ _THREAD_SAFE_METHOD_
+ return keys_pressed.has(p_scancode);
+}
+
+bool InputDefault::is_mouse_button_pressed(int p_button) {
+
+ _THREAD_SAFE_METHOD_
+ return (mouse_button_mask&(1<<p_button))!=0;
+}
+
+
+static int _combine_device(int p_value,int p_device) {
+
+ return p_value|(p_device<<20);
+}
+
+bool InputDefault::is_joy_button_pressed(int p_device, int p_button) {
+
+ _THREAD_SAFE_METHOD_
+ return joy_buttons_pressed.has(_combine_device(p_button,p_device));
+}
+
+bool InputDefault::is_action_pressed(const StringName& p_action) {
+
+ if (custom_action_press.has(p_action))
+ return true; //simpler
+
+ const List<InputEvent> *alist = InputMap::get_singleton()->get_action_list(p_action);
+ if (!alist)
+ return NULL;
+
+
+ for (const List<InputEvent>::Element *E=alist->front();E;E=E->next()) {
+
+
+ int device=E->get().device;
+
+ switch(E->get().type) {
+
+ case InputEvent::KEY: {
+
+ const InputEventKey &iek=E->get().key;
+ if ((keys_pressed.has(iek.scancode)))
+ return true;
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &iemb=E->get().mouse_button;
+ if(mouse_button_mask&(1<<iemb.button_index))
+ return true;
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+
+ const InputEventJoystickButton &iejb=E->get().joy_button;
+ int c = _combine_device(iejb.button_index,device);
+ if (joy_buttons_pressed.has(c))
+ return true;
+ } break;
+ }
+ }
+
+ return false;
+}
+
+float InputDefault::get_joy_axis(int p_device,int p_axis) {
+
+ _THREAD_SAFE_METHOD_
+ int c = _combine_device(p_axis,p_device);
+ if (joy_axis.has(c)) {
+ return joy_axis[c];
+ } else {
+ return 0;
+ }
+}
+
+Vector3 InputDefault::get_accelerometer() {
+
+ _THREAD_SAFE_METHOD_
+ return accelerometer;
+}
+
+void InputDefault::parse_input_event(const InputEvent& p_event) {
+
+ _THREAD_SAFE_METHOD_
+ switch(p_event.type) {
+
+ case InputEvent::KEY: {
+
+ if (p_event.key.echo)
+ break;
+ if (p_event.key.scancode==0)
+ break;
+
+ if (p_event.key.pressed)
+ keys_pressed.insert(p_event.key.scancode);
+ else
+ keys_pressed.erase(p_event.key.scancode);
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ if (p_event.mouse_button.doubleclick)
+ break;
+
+ if (p_event.mouse_button.pressed)
+ mouse_button_mask|=(1<<p_event.mouse_button.button_index);
+ else
+ mouse_button_mask&=~(1<<p_event.mouse_button.button_index);
+ } break;
+ case InputEvent::JOYSTICK_BUTTON: {
+
+ int c = _combine_device(p_event.joy_button.button_index,p_event.device);
+
+ if (p_event.joy_button.pressed)
+ joy_buttons_pressed.insert(c);
+ else
+ joy_buttons_pressed.erase(c);
+ } break;
+ case InputEvent::JOYSTICK_MOTION: {
+ set_joy_axis(p_event.device, p_event.joy_motion.axis, p_event.joy_motion.axis_value);
+ } break;
+
+ }
+
+ if (main_loop)
+ main_loop->input_event(p_event);
+
+}
+
+void InputDefault::set_joy_axis(int p_device,int p_axis,float p_value) {
+
+ _THREAD_SAFE_METHOD_
+ int c = _combine_device(p_axis,p_device);
+ joy_axis[c]=p_value;
+}
+
+void InputDefault::set_accelerometer(const Vector3& p_accel) {
+
+ _THREAD_SAFE_METHOD_
+
+ accelerometer=p_accel;
+
+}
+
+void InputDefault::set_main_loop(MainLoop *p_main_loop) {
+ main_loop=p_main_loop;
+
+}
+
+void InputDefault::set_mouse_pos(const Point2& p_posf) {
+
+ mouse_speed_track.update(p_posf-mouse_pos);
+ mouse_pos=p_posf;
+}
+
+Point2 InputDefault::get_mouse_pos() const {
+
+ return mouse_pos;
+}
+Point2 InputDefault::get_mouse_speed() const {
+
+ return mouse_speed_track.speed;
+}
+
+void InputDefault::iteration(float p_step) {
+
+
+}
+
+void InputDefault::action_press(const StringName& p_action) {
+
+ if (custom_action_press.has(p_action)) {
+
+ custom_action_press[p_action]++;
+ } else {
+ custom_action_press[p_action]=1;
+ }
+}
+
+void InputDefault::action_release(const StringName& p_action){
+
+ ERR_FAIL_COND(!custom_action_press.has(p_action));
+ custom_action_press[p_action]--;
+ if (custom_action_press[p_action]==0) {
+ custom_action_press.erase(p_action);
+ }
+}
+
+InputDefault::InputDefault() {
+
+ mouse_button_mask=0;
+ main_loop=NULL;
+}
diff --git a/core/os/input.h b/core/os/input.h
new file mode 100644
index 0000000000..3f62b93972
--- /dev/null
+++ b/core/os/input.h
@@ -0,0 +1,140 @@
+/*************************************************************************/
+/* input.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 INPUT_H
+#define INPUT_H
+
+#include "object.h"
+#include "os/thread_safe.h"
+#include "os/main_loop.h"
+
+class Input : public Object {
+
+ OBJ_TYPE( Input, Object );
+
+ static Input *singleton;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ enum MouseMode {
+ MOUSE_MODE_VISIBLE,
+ MOUSE_MODE_HIDDEN,
+ MOUSE_MODE_CAPTURED
+ };
+
+ void set_mouse_mode(MouseMode p_mode);
+ MouseMode get_mouse_mode() const;
+
+ static Input *get_singleton();
+
+ virtual bool is_key_pressed(int p_scancode)=0;
+ virtual bool is_mouse_button_pressed(int p_button)=0;
+ virtual bool is_joy_button_pressed(int p_device, int p_button)=0;
+ virtual bool is_action_pressed(const StringName& p_action)=0;
+
+ virtual float get_joy_axis(int p_device,int p_axis)=0;
+
+ virtual Point2 get_mouse_pos() const=0;
+ virtual Point2 get_mouse_speed() const=0;
+
+ virtual Vector3 get_accelerometer()=0;
+
+ virtual void action_press(const StringName& p_action)=0;
+ virtual void action_release(const StringName& p_action)=0;
+
+ Input();
+};
+
+VARIANT_ENUM_CAST(Input::MouseMode);
+
+class InputDefault : public Input {
+
+ OBJ_TYPE( InputDefault, Input );
+ _THREAD_SAFE_CLASS_
+
+ int mouse_button_mask;
+ Set<int> keys_pressed;
+ Set<int> joy_buttons_pressed;
+ Map<int,float> joy_axis;
+ Map<StringName,int> custom_action_press;
+ Vector3 accelerometer;
+ Vector2 mouse_pos;
+ MainLoop *main_loop;
+
+ struct SpeedTrack {
+
+ uint64_t last_tick;
+ Vector2 speed;
+ Vector2 accum;
+ float accum_t;
+ float min_ref_frame;
+ float max_ref_frame;
+
+ void update(const Vector2& p_delta_p);
+ void reset();
+ SpeedTrack();
+ };
+
+ SpeedTrack mouse_speed_track;
+
+public:
+
+
+
+ virtual bool is_key_pressed(int p_scancode);
+ virtual bool is_mouse_button_pressed(int p_button);
+ virtual bool is_joy_button_pressed(int p_device, int p_button);
+ virtual bool is_action_pressed(const StringName& p_action);
+
+ virtual float get_joy_axis(int p_device,int p_axis);
+
+ virtual Vector3 get_accelerometer();
+
+ virtual Point2 get_mouse_pos() const;
+ virtual Point2 get_mouse_speed() const;
+
+ void parse_input_event(const InputEvent& p_event);
+ void set_accelerometer(const Vector3& p_accel);
+ void set_joy_axis(int p_device,int p_axis,float p_value);
+
+ void set_main_loop(MainLoop *main_loop);
+ void set_mouse_pos(const Point2& p_posf);
+
+ void action_press(const StringName& p_action);
+ void action_release(const StringName& p_action);
+
+ void iteration(float p_step);
+
+ InputDefault();
+
+};
+
+#endif // INPUT_H
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
new file mode 100644
index 0000000000..499ec0c08e
--- /dev/null
+++ b/core/os/input_event.cpp
@@ -0,0 +1,190 @@
+/*************************************************************************/
+/* input_event.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 "input_event.h"
+#include "input_map.h"
+#include "os/keyboard.h"
+/**
+ *
+ */
+
+bool InputEvent::operator==(const InputEvent &p_event) const {
+
+ return true;
+}
+InputEvent::operator String() const {
+
+ String str="Device "+itos(device)+" ID "+itos(ID)+" ";
+
+ switch(type) {
+
+ case NONE: {
+
+ return "Event: None";
+ } break;
+ case KEY: {
+
+ str+= "Event: Key ";
+ str=str+"Unicode: "+String::chr(key.unicode)+" Scan: "+itos( key.scancode )+" Echo: "+String(key.echo?"True":"False")+" Pressed"+String(key.pressed?"True":"False")+" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ return str;
+ } break;
+ case MOUSE_MOTION: {
+
+ str+= "Event: Motion ";
+ str=str+" Pos: " +itos(mouse_motion.x)+","+itos(mouse_motion.y)+" Rel: "+itos(mouse_motion.relative_x)+","+itos(mouse_motion.relative_y)+" Mask: ";
+ for (int i=0;i<8;i++) {
+
+ if ((1<<i)&mouse_motion.button_mask)
+ str+=itos(i+1);
+ }
+ str+=" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ return str;
+ } break;
+ case MOUSE_BUTTON: {
+ str+= "Event: Button ";
+ str=str+"Pressed: "+itos(mouse_button.pressed)+" Pos: " +itos(mouse_button.x)+","+itos(mouse_button.y)+" Button: "+itos(mouse_button.button_index)+" Mask: ";
+ for (int i=0;i<8;i++) {
+
+ if ((1<<i)&mouse_button.button_mask)
+ str+=itos(i+1);
+ }
+ str+=" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ str+=String(" DoubleClick: ")+(mouse_button.doubleclick?"Yes":"No");
+
+ return str;
+
+ } break;
+ case JOYSTICK_MOTION: {
+ str+= "Event: JoyMotion ";
+ str=str+"Axis: "+itos(joy_motion.axis)+" Value: " +rtos(joy_motion.axis_value);
+ return str;
+
+ } break;
+ case JOYSTICK_BUTTON: {
+ str+= "Event: JoyButton ";
+ str=str+"Pressed: "+itos(joy_button.pressed)+" Index: " +itos(joy_button.button_index)+" pressure "+rtos(joy_button.pressure);
+ return str;
+
+ } break;
+ case SCREEN_TOUCH: {
+ str+= "Event: ScreenTouch ";
+ str=str+"Pressed: "+itos(screen_touch.pressed)+" Index: " +itos(screen_touch.index)+" pos "+rtos(screen_touch.x)+","+rtos(screen_touch.y);
+ return str;
+
+ } break;
+ case SCREEN_DRAG: {
+ str+= "Event: ScreenDrag ";
+ str=str+" Index: " +itos(screen_drag.index)+" pos "+rtos(screen_drag.x)+","+rtos(screen_drag.y);
+ return str;
+
+ } break;
+ case ACTION: {
+ str+= "Event: Action: "+InputMap::get_singleton()->get_action_from_id(action.action)+" Pressed: "+itos(action.pressed);
+ return str;
+
+ } break;
+
+ }
+
+ return "";
+}
+
+void InputEvent::set_as_action(const String& p_action) {
+
+ type=ACTION;
+ action.action=InputMap::get_singleton()->get_action_id(p_action);
+ action.pressed=false;
+}
+
+bool InputEvent::is_pressed() const {
+
+ switch(type) {
+
+ case KEY: return key.pressed;
+ case MOUSE_BUTTON: return mouse_button.pressed;
+ case JOYSTICK_BUTTON: return joy_button.pressed;
+ case SCREEN_TOUCH: return screen_touch.pressed;
+ case ACTION: return action.pressed;
+ default: {}
+ }
+
+ return false;
+}
+
+bool InputEvent::is_echo() const {
+
+ return (type==KEY && key.echo);
+}
+
+bool InputEvent::is_action(const String& p_action) const {
+
+ return InputMap::get_singleton()->event_is_action(*this,p_action);
+}
+
+uint32_t InputEventKey::get_scancode_with_modifiers() const {
+
+ uint32_t sc=scancode;
+ if (mod.control)
+ sc|=KEY_MASK_CTRL;
+ if (mod.alt)
+ sc|=KEY_MASK_ALT;
+ if (mod.shift)
+ sc|=KEY_MASK_SHIFT;
+ if (mod.meta)
+ sc|=KEY_MASK_META;
+
+ return sc;
+
+}
diff --git a/core/os/input_event.h b/core/os/input_event.h
new file mode 100644
index 0000000000..2c10bffcd2
--- /dev/null
+++ b/core/os/input_event.h
@@ -0,0 +1,299 @@
+/*************************************************************************/
+/* input_event.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 INPUT_EVENT_H
+#define INPUT_EVENT_H
+
+
+#include "typedefs.h"
+#include "os/copymem.h"
+#include "ustring.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+
+
+/**
+ * Input Event classes. These are used in the main loop.
+ * The events are pretty obvious.
+ */
+
+enum {
+ BUTTON_LEFT=1,
+ BUTTON_RIGHT=2,
+ BUTTON_MIDDLE=3,
+ BUTTON_WHEEL_UP=4,
+ BUTTON_WHEEL_DOWN=5,
+ BUTTON_MASK_LEFT=(1<<(BUTTON_LEFT-1)),
+ BUTTON_MASK_RIGHT=(1<<(BUTTON_RIGHT-1)),
+ BUTTON_MASK_MIDDLE=(1<<(BUTTON_MIDDLE-1)),
+
+};
+
+enum {
+
+ JOY_BUTTON_0 = 0,
+ JOY_BUTTON_1 = 1,
+ JOY_BUTTON_2 = 2,
+ JOY_BUTTON_3 = 3,
+ JOY_BUTTON_4 = 4,
+ JOY_BUTTON_5 = 5,
+ JOY_BUTTON_6 = 6,
+ JOY_BUTTON_7 = 7,
+ JOY_BUTTON_8 = 8,
+ JOY_BUTTON_9 = 9,
+ JOY_BUTTON_10 = 10,
+ JOY_BUTTON_11 = 11,
+ JOY_BUTTON_12 = 12,
+ JOY_BUTTON_13 = 13,
+ JOY_BUTTON_14 = 14,
+ JOY_BUTTON_15 = 15,
+ JOY_BUTTON_MAX = 16,
+
+ JOY_L = JOY_BUTTON_4,
+ JOY_R = JOY_BUTTON_5,
+ JOY_L2 = JOY_BUTTON_6,
+ JOY_R2 = JOY_BUTTON_7,
+ JOY_L3 = JOY_BUTTON_8,
+ JOY_R3 = JOY_BUTTON_9,
+ JOY_SELECT = JOY_BUTTON_10,
+ JOY_START = JOY_BUTTON_11,
+ JOY_DPAD_UP = JOY_BUTTON_12,
+ JOY_DPAD_DOWN = JOY_BUTTON_13,
+ JOY_DPAD_LEFT = JOY_BUTTON_14,
+ JOY_DPAD_RIGHT = JOY_BUTTON_15,
+
+ // a little history about game controllers (who copied who)
+
+ JOY_SNES_B = JOY_BUTTON_0,
+ JOY_SNES_A = JOY_BUTTON_1,
+ JOY_SNES_Y = JOY_BUTTON_2,
+ JOY_SNES_X = JOY_BUTTON_3,
+
+ JOY_SONY_CIRCLE=JOY_SNES_A,
+ JOY_SONY_X=JOY_SNES_B,
+ JOY_SONY_SQUARE=JOY_SNES_Y,
+ JOY_SONY_TRIANGLE=JOY_SNES_X,
+
+ JOY_SEGA_B=JOY_SNES_A,
+ JOY_SEGA_A=JOY_SNES_B,
+ JOY_SEGA_X=JOY_SNES_Y,
+ JOY_SEGA_Y=JOY_SNES_X,
+
+ JOY_XBOX_B=JOY_SEGA_B,
+ JOY_XBOX_A=JOY_SEGA_A,
+ JOY_XBOX_X=JOY_SEGA_X,
+ JOY_XBOX_Y=JOY_SEGA_Y,
+
+ JOY_DS_A = JOY_SNES_A,
+ JOY_DS_B = JOY_SNES_B,
+ JOY_DS_X = JOY_SNES_X,
+ JOY_DS_Y = JOY_SNES_Y,
+
+ JOY_WII_C = JOY_BUTTON_5,
+ JOY_WII_Z = JOY_BUTTON_6,
+
+ JOY_WII_MINUS = JOY_BUTTON_9,
+ JOY_WII_PLUS = JOY_BUTTON_10,
+
+ // end of history
+
+ JOY_AXIS_0=0,
+ JOY_AXIS_1=1,
+ JOY_AXIS_2=2,
+ JOY_AXIS_3=3,
+ JOY_AXIS_4=4,
+ JOY_AXIS_5=5,
+ JOY_AXIS_6=6,
+ JOY_AXIS_7=7,
+ JOY_AXIS_MAX=8,
+
+ JOY_ANALOG_0_X = JOY_AXIS_0,
+ JOY_ANALOG_0_Y = JOY_AXIS_1,
+
+ JOY_ANALOG_1_X = JOY_AXIS_2,
+ JOY_ANALOG_1_Y = JOY_AXIS_3,
+
+ JOY_ANALOG_2_X = JOY_AXIS_4,
+ JOY_ANALOG_2_Y = JOY_AXIS_5,
+};
+
+
+/**
+ * Input Modifier Status
+ * for keyboard/mouse events.
+ */
+struct InputModifierState {
+
+ bool shift;
+ bool alt;
+#ifdef APPLE_STYLE_KEYS
+ union {
+ bool command;
+ bool meta; //< windows/mac key
+ };
+
+ bool control;
+#else
+ union {
+ bool command; //< windows/mac key
+ bool control;
+ };
+ bool meta; //< windows/mac key
+
+#endif
+
+ bool operator==(const InputModifierState& rvalue) const {
+
+ return ( (shift==rvalue.shift) && (alt==rvalue.alt) && (control==rvalue.control) && (meta==rvalue.meta));
+ }
+};
+
+
+
+
+
+
+struct InputEventKey {
+
+ InputModifierState mod;
+
+ bool pressed; /// otherwise release
+
+ uint32_t scancode; ///< check keyboard.h , KeyCode enum, without modifier masks
+ uint32_t unicode; ///unicode
+
+ uint32_t get_scancode_with_modifiers() const;
+
+ bool echo; /// true if this is an echo key
+};
+
+
+struct InputEventMouse {
+
+ InputModifierState mod;
+ int button_mask;
+ int x,y;
+ int global_x,global_y;
+ int pointer_index;
+};
+
+struct InputEventMouseButton : public InputEventMouse {
+
+
+ int button_index;
+ bool pressed; //otherwise released
+ bool doubleclick; //last even less than doubleclick time
+
+};
+
+struct InputEventMouseMotion : public InputEventMouse {
+
+ int relative_x,relative_y;
+ float speed_x,speed_y;
+};
+
+struct InputEventJoystickMotion {
+
+ int axis; ///< Joystick axis
+ float axis_value; ///< -1 to 1
+};
+
+struct InputEventJoystickButton {
+
+ int button_index;
+ bool pressed;
+ float pressure; //0 to 1
+};
+
+struct InputEventScreenTouch {
+
+ int index;
+ int x,y;
+ bool pressed;
+};
+struct InputEventScreenDrag {
+
+ int index;
+ int x,y;
+ int relative_x,relative_y;
+ float speed_x,speed_y;
+};
+
+struct InputEventAction {
+
+ int action;
+ bool pressed;
+};
+
+
+
+struct InputEvent {
+
+ enum Type {
+ NONE,
+ KEY,
+ MOUSE_MOTION,
+ MOUSE_BUTTON,
+ JOYSTICK_MOTION,
+ JOYSTICK_BUTTON,
+ SCREEN_TOUCH,
+ SCREEN_DRAG,
+ ACTION,
+ TYPE_MAX
+ };
+
+ uint32_t ID;
+ int type;
+ int device;
+
+ union {
+ InputEventMouseMotion mouse_motion;
+ InputEventMouseButton mouse_button;
+ InputEventJoystickMotion joy_motion;
+ InputEventJoystickButton joy_button;
+ InputEventKey key;
+ InputEventScreenTouch screen_touch;
+ InputEventScreenDrag screen_drag;
+ InputEventAction action;
+ };
+
+ bool is_pressed() const;
+ bool is_action(const String& p_action) const;
+ bool is_echo() const;
+ void set_as_action(const String& p_action);
+
+ bool operator==(const InputEvent &p_event) const;
+ operator String() const;
+ InputEvent() { zeromem(this,sizeof(InputEvent)); }
+};
+
+
+#endif
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
new file mode 100644
index 0000000000..a4201c34ea
--- /dev/null
+++ b/core/os/keyboard.cpp
@@ -0,0 +1,355 @@
+/*************************************************************************/
+/* keyboard.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 "keyboard.h"
+
+
+struct _KeyCodeText {
+ int code;
+ const char *text;
+};
+
+static const _KeyCodeText _keycodes[]={
+
+ {KEY_ESCAPE ,"Escape"},
+ {KEY_TAB ,"Tab"},
+ {KEY_BACKTAB ,"BackTab"},
+ {KEY_BACKSPACE ,"BackSpace"},
+ {KEY_RETURN ,"Return"},
+ {KEY_ENTER ,"Enter"},
+ {KEY_INSERT ,"Insert"},
+ {KEY_DELETE ,"Delete"},
+ {KEY_PAUSE ,"Pause"},
+ {KEY_PRINT ,"Print"},
+ {KEY_SYSREQ ,"SysReq"},
+ {KEY_CLEAR ,"Clear"},
+ {KEY_HOME ,"Home"},
+ {KEY_END ,"End"},
+ {KEY_LEFT ,"Left"},
+ {KEY_UP ,"Up"},
+ {KEY_RIGHT ,"Right"},
+ {KEY_DOWN ,"Down"},
+ {KEY_PAGEUP ,"PageUp"},
+ {KEY_PAGEDOWN ,"PageDown"},
+ {KEY_SHIFT ,"Shift"},
+ {KEY_CONTROL ,"Control"},
+ {KEY_META ,"Meta"},
+ {KEY_ALT ,"Alt"},
+ {KEY_CAPSLOCK ,"CapsLock"},
+ {KEY_NUMLOCK ,"NumLock"},
+ {KEY_SCROLLLOCK ,"ScrollLock"},
+ {KEY_F1 ,"F1"},
+ {KEY_F2 ,"F2"},
+ {KEY_F3 ,"F3"},
+ {KEY_F4 ,"F4"},
+ {KEY_F5 ,"F5"},
+ {KEY_F6 ,"F6"},
+ {KEY_F7 ,"F7"},
+ {KEY_F8 ,"F8"},
+ {KEY_F9 ,"F9"},
+ {KEY_F10 ,"F10"},
+ {KEY_F11 ,"F11"},
+ {KEY_F12 ,"F12"},
+ {KEY_F13 ,"F13"},
+ {KEY_F14 ,"F14"},
+ {KEY_F15 ,"F15"},
+ {KEY_F16 ,"F16"},
+ {KEY_KP_ENTER ,"Kp Enter"},
+ {KEY_KP_MULTIPLY ,"Kp Multiply"},
+ {KEY_KP_DIVIDE ,"Kp Divide"},
+ {KEY_KP_SUBSTRACT ,"Kp Substract"},
+ {KEY_KP_PERIOD ,"Kp Period"},
+ {KEY_KP_ADD ,"Kp Add"},
+ {KEY_KP_0 ,"Kp 0"},
+ {KEY_KP_1 ,"Kp 1"},
+ {KEY_KP_2 ,"Kp 2"},
+ {KEY_KP_3 ,"Kp 3"},
+ {KEY_KP_4 ,"Kp 4"},
+ {KEY_KP_5 ,"Kp 5"},
+ {KEY_KP_6 ,"Kp 6"},
+ {KEY_KP_7 ,"Kp 7"},
+ {KEY_KP_8 ,"Kp 8"},
+ {KEY_KP_9 ,"Kp 9"},
+ {KEY_SUPER_L ,"Super L"},
+ {KEY_SUPER_R ,"Super R"},
+ {KEY_MENU ,"Menu"},
+ {KEY_HYPER_L ,"Hyper L"},
+ {KEY_HYPER_R ,"Hyper R"},
+ {KEY_HELP ,"Help"},
+ {KEY_DIRECTION_L ,"Direction L"},
+ {KEY_DIRECTION_R ,"Direction R"},
+ {KEY_BACK ,"Back"},
+ {KEY_FORWARD ,"Forward"},
+ {KEY_STOP ,"Stop"},
+ {KEY_REFRESH ,"Refresh"},
+ {KEY_VOLUMEDOWN ,"VolumeDown"},
+ {KEY_VOLUMEMUTE ,"VolumeMute"},
+ {KEY_VOLUMEUP ,"VolumeUp"},
+ {KEY_BASSBOOST ,"BassBoost"},
+ {KEY_BASSUP ,"BassUp"},
+ {KEY_BASSDOWN ,"BassDown"},
+ {KEY_TREBLEUP ,"TrebleUp"},
+ {KEY_TREBLEDOWN ,"TrebleDown"},
+ {KEY_MEDIAPLAY ,"MediaPlay"},
+ {KEY_MEDIASTOP ,"MediaStop"},
+ {KEY_MEDIAPREVIOUS ,"MediaPrevious"},
+ {KEY_MEDIANEXT ,"MediaNext"},
+ {KEY_MEDIARECORD ,"MediaRecord"},
+ {KEY_HOMEPAGE ,"HomePage"},
+ {KEY_FAVORITES ,"Favorites"},
+ {KEY_SEARCH ,"Search"},
+ {KEY_STANDBY ,"StandBy"},
+ {KEY_LAUNCHMAIL ,"LaunchMail"},
+ {KEY_LAUNCHMEDIA ,"LaunchMedia"},
+ {KEY_LAUNCH0 ,"Launch0"},
+ {KEY_LAUNCH1 ,"Launch1"},
+ {KEY_LAUNCH2 ,"Launch2"},
+ {KEY_LAUNCH3 ,"Launch3"},
+ {KEY_LAUNCH4 ,"Launch4"},
+ {KEY_LAUNCH5 ,"Launch5"},
+ {KEY_LAUNCH6 ,"Launch6"},
+ {KEY_LAUNCH7 ,"Launch7"},
+ {KEY_LAUNCH8 ,"Launch8"},
+ {KEY_LAUNCH9 ,"Launch9"},
+ {KEY_LAUNCHA ,"LaunchA"},
+ {KEY_LAUNCHB ,"LaunchB"},
+ {KEY_LAUNCHC ,"LaunchC"},
+ {KEY_LAUNCHD ,"LaunchD"},
+ {KEY_LAUNCHE ,"LaunchE"},
+ {KEY_LAUNCHF ,"LaunchF"},
+
+ {KEY_UNKNOWN ,"Unknown"},
+
+ {KEY_SPACE ,"Space"},
+ {KEY_EXCLAM ,"Exclam"},
+ {KEY_QUOTEDBL ,"QuoteDbl"},
+ {KEY_NUMBERSIGN ,"NumberSign"},
+ {KEY_DOLLAR ,"Dollar"},
+ {KEY_PERCENT ,"Percent"},
+ {KEY_AMPERSAND ,"Ampersand"},
+ {KEY_APOSTROPHE ,"Apostrophe"},
+ {KEY_PARENLEFT ,"ParenLeft"},
+ {KEY_PARENRIGHT ,"ParenRight"},
+ {KEY_ASTERISK ,"Asterisk"},
+ {KEY_PLUS ,"Plus"},
+ {KEY_COMMA ,"Comma"},
+ {KEY_MINUS ,"Minus"},
+ {KEY_PERIOD ,"Period"},
+ {KEY_SLASH ,"Slash"},
+ {KEY_0 ,"0"},
+ {KEY_1 ,"1"},
+ {KEY_2 ,"2"},
+ {KEY_3 ,"3"},
+ {KEY_4 ,"4"},
+ {KEY_5 ,"5"},
+ {KEY_6 ,"6"},
+ {KEY_7 ,"7"},
+ {KEY_8 ,"8"},
+ {KEY_9 ,"9"},
+ {KEY_COLON ,"Colon"},
+ {KEY_SEMICOLON ,"Semicolon"},
+ {KEY_LESS ,"Less"},
+ {KEY_EQUAL ,"Equal"},
+ {KEY_GREATER ,"Greater"},
+ {KEY_QUESTION ,"Question"},
+ {KEY_AT ,"At"},
+ {KEY_A ,"A"},
+ {KEY_B ,"B"},
+ {KEY_C ,"C"},
+ {KEY_D ,"D"},
+ {KEY_E ,"E"},
+ {KEY_F ,"F"},
+ {KEY_G ,"G"},
+ {KEY_H ,"H"},
+ {KEY_I ,"I"},
+ {KEY_J ,"J"},
+ {KEY_K ,"K"},
+ {KEY_L ,"L"},
+ {KEY_M ,"M"},
+ {KEY_N ,"N"},
+ {KEY_O ,"O"},
+ {KEY_P ,"P"},
+ {KEY_Q ,"Q"},
+ {KEY_R ,"R"},
+ {KEY_S ,"S"},
+ {KEY_T ,"T"},
+ {KEY_U ,"U"},
+ {KEY_V ,"V"},
+ {KEY_W ,"W"},
+ {KEY_X ,"X"},
+ {KEY_Y ,"Y"},
+ {KEY_Z ,"Z"},
+ {KEY_BRACKETLEFT ,"BracketLeft"},
+ {KEY_BACKSLASH ,"BackSlash"},
+ {KEY_BRACKETRIGHT ,"BracketRight"},
+ {KEY_ASCIICIRCUM ,"AsciiCircum"},
+ {KEY_UNDERSCORE ,"UnderScore"},
+ {KEY_QUOTELEFT ,"QuoteLeft"},
+ {KEY_BRACELEFT ,"BraceLeft"},
+ {KEY_BAR ,"Bar"},
+ {KEY_BRACERIGHT ,"BraceRight"},
+ {KEY_ASCIITILDE ,"AsciiTilde"},
+ {KEY_NOBREAKSPACE ,"NoBreakSpace"},
+ {KEY_EXCLAMDOWN ,"ExclamDown"},
+ {KEY_CENT ,"Cent"},
+ {KEY_STERLING ,"Sterling"},
+ {KEY_CURRENCY ,"Currency"},
+ {KEY_YEN ,"Yen"},
+ {KEY_BROKENBAR ,"BrokenBar"},
+ {KEY_SECTION ,"Section"},
+ {KEY_DIAERESIS ,"Diaeresis"},
+ {KEY_COPYRIGHT ,"Copyright"},
+ {KEY_ORDFEMININE ,"Ordfeminine"},
+ {KEY_GUILLEMOTLEFT ,"GuillemotLeft"},
+ {KEY_NOTSIGN ,"NotSign"},
+ {KEY_HYPHEN ,"Hyphen"},
+ {KEY_REGISTERED ,"Registered"},
+ {KEY_MACRON ,"Macron"},
+ {KEY_DEGREE ,"Degree"},
+ {KEY_PLUSMINUS ,"PlusMinus"},
+ {KEY_TWOSUPERIOR ,"TwoSuperior"},
+ {KEY_THREESUPERIOR ,"ThreeSuperior"},
+ {KEY_ACUTE ,"Acute"},
+ {KEY_MU ,"Mu"},
+ {KEY_PARAGRAPH ,"Paragraph"},
+ {KEY_PERIODCENTERED ,"PeriodCentered"},
+ {KEY_CEDILLA ,"Cedilla"},
+ {KEY_ONESUPERIOR ,"OneSuperior"},
+ {KEY_MASCULINE ,"Masculine"},
+ {KEY_GUILLEMOTRIGHT ,"GuillemotRight"},
+ {KEY_ONEQUARTER ,"OneQuarter"},
+ {KEY_ONEHALF ,"OneHalf"},
+ {KEY_THREEQUARTERS ,"ThreeQuarters"},
+ {KEY_QUESTIONDOWN ,"QuestionDown"},
+ {KEY_AGRAVE ,"Agrave"},
+ {KEY_AACUTE ,"Aacute"},
+ {KEY_ACIRCUMFLEX ,"AcircumFlex"},
+ {KEY_ATILDE ,"Atilde"},
+ {KEY_ADIAERESIS ,"Adiaeresis"},
+ {KEY_ARING ,"Aring"},
+ {KEY_AE ,"Ae"},
+ {KEY_CCEDILLA ,"Ccedilla"},
+ {KEY_EGRAVE ,"Egrave"},
+ {KEY_EACUTE ,"Eacute"},
+ {KEY_ECIRCUMFLEX ,"Ecircumflex"},
+ {KEY_EDIAERESIS ,"Ediaeresis"},
+ {KEY_IGRAVE ,"Igrave"},
+ {KEY_IACUTE ,"Iacute"},
+ {KEY_ICIRCUMFLEX ,"Icircumflex"},
+ {KEY_IDIAERESIS ,"Idiaeresis"},
+ {KEY_ETH ,"Eth"},
+ {KEY_NTILDE ,"Ntilde"},
+ {KEY_OGRAVE ,"Ograve"},
+ {KEY_OACUTE ,"Oacute"},
+ {KEY_OCIRCUMFLEX ,"Ocircumflex"},
+ {KEY_OTILDE ,"Otilde"},
+ {KEY_ODIAERESIS ,"Odiaeresis"},
+ {KEY_MULTIPLY ,"Multiply"},
+ {KEY_OOBLIQUE ,"Ooblique"},
+ {KEY_UGRAVE ,"Ugrave"},
+ {KEY_UACUTE ,"Uacute"},
+ {KEY_UCIRCUMFLEX ,"Ucircumflex"},
+ {KEY_UDIAERESIS ,"Udiaeresis"},
+ {KEY_YACUTE ,"Yacute"},
+ {KEY_THORN ,"Thorn"},
+ {KEY_SSHARP ,"Ssharp"},
+
+ {KEY_DIVISION ,"Division"},
+ {KEY_YDIAERESIS ,"Ydiaeresis"},
+ {0 ,0}
+};
+
+bool keycode_has_unicode(uint32_t p_keycode) {
+
+
+ switch(p_keycode) {
+
+ case KEY_ESCAPE: case KEY_TAB: case KEY_BACKTAB: case KEY_BACKSPACE: case KEY_RETURN: case KEY_ENTER: case KEY_INSERT: case KEY_DELETE: case KEY_PAUSE:
+ case KEY_PRINT: case KEY_SYSREQ: case KEY_CLEAR: case KEY_HOME: case KEY_END: case KEY_LEFT: case KEY_UP: case KEY_RIGHT: case KEY_DOWN: case KEY_PAGEUP:
+ case KEY_PAGEDOWN: case KEY_SHIFT: case KEY_CONTROL: case KEY_META: case KEY_ALT: case KEY_CAPSLOCK: case KEY_NUMLOCK: case KEY_SCROLLLOCK: case KEY_F1:
+ case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: case KEY_F13: case KEY_F14:
+ case KEY_F15: case KEY_F16: case KEY_KP_ENTER: case KEY_SUPER_L: case KEY_SUPER_R: case KEY_MENU: case KEY_HYPER_L: case KEY_HYPER_R: case KEY_HELP:
+ case KEY_DIRECTION_L: case KEY_DIRECTION_R: case KEY_BACK: case KEY_FORWARD: case KEY_STOP: case KEY_REFRESH: case KEY_VOLUMEDOWN: case KEY_VOLUMEMUTE:
+ case KEY_VOLUMEUP: case KEY_BASSBOOST: case KEY_BASSUP: case KEY_BASSDOWN: case KEY_TREBLEUP: case KEY_TREBLEDOWN: case KEY_MEDIAPLAY: case KEY_MEDIASTOP:
+ case KEY_MEDIAPREVIOUS: case KEY_MEDIANEXT: case KEY_MEDIARECORD: case KEY_HOMEPAGE: case KEY_FAVORITES: case KEY_SEARCH: case KEY_STANDBY:
+ case KEY_OPENURL: case KEY_LAUNCHMAIL: case KEY_LAUNCHMEDIA: case KEY_LAUNCH0: case KEY_LAUNCH1: case KEY_LAUNCH2: case KEY_LAUNCH3: case KEY_LAUNCH4:
+ case KEY_LAUNCH5: case KEY_LAUNCH6: case KEY_LAUNCH7: case KEY_LAUNCH8: case KEY_LAUNCH9: case KEY_LAUNCHA: case KEY_LAUNCHB: case KEY_LAUNCHC: case KEY_LAUNCHD:
+ case KEY_LAUNCHE: case KEY_LAUNCHF: return false;
+ }
+
+ return true;
+}
+
+String keycode_get_string(uint32_t p_code) {
+
+ String codestr;
+ if (p_code&KEY_MASK_SHIFT)
+ codestr+="Shift+";
+ if (p_code&KEY_MASK_ALT)
+ codestr+="Alt+";
+ if (p_code&KEY_MASK_CTRL)
+ codestr+="Ctrl+";
+ if (p_code&KEY_MASK_META)
+ codestr+="Meta+";
+
+ p_code&=KEY_CODE_MASK;
+
+ const _KeyCodeText *kct =&_keycodes[0];
+
+ while(kct->text) {
+
+ if (kct->code==(int)p_code) {
+
+ codestr+=kct->text;
+ return codestr;
+ }
+ kct++;
+ }
+
+ codestr+=String::chr(p_code);
+
+ return codestr;
+
+}
+
+int find_keycode(const String& p_code) {
+
+ const _KeyCodeText *kct =&_keycodes[0];
+
+ while(kct->text) {
+
+ if (p_code.nocasecmp_to(kct->text)==0) {
+ return kct->code;
+
+ }
+ kct++;
+ }
+
+ return 0;
+
+}
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
new file mode 100644
index 0000000000..18b56b5830
--- /dev/null
+++ b/core/os/keyboard.h
@@ -0,0 +1,332 @@
+/*************************************************************************/
+/* keyboard.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 KEYBOARD_H
+#define KEYBOARD_H
+
+#include "ustring.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+/**
+@author Juan Linietsky <reduzio@gmail.com>
+*/
+
+/*
+ Special Key:
+
+ The strategy here is similar to the one used by toolkits,
+ which consists in leaving the 24 bits unicode range for printable
+ characters, and use the upper 8 bits for special keys and
+ modifiers. This way everything (char/keycode) can fit nicely in one 32 bits unsigned integer.
+*/
+enum {
+ SPKEY = (1<<24)
+};
+
+enum KeyList {
+/* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */
+ KEY_ESCAPE=SPKEY | 0x01,
+ KEY_TAB=SPKEY | 0x02,
+ KEY_BACKTAB=SPKEY | 0x03,
+ KEY_BACKSPACE=SPKEY | 0x04,
+ KEY_RETURN=SPKEY | 0x05,
+ KEY_ENTER=SPKEY | 0x06,
+ KEY_INSERT=SPKEY | 0x07,
+ KEY_DELETE=SPKEY | 0x08,
+ KEY_PAUSE=SPKEY | 0x09,
+ KEY_PRINT=SPKEY | 0x0A,
+ KEY_SYSREQ=SPKEY | 0x0B,
+ KEY_CLEAR=SPKEY | 0x0C,
+ KEY_HOME=SPKEY | 0x0D,
+ KEY_END=SPKEY | 0x0E,
+ KEY_LEFT=SPKEY | 0x0F,
+ KEY_UP=SPKEY | 0x10,
+ KEY_RIGHT=SPKEY | 0x11,
+ KEY_DOWN=SPKEY | 0x12,
+ KEY_PAGEUP=SPKEY | 0x13,
+ KEY_PAGEDOWN=SPKEY | 0x14,
+ KEY_SHIFT=SPKEY | 0x15,
+ KEY_CONTROL=SPKEY | 0x16,
+ KEY_META=SPKEY | 0x17,
+ KEY_ALT=SPKEY | 0x18,
+ KEY_CAPSLOCK=SPKEY | 0x19,
+ KEY_NUMLOCK=SPKEY | 0x1A,
+ KEY_SCROLLLOCK=SPKEY | 0x1B,
+ KEY_F1=SPKEY | 0x1C,
+ KEY_F2=SPKEY | 0x1D,
+ KEY_F3=SPKEY | 0x1E,
+ KEY_F4=SPKEY | 0x1F,
+ KEY_F5=SPKEY | 0x20,
+ KEY_F6=SPKEY | 0x21,
+ KEY_F7=SPKEY | 0x22,
+ KEY_F8=SPKEY | 0x23,
+ KEY_F9=SPKEY | 0x24,
+ KEY_F10=SPKEY | 0x25,
+ KEY_F11=SPKEY | 0x26,
+ KEY_F12=SPKEY | 0x27,
+ KEY_F13=SPKEY | 0x28,
+ KEY_F14=SPKEY | 0x29,
+ KEY_F15=SPKEY | 0x2A,
+ KEY_F16=SPKEY | 0x2B,
+ KEY_KP_ENTER=SPKEY | 0x80,
+ KEY_KP_MULTIPLY=SPKEY | 0x81,
+ KEY_KP_DIVIDE=SPKEY | 0x82,
+ KEY_KP_SUBSTRACT=SPKEY | 0x83,
+ KEY_KP_PERIOD=SPKEY | 0x84,
+ KEY_KP_ADD=SPKEY | 0x85,
+ KEY_KP_0=SPKEY | 0x86,
+ KEY_KP_1=SPKEY | 0x87,
+ KEY_KP_2=SPKEY | 0x88,
+ KEY_KP_3=SPKEY | 0x89,
+ KEY_KP_4=SPKEY | 0x8A,
+ KEY_KP_5=SPKEY | 0x8B,
+ KEY_KP_6=SPKEY | 0x8C,
+ KEY_KP_7=SPKEY | 0x8D,
+ KEY_KP_8=SPKEY | 0x8E,
+ KEY_KP_9=SPKEY | 0x8F,
+ KEY_SUPER_L=SPKEY | 0x2C,
+ KEY_SUPER_R=SPKEY | 0x2D,
+ KEY_MENU=SPKEY | 0x2E,
+ KEY_HYPER_L=SPKEY | 0x2F,
+ KEY_HYPER_R=SPKEY | 0x30,
+ KEY_HELP=SPKEY | 0x31,
+ KEY_DIRECTION_L=SPKEY | 0x32,
+ KEY_DIRECTION_R=SPKEY | 0x33,
+ KEY_BACK=SPKEY | 0x40,
+ KEY_FORWARD=SPKEY | 0x41,
+ KEY_STOP=SPKEY | 0x42,
+ KEY_REFRESH=SPKEY | 0x43,
+ KEY_VOLUMEDOWN=SPKEY | 0x44,
+ KEY_VOLUMEMUTE=SPKEY | 0x45,
+ KEY_VOLUMEUP=SPKEY | 0x46,
+ KEY_BASSBOOST=SPKEY | 0x47,
+ KEY_BASSUP=SPKEY | 0x48,
+ KEY_BASSDOWN=SPKEY | 0x49,
+ KEY_TREBLEUP=SPKEY | 0x4A,
+ KEY_TREBLEDOWN=SPKEY | 0x4B,
+ KEY_MEDIAPLAY=SPKEY | 0x4C,
+ KEY_MEDIASTOP=SPKEY | 0x4D,
+ KEY_MEDIAPREVIOUS=SPKEY | 0x4E,
+ KEY_MEDIANEXT=SPKEY | 0x4F,
+ KEY_MEDIARECORD= SPKEY | 0x50,
+ KEY_HOMEPAGE=SPKEY | 0x51,
+ KEY_FAVORITES=SPKEY | 0x52,
+ KEY_SEARCH=SPKEY | 0x53,
+ KEY_STANDBY=SPKEY | 0x54,
+ KEY_OPENURL=SPKEY | 0x55,
+ KEY_LAUNCHMAIL=SPKEY | 0x56,
+ KEY_LAUNCHMEDIA=SPKEY | 0x57,
+ KEY_LAUNCH0=SPKEY | 0x58,
+ KEY_LAUNCH1=SPKEY | 0x59,
+ KEY_LAUNCH2=SPKEY | 0x5A,
+ KEY_LAUNCH3=SPKEY | 0x5B,
+ KEY_LAUNCH4=SPKEY | 0x5C,
+ KEY_LAUNCH5=SPKEY | 0x5D,
+ KEY_LAUNCH6=SPKEY | 0x5E,
+ KEY_LAUNCH7=SPKEY | 0x5F,
+ KEY_LAUNCH8=SPKEY | 0x60,
+ KEY_LAUNCH9=SPKEY | 0x61,
+ KEY_LAUNCHA=SPKEY | 0x62,
+ KEY_LAUNCHB=SPKEY | 0x63,
+ KEY_LAUNCHC=SPKEY | 0x64,
+ KEY_LAUNCHD=SPKEY | 0x65,
+ KEY_LAUNCHE=SPKEY | 0x66,
+ KEY_LAUNCHF=SPKEY | 0x67,
+
+ KEY_UNKNOWN=SPKEY | 0xFFFFFF,
+
+/* PRINTABLE LATIN 1 CODES */
+
+ KEY_SPACE=0x0020,
+ KEY_EXCLAM=0x0021,
+ KEY_QUOTEDBL=0x0022,
+ KEY_NUMBERSIGN=0x0023,
+ KEY_DOLLAR=0x0024,
+ KEY_PERCENT=0x0025,
+ KEY_AMPERSAND=0x0026,
+ KEY_APOSTROPHE=0x0027,
+ KEY_PARENLEFT=0x0028,
+ KEY_PARENRIGHT=0x0029,
+ KEY_ASTERISK=0x002A,
+ KEY_PLUS=0x002B,
+ KEY_COMMA=0x002C,
+ KEY_MINUS=0x002D,
+ KEY_PERIOD=0x002E,
+ KEY_SLASH=0x002F,
+ KEY_0=0x0030,
+ KEY_1=0x0031,
+ KEY_2=0x0032,
+ KEY_3=0x0033,
+ KEY_4=0x0034,
+ KEY_5=0x0035,
+ KEY_6=0x0036,
+ KEY_7=0x0037,
+ KEY_8=0x0038,
+ KEY_9=0x0039,
+ KEY_COLON=0x003A,
+ KEY_SEMICOLON=0x003B,
+ KEY_LESS=0x003C,
+ KEY_EQUAL=0x003D,
+ KEY_GREATER=0x003E,
+ KEY_QUESTION=0x003F,
+ KEY_AT=0x0040,
+ KEY_A=0x0041,
+ KEY_B=0x0042,
+ KEY_C=0x0043,
+ KEY_D=0x0044,
+ KEY_E=0x0045,
+ KEY_F=0x0046,
+ KEY_G=0x0047,
+ KEY_H=0x0048,
+ KEY_I=0x0049,
+ KEY_J=0x004A,
+ KEY_K=0x004B,
+ KEY_L=0x004C,
+ KEY_M=0x004D,
+ KEY_N=0x004E,
+ KEY_O=0x004F,
+ KEY_P=0x0050,
+ KEY_Q=0x0051,
+ KEY_R=0x0052,
+ KEY_S=0x0053,
+ KEY_T=0x0054,
+ KEY_U=0x0055,
+ KEY_V=0x0056,
+ KEY_W=0x0057,
+ KEY_X=0x0058,
+ KEY_Y=0x0059,
+ KEY_Z=0x005A,
+ KEY_BRACKETLEFT=0x005B,
+ KEY_BACKSLASH=0x005C,
+ KEY_BRACKETRIGHT=0x005D,
+ KEY_ASCIICIRCUM=0x005E,
+ KEY_UNDERSCORE=0x005F,
+ KEY_QUOTELEFT=0x0060,
+ KEY_BRACELEFT=0x007B,
+ KEY_BAR=0x007C,
+ KEY_BRACERIGHT=0x007D,
+ KEY_ASCIITILDE=0x007E,
+ KEY_NOBREAKSPACE=0x00A0,
+ KEY_EXCLAMDOWN=0x00A1,
+ KEY_CENT=0x00A2,
+ KEY_STERLING=0x00A3,
+ KEY_CURRENCY=0x00A4,
+ KEY_YEN=0x00A5,
+ KEY_BROKENBAR=0x00A6,
+ KEY_SECTION=0x00A7,
+ KEY_DIAERESIS=0x00A8,
+ KEY_COPYRIGHT=0x00A9,
+ KEY_ORDFEMININE=0x00AA,
+ KEY_GUILLEMOTLEFT=0x00AB,
+ KEY_NOTSIGN=0x00AC,
+ KEY_HYPHEN=0x00AD,
+ KEY_REGISTERED=0x00AE,
+ KEY_MACRON=0x00AF,
+ KEY_DEGREE=0x00B0,
+ KEY_PLUSMINUS=0x00B1,
+ KEY_TWOSUPERIOR=0x00B2,
+ KEY_THREESUPERIOR=0x00B3,
+ KEY_ACUTE=0x00B4,
+ KEY_MU=0x00B5,
+ KEY_PARAGRAPH=0x00B6,
+ KEY_PERIODCENTERED=0x00B7,
+ KEY_CEDILLA=0x00B8,
+ KEY_ONESUPERIOR=0x00B9,
+ KEY_MASCULINE=0x00BA,
+ KEY_GUILLEMOTRIGHT=0x00BB,
+ KEY_ONEQUARTER=0x00BC,
+ KEY_ONEHALF=0x00BD,
+ KEY_THREEQUARTERS=0x00BE,
+ KEY_QUESTIONDOWN=0x00BF,
+ KEY_AGRAVE=0x00C0,
+ KEY_AACUTE=0x00C1,
+ KEY_ACIRCUMFLEX=0x00C2,
+ KEY_ATILDE=0x00C3,
+ KEY_ADIAERESIS=0x00C4,
+ KEY_ARING=0x00C5,
+ KEY_AE=0x00C6,
+ KEY_CCEDILLA=0x00C7,
+ KEY_EGRAVE=0x00C8,
+ KEY_EACUTE=0x00C9,
+ KEY_ECIRCUMFLEX=0x00CA,
+ KEY_EDIAERESIS=0x00CB,
+ KEY_IGRAVE=0x00CC,
+ KEY_IACUTE=0x00CD,
+ KEY_ICIRCUMFLEX=0x00CE,
+ KEY_IDIAERESIS=0x00CF,
+ KEY_ETH=0x00D0,
+ KEY_NTILDE=0x00D1,
+ KEY_OGRAVE=0x00D2,
+ KEY_OACUTE=0x00D3,
+ KEY_OCIRCUMFLEX=0x00D4,
+ KEY_OTILDE=0x00D5,
+ KEY_ODIAERESIS=0x00D6,
+ KEY_MULTIPLY=0x00D7,
+ KEY_OOBLIQUE=0x00D8,
+ KEY_UGRAVE=0x00D9,
+ KEY_UACUTE=0x00DA,
+ KEY_UCIRCUMFLEX=0x00DB,
+ KEY_UDIAERESIS=0x00DC,
+ KEY_YACUTE=0x00DD,
+ KEY_THORN=0x00DE,
+ KEY_SSHARP=0x00DF,
+
+ KEY_DIVISION=0x00F7,
+ KEY_YDIAERESIS=0x00FF,
+
+
+};
+
+
+enum KeyModifierMask {
+
+ KEY_CODE_MASK=((1<<25)-1), ///< Apply this mask to any keycode to remove modifiers.
+ KEY_MODIFIER_MASK=(0xFF<<24), ///< Apply this mask to isolate modifiers.
+ KEY_MASK_SHIFT = (1<<25),
+ KEY_MASK_ALT = (1<<26),
+ KEY_MASK_META = (1<<27),
+ KEY_MASK_CTRL = (1<<28),
+#ifdef APPLE_STYLE_KEYS
+ KEY_MASK_CMD = KEY_MASK_META,
+#else
+ KEY_MASK_CMD = KEY_MASK_CTRL,
+#endif
+
+ KEY_MASK_KPAD = (1<<29),
+ KEY_MASK_GROUP_SWITCH = (1<<30)
+ // bit 31 can't be used because variant uses regular 32 bits int as datatype
+
+};
+
+String keycode_get_string(uint32_t p_code);
+bool keycode_has_unicode(uint32_t p_unicode);
+int find_keycode(const String& p_code);
+
+#endif
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
new file mode 100644
index 0000000000..a8e02526b9
--- /dev/null
+++ b/core/os/main_loop.cpp
@@ -0,0 +1,104 @@
+/*************************************************************************/
+/* main_loop.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_loop.h"
+#include "script_language.h"
+
+void MainLoop::_bind_methods() {
+
+ ObjectTypeDB::bind_method("input_event",&MainLoop::input_event);
+
+ BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
+ BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
+ BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
+
+
+};
+
+void MainLoop::set_init_script(const Ref<Script>& p_init_script) {
+
+ init_script=p_init_script;
+}
+
+MainLoop::MainLoop() {
+}
+
+
+MainLoop::~MainLoop()
+{
+}
+
+
+
+void MainLoop::input_text( const String& p_text ) {
+
+
+}
+
+void MainLoop::input_event( const InputEvent& p_event ) {
+
+ if (get_script_instance())
+ get_script_instance()->call("input_event",p_event);
+
+}
+
+void MainLoop::init() {
+
+ if (init_script.is_valid())
+ set_script(init_script.get_ref_ptr());
+
+ if (get_script_instance())
+ get_script_instance()->call("init");
+
+}
+bool MainLoop::iteration(float p_time) {
+
+ if (get_script_instance())
+ return get_script_instance()->call("iteration",p_time);
+
+ return false;
+
+}
+bool MainLoop::idle(float p_time) {
+
+ if (get_script_instance())
+ return get_script_instance()->call("idle",p_time);
+
+ return false;
+}
+void MainLoop::finish() {
+
+ if (get_script_instance()) {
+ get_script_instance()->call("finish");
+ set_script(RefPtr()); //clear script
+ }
+
+
+}
+
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
new file mode 100644
index 0000000000..b84d2841e1
--- /dev/null
+++ b/core/os/main_loop.h
@@ -0,0 +1,72 @@
+/*************************************************************************/
+/* main_loop.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 MAIN_LOOP_H
+#define MAIN_LOOP_H
+
+#include "os/input_event.h"
+#include "reference.h"
+#include "script_language.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class MainLoop : public Object {
+
+ OBJ_TYPE( MainLoop, Object );
+ OBJ_CATEGORY("Main Loop");
+
+ Ref<Script> init_script;
+protected:
+ static void _bind_methods();
+
+public:
+
+ enum {
+ NOTIFICATION_WM_FOCUS_IN = 5,
+ NOTIFICATION_WM_FOCUS_OUT = 6,
+ NOTIFICATION_WM_QUIT_REQUEST = 7,
+ NOTIFICATION_WM_UNFOCUS_REQUEST = 8
+ };
+
+ virtual void input_event( const InputEvent& p_event );
+ virtual void input_text( const String& p_text );
+
+ virtual void init();
+ virtual bool iteration(float p_time);
+ virtual bool idle(float p_time);
+ virtual void finish();
+
+ void set_init_script(const Ref<Script>& p_init_script);
+
+ MainLoop();
+ virtual ~MainLoop();
+
+
+};
+
+#endif
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
new file mode 100644
index 0000000000..ca5bacf9cd
--- /dev/null
+++ b/core/os/memory.cpp
@@ -0,0 +1,134 @@
+/*************************************************************************/
+/* memory.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 "memory.h"
+#include "error_macros.h"
+#include "copymem.h"
+#include <stdio.h>
+void * operator new(size_t p_size,const char *p_description) {
+
+ return Memory::alloc_static( p_size, p_description );
+}
+
+void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)) {
+
+ return p_allocfunc(p_size);
+}
+
+#include <stdio.h>
+
+void * Memory::alloc_static(size_t p_bytes,const char *p_alloc_from) {
+
+ ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
+ return MemoryPoolStatic::get_singleton()->alloc(p_bytes,p_alloc_from);
+}
+void * Memory::realloc_static(void *p_memory,size_t p_bytes) {
+
+ ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
+ return MemoryPoolStatic::get_singleton()->realloc(p_memory,p_bytes);
+}
+
+void Memory::free_static(void *p_ptr) {
+
+ ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
+ MemoryPoolStatic::get_singleton()->free(p_ptr);
+}
+
+
+size_t Memory::get_static_mem_available() {
+
+ ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
+ return MemoryPoolStatic::get_singleton()->get_available_mem();
+
+}
+
+size_t Memory::get_static_mem_max_usage() {
+
+ ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
+ return MemoryPoolStatic::get_singleton()->get_max_usage();
+}
+
+size_t Memory::get_static_mem_usage() {
+
+ ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
+ return MemoryPoolStatic::get_singleton()->get_total_usage();
+
+}
+
+void Memory::dump_static_mem_to_file(const char* p_file) {
+
+ MemoryPoolStatic::get_singleton()->dump_mem_to_file(p_file);
+}
+
+MID Memory::alloc_dynamic(size_t p_bytes, const char *p_descr) {
+
+ MemoryPoolDynamic::ID id = MemoryPoolDynamic::get_singleton()->alloc(p_bytes,p_descr);
+
+ return MID(id);
+}
+Error Memory::realloc_dynamic(MID p_mid,size_t p_bytes) {
+
+ MemoryPoolDynamic::ID id = p_mid.data?p_mid.data->id:MemoryPoolDynamic::INVALID_ID;
+
+ if (id==MemoryPoolDynamic::INVALID_ID)
+ return ERR_INVALID_PARAMETER;
+
+ return MemoryPoolDynamic::get_singleton()->realloc(p_mid, p_bytes);
+
+}
+
+size_t Memory::get_dynamic_mem_available() {
+
+ return MemoryPoolDynamic::get_singleton()->get_available_mem();
+}
+
+size_t Memory::get_dynamic_mem_usage() {
+
+ return MemoryPoolDynamic::get_singleton()->get_total_usage();
+}
+
+void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
+
+ void *failptr=0;
+ ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
+
+ return p_pointer;
+}
+
+
+
+_GlobalNil::_GlobalNil() {
+
+ color=1;
+ left=this;
+ right=this;
+ parent=this;
+}
+
+_GlobalNil _GlobalNilClass::_nil;
+
diff --git a/core/os/memory.h b/core/os/memory.h
new file mode 100644
index 0000000000..6fc3d8f3eb
--- /dev/null
+++ b/core/os/memory.h
@@ -0,0 +1,362 @@
+/*************************************************************************/
+/* memory.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 MEMORY_H
+#define MEMORY_H
+
+#include <stddef.h>
+#include "safe_refcount.h"
+#include "os/memory_pool_dynamic.h"
+#include "os/memory_pool_static.h"
+
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class MID {
+
+ struct Data {
+
+ SafeRefCount refcount;
+ MemoryPoolDynamic::ID id;
+ };
+
+ mutable Data *data;
+
+ void unref() {
+
+ if (!data)
+ return;
+ if (data->refcount.unref()) {
+
+ if (data->id!=MemoryPoolDynamic::INVALID_ID)
+ MemoryPoolDynamic::get_singleton()->free(data->id);
+ MemoryPoolStatic::get_singleton()->free(data);
+ }
+
+ data=NULL;
+ }
+
+ void ref(Data *p_data) {
+
+ if (data==p_data)
+ return;
+ unref();
+
+ if (p_data && p_data->refcount.ref())
+ data=p_data;
+ }
+
+friend class MID_Lock;
+
+ inline void lock() {
+
+ if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
+ MemoryPoolDynamic::get_singleton()->lock(data->id);
+ }
+ inline void unlock() {
+
+ if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
+ MemoryPoolDynamic::get_singleton()->unlock(data->id);
+
+ }
+
+ inline void * get() {
+
+ if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
+ return MemoryPoolDynamic::get_singleton()->get(data->id);
+
+ return NULL;
+ }
+
+ Error _resize(size_t p_size) {
+
+ if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
+ return OK;
+ if (p_size && !data) {
+ // create data because we'll need it
+ data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
+ ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
+ data->refcount.init();
+ data->id=MemoryPoolDynamic::INVALID_ID;
+ }
+
+ if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
+
+ MemoryPoolDynamic::get_singleton()->free(data->id);
+ data->id=MemoryPoolDynamic::INVALID_ID;
+ }
+
+ if (p_size>0) {
+
+ if (data->id==MemoryPoolDynamic::INVALID_ID) {
+
+ data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
+ ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
+
+ } else {
+
+ MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
+ ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
+
+ }
+ }
+
+ return OK;
+ }
+friend class Memory;
+
+ MID(MemoryPoolDynamic::ID p_id) {
+
+ data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
+ data->refcount.init();
+ data->id=p_id;
+ }
+public:
+
+ bool is_valid() const { return data; }
+ operator bool() const { return data; }
+
+
+ size_t get_size() const { return (data && data->id!=MemoryPoolDynamic::INVALID_ID) ? MemoryPoolDynamic::get_singleton()->get_size(data->id) : 0; }
+ Error resize(size_t p_size) { return _resize(p_size); }
+ inline void operator=(const MID& p_mid) { ref( p_mid.data ); }
+ inline bool is_locked() const { return (data && data->id!=MemoryPoolDynamic::INVALID_ID) ? MemoryPoolDynamic::get_singleton()->is_locked(data->id) : false; }
+ inline MID(const MID& p_mid) { data=NULL; ref( p_mid.data ); }
+ inline MID() { data = NULL; }
+ ~MID() { unref(); }
+};
+
+
+class MID_Lock {
+
+ MID mid;
+
+public:
+
+ void *data() { return mid.get(); }
+
+ void operator=(const MID_Lock& p_lock ) { mid.unlock(); mid = p_lock.mid; mid.lock(); }
+ inline MID_Lock(const MID& p_mid) { mid=p_mid; mid.lock(); }
+ inline MID_Lock(const MID_Lock& p_lock) { mid=p_lock.mid; mid.lock(); }
+ MID_Lock() {}
+ ~MID_Lock() { mid.unlock(); }
+};
+
+
+class Memory{
+
+ Memory();
+public:
+
+ static void * alloc_static(size_t p_bytes,const char *p_descr="");
+ static void * realloc_static(void *p_memory,size_t p_bytes);
+ static void free_static(void *p_ptr);
+ static size_t get_static_mem_available();
+ static size_t get_static_mem_usage();
+ static size_t get_static_mem_max_usage();
+ static void dump_static_mem_to_file(const char* p_file);
+
+ static MID alloc_dynamic(size_t p_bytes, const char *p_descr="");
+ static Error realloc_dynamic(MID p_mid,size_t p_bytes);
+
+ static size_t get_dynamic_mem_available();
+ static size_t get_dynamic_mem_usage();
+
+};
+
+template<class T>
+struct MemAalign {
+ static _FORCE_INLINE_ int get_align() { return DEFAULT_ALIGNMENT; }
+};
+
+class DefaultAllocator {
+public:
+ _FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, ""); }
+ _FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr); }
+
+};
+
+
+void * operator new(size_t p_size,const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
+void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
+
+void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+#define memalloc(m_size) Memory::alloc_static(m_size, __FILE__":"__STR(__LINE__)", memalloc.")
+#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
+#define memfree(m_size) Memory::free_static(m_size)
+
+#else
+
+#define memalloc(m_size) Memory::alloc_static(m_size)
+#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
+#define memfree(m_size) Memory::free_static(m_size)
+
+#endif
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+#define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__":"__STR(__LINE__)", type: DYNAMIC")
+#define dynrealloc(m_mem,m_size) m_mem.resize(m_size)
+
+#else
+
+#define dynalloc(m_size) Memory::alloc_dynamic(m_size)
+#define dynrealloc(m_mem,m_size) m_mem.resize(m_size)
+
+#endif
+
+
+_FORCE_INLINE_ void postinitialize_handler(void *) {}
+
+
+template<class T>
+_FORCE_INLINE_ T *_post_initialize(T *p_obj) {
+
+ postinitialize_handler(p_obj);
+ return p_obj;
+}
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+#define memnew(m_class) _post_initialize(new(__FILE__":"__STR(__LINE__)", memnew type: "__STR(m_class)) m_class)
+#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),__FILE__":"__STR(__LINE__)", type: "__STR(m_class)) m_class)
+
+#else
+
+#define memnew(m_class) _post_initialize(new("") m_class)
+#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class)
+
+#endif
+
+#define memnew_allocator(m_class,m_allocator) _post_initialize(new(m_allocator::alloc) m_class)
+
+
+_FORCE_INLINE_ bool predelete_handler(void *) { return true; }
+
+template<class T>
+void memdelete(T *p_class) {
+
+ if (!predelete_handler(p_class))
+ return; // doesn't want to be deleted
+ p_class->~T();
+ Memory::free_static(p_class);
+}
+
+template<class T,class A>
+void memdelete_allocator(T *p_class) {
+
+ if (!predelete_handler(p_class))
+ return; // doesn't want to be deleted
+ p_class->~T();
+ A::free(p_class);
+}
+
+#define memdelete_notnull(m_v) { if (m_v) memdelete(m_v); }
+#ifdef DEBUG_MEMORY_ENABLED
+
+#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__":"__STR(__LINE__)", memnew_arr type: "_STR(m_class))
+
+#else
+
+#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count)
+
+#endif
+
+template<typename T>
+T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
+
+ if (p_elements==0)
+ return 0;
+ /** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the
+ same strategy used by std::vector, and the DVector class, so it should be safe.*/
+
+ size_t len = sizeof(T) * p_elements;
+ unsigned int *mem = (unsigned int*)Memory::alloc_static( len + DEFAULT_ALIGNMENT, p_descr );
+ T *failptr=0; //get rid of a warning
+ ERR_FAIL_COND_V( !mem, failptr );
+ *mem=p_elements;
+ mem = (unsigned int *)( ((uint8_t*)mem) + DEFAULT_ALIGNMENT);
+ T* elems = (T*)mem;
+
+ /* call operator new */
+ for (size_t i=0;i<p_elements;i++) {
+ new(&elems[i],sizeof(T),p_descr) T;
+ }
+
+ return (T*)mem;
+}
+
+/**
+ * Wonders of having own array functions, you can actually check the length of
+ * an allocated-with memnew_arr() array
+ */
+
+template<typename T>
+size_t memarr_len(const T *p_class) {
+
+ uint8_t* ptr = ((uint8_t*)p_class) - DEFAULT_ALIGNMENT;
+ return *(size_t*)ptr;
+}
+
+template<typename T>
+void memdelete_arr(T *p_class) {
+
+ unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - DEFAULT_ALIGNMENT);
+
+ for (unsigned int i=0;i<*elems;i++) {
+
+ p_class[i].~T();
+ };
+ Memory::free_static(elems);
+}
+
+
+struct _GlobalNil {
+
+ int color;
+ _GlobalNil *right;
+ _GlobalNil *left;
+ _GlobalNil *parent;
+
+ _GlobalNil();
+
+};
+
+struct _GlobalNilClass {
+
+ static _GlobalNil _nil;
+};
+
+
+
+#endif
diff --git a/core/os/memory_pool_dynamic.cpp b/core/os/memory_pool_dynamic.cpp
new file mode 100644
index 0000000000..4df554f18d
--- /dev/null
+++ b/core/os/memory_pool_dynamic.cpp
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* memory_pool_dynamic.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 "memory_pool_dynamic.h"
+
+
+MemoryPoolDynamic* MemoryPoolDynamic::singleton=NULL;
+
+
+MemoryPoolDynamic* MemoryPoolDynamic::get_singleton() {
+
+ return singleton;
+}
+
+
+MemoryPoolDynamic::MemoryPoolDynamic() {
+
+ ERR_FAIL_COND(singleton!=NULL);
+ singleton=this;
+}
+
+MemoryPoolDynamic::~MemoryPoolDynamic() {
+
+ singleton=NULL;
+}
diff --git a/core/os/memory_pool_dynamic.h b/core/os/memory_pool_dynamic.h
new file mode 100644
index 0000000000..ca517daf41
--- /dev/null
+++ b/core/os/memory_pool_dynamic.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* memory_pool_dynamic.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 MEMORY_POOL_DYNAMIC_H
+#define MEMORY_POOL_DYNAMIC_H
+
+#include "typedefs.h"
+
+
+class MemoryPoolDynamic {
+
+ static MemoryPoolDynamic* singleton;
+protected:
+friend class Memory;
+friend class MID;
+
+ enum {
+
+ INVALID_ID=0xFFFFFFFF
+ };
+
+ static MemoryPoolDynamic* get_singleton();
+
+ typedef uint64_t ID;
+
+
+ virtual ID alloc(size_t p_amount,const char* p_description)=0;
+ virtual void free(ID p_id)=0;
+ virtual Error realloc(ID p_id, size_t p_amount)=0;
+ virtual bool is_valid(ID p_id)=0;
+ virtual size_t get_size(ID p_id) const=0;
+ virtual const char* get_description(ID p_id) const=0;
+
+ virtual Error lock(ID p_id)=0;
+ virtual void * get(ID p_ID)=0;
+ virtual Error unlock(ID p_id)=0;
+ virtual bool is_locked(ID p_id) const=0;
+
+ virtual size_t get_available_mem() const=0;
+ virtual size_t get_total_usage() const=0;
+
+ MemoryPoolDynamic();
+public:
+ virtual ~MemoryPoolDynamic();
+
+};
+
+
+#endif
+
+
+
+
+
diff --git a/core/os/memory_pool_dynamic_prealloc.cpp b/core/os/memory_pool_dynamic_prealloc.cpp
new file mode 100644
index 0000000000..c5823366c1
--- /dev/null
+++ b/core/os/memory_pool_dynamic_prealloc.cpp
@@ -0,0 +1,116 @@
+/*************************************************************************/
+/* memory_pool_dynamic_prealloc.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 "memory_pool_dynamic_prealloc.h"
+#include "os/memory.h"
+
+#include "print_string.h"
+MemoryPoolDynamicPrealloc::ID MemoryPoolDynamicPrealloc::alloc(size_t p_amount,const char* p_description) {
+
+
+// print_line("dynpool - allocating: "+itos(p_amount));
+ ID id = pool_alloc->alloc(p_amount);
+// print_line("dynpool - free: "+itos(pool_alloc->get_free_mem()));
+ return id;
+
+}
+
+void MemoryPoolDynamicPrealloc::free(ID p_id) {
+
+ pool_alloc->free(p_id);
+}
+
+Error MemoryPoolDynamicPrealloc::realloc(ID p_id, size_t p_amount) {
+
+ return pool_alloc->resize(p_id,p_amount);
+}
+
+bool MemoryPoolDynamicPrealloc::is_valid(ID p_id) {
+
+ return true;
+}
+
+size_t MemoryPoolDynamicPrealloc::get_size(ID p_id) const {
+
+ return pool_alloc->get_size(p_id);
+}
+
+const char* MemoryPoolDynamicPrealloc::get_description(ID p_id) const {
+
+ return "";
+}
+
+Error MemoryPoolDynamicPrealloc::lock(ID p_id) {
+
+// print_line("lock: "+itos(p_id));
+ return pool_alloc->lock(p_id);
+}
+
+void * MemoryPoolDynamicPrealloc::get(ID p_ID) {
+
+// print_line("get: "+itos(p_ID));
+ return pool_alloc->get(p_ID);
+}
+
+Error MemoryPoolDynamicPrealloc::unlock(ID p_id) {
+
+// print_line("unlock: "+itos(p_id));
+ pool_alloc->unlock(p_id);
+ return OK;
+}
+
+bool MemoryPoolDynamicPrealloc::is_locked(ID p_id) const {
+
+ return pool_alloc->is_locked(p_id);
+}
+
+
+size_t MemoryPoolDynamicPrealloc::get_available_mem() const {
+
+ return pool_alloc->get_free_mem();
+}
+
+size_t MemoryPoolDynamicPrealloc::get_total_usage() const {
+
+ return pool_alloc->get_used_mem();
+}
+
+
+
+MemoryPoolDynamicPrealloc::MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align, int p_max_entries) {
+
+ pool_alloc = memnew( PoolAllocator(p_mem,p_size,p_align,true,p_max_entries));
+
+}
+
+MemoryPoolDynamicPrealloc::~MemoryPoolDynamicPrealloc() {
+
+
+ memdelete( pool_alloc );
+}
+
diff --git a/core/os/memory_pool_dynamic_prealloc.h b/core/os/memory_pool_dynamic_prealloc.h
new file mode 100644
index 0000000000..698885561a
--- /dev/null
+++ b/core/os/memory_pool_dynamic_prealloc.h
@@ -0,0 +1,60 @@
+/*************************************************************************/
+/* memory_pool_dynamic_prealloc.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 MEMORY_POOL_DYNAMIC_PREALLOC_H
+#define MEMORY_POOL_DYNAMIC_PREALLOC_H
+
+#include "pool_allocator.h"
+#include "core/os/memory_pool_dynamic.h"
+
+class MemoryPoolDynamicPrealloc : public MemoryPoolDynamic {
+
+ PoolAllocator *pool_alloc;
+
+public:
+
+ virtual ID alloc(size_t p_amount,const char* p_description);
+ virtual void free(ID p_id);
+ virtual Error realloc(ID p_id, size_t p_amount);
+ virtual bool is_valid(ID p_id);
+ virtual size_t get_size(ID p_id) const;
+ virtual const char* get_description(ID p_id) const;
+
+ virtual Error lock(ID p_id);
+ virtual void * get(ID p_ID);
+ virtual Error unlock(ID p_id);
+ virtual bool is_locked(ID p_id) const;
+
+ virtual size_t get_available_mem() const;
+ virtual size_t get_total_usage() const;
+
+ MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align = 16, int p_max_entries=PoolAllocator::DEFAULT_MAX_ALLOCS);
+ ~MemoryPoolDynamicPrealloc();
+};
+
+#endif // MEMORY_POOL_DYNAMIC_PREALLOC_H
diff --git a/core/os/memory_pool_dynamic_static.cpp b/core/os/memory_pool_dynamic_static.cpp
new file mode 100644
index 0000000000..93f94d7726
--- /dev/null
+++ b/core/os/memory_pool_dynamic_static.cpp
@@ -0,0 +1,272 @@
+/*************************************************************************/
+/* memory_pool_dynamic_static.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 "memory_pool_dynamic_static.h"
+#include "os/memory.h"
+#include "os/os.h"
+#include "ustring.h"
+#include "print_string.h"
+#include <stdio.h>
+
+MemoryPoolDynamicStatic::Chunk *MemoryPoolDynamicStatic::get_chunk(ID p_id) {
+
+ uint64_t check = p_id/MAX_CHUNKS;
+ uint64_t idx = p_id%MAX_CHUNKS;
+
+ if (!chunk[idx].mem || chunk[idx].check!=check)
+ return NULL;
+
+ return &chunk[idx];
+}
+
+
+const MemoryPoolDynamicStatic::Chunk *MemoryPoolDynamicStatic::get_chunk(ID p_id) const {
+
+ uint64_t check = p_id/MAX_CHUNKS;
+ uint64_t idx = p_id%MAX_CHUNKS;
+
+ if (!chunk[idx].mem || chunk[idx].check!=check)
+ return NULL;
+
+ return &chunk[idx];
+}
+
+MemoryPoolDynamic::ID MemoryPoolDynamicStatic::alloc(size_t p_amount,const char* p_description) {
+
+ _THREAD_SAFE_METHOD_
+
+ int idx=-1;
+
+ for (int i=0;i<MAX_CHUNKS;i++) {
+
+ last_alloc++;
+ if (last_alloc>=MAX_CHUNKS)
+ last_alloc=0;
+
+ if ( !chunk[last_alloc].mem ) {
+
+ idx=last_alloc;
+ break;
+ }
+ }
+
+
+ if (idx==-1) {
+ ERR_EXPLAIN("Out of dynamic Memory IDs");
+ ERR_FAIL_V(INVALID_ID);
+ //return INVALID_ID;
+ }
+
+ //chunk[idx].mem = Memory::alloc_static(p_amount,p_description);
+ chunk[idx].mem = memalloc(p_amount);
+ if (!chunk[idx].mem)
+ return INVALID_ID;
+
+ chunk[idx].size=p_amount;
+ chunk[idx].check=++last_check;
+ chunk[idx].descr=p_description;
+ chunk[idx].lock=0;
+
+ total_usage+=p_amount;
+ if (total_usage>max_usage)
+ max_usage=total_usage;
+
+ ID id = chunk[idx].check*MAX_CHUNKS + (uint64_t)idx;
+
+ return id;
+
+}
+void MemoryPoolDynamicStatic::free(ID p_id) {
+
+ _THREAD_SAFE_METHOD_
+
+ Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND(!c);
+
+
+ total_usage-=c->size;
+ memfree(c->mem);
+
+ c->mem=0;
+
+ if (c->lock>0) {
+
+ ERR_PRINT("Freed ID Still locked");
+ }
+}
+
+Error MemoryPoolDynamicStatic::realloc(ID p_id, size_t p_amount) {
+
+ _THREAD_SAFE_METHOD_
+
+ Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(c->lock > 0 , ERR_LOCKED );
+
+
+ void * new_mem = memrealloc(c->mem,p_amount);
+
+ ERR_FAIL_COND_V(!new_mem,ERR_OUT_OF_MEMORY);
+ total_usage-=c->size;
+ c->mem=new_mem;
+ c->size=p_amount;
+ total_usage+=c->size;
+ if (total_usage>max_usage)
+ max_usage=total_usage;
+
+
+ return OK;
+}
+bool MemoryPoolDynamicStatic::is_valid(ID p_id) {
+
+ _THREAD_SAFE_METHOD_
+
+ Chunk *c = get_chunk(p_id);
+
+ return c!=NULL;
+
+}
+size_t MemoryPoolDynamicStatic::get_size(ID p_id) const {
+
+ _THREAD_SAFE_METHOD_
+
+ const Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,0);
+
+ return c->size;
+
+
+}
+const char* MemoryPoolDynamicStatic::get_description(ID p_id) const {
+
+ _THREAD_SAFE_METHOD_
+
+ const Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,"");
+
+ return c->descr;
+
+}
+
+
+bool MemoryPoolDynamicStatic::is_locked(ID p_id) const {
+
+ _THREAD_SAFE_METHOD_
+
+ const Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,false);
+
+ return c->lock>0;
+
+}
+
+Error MemoryPoolDynamicStatic::lock(ID p_id) {
+
+ _THREAD_SAFE_METHOD_
+
+ Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,ERR_INVALID_PARAMETER);
+
+ c->lock++;
+
+ return OK;
+}
+void * MemoryPoolDynamicStatic::get(ID p_id) {
+
+ _THREAD_SAFE_METHOD_
+
+ const Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,NULL);
+ ERR_FAIL_COND_V( c->lock==0, NULL );
+
+ return c->mem;
+}
+Error MemoryPoolDynamicStatic::unlock(ID p_id) {
+
+ _THREAD_SAFE_METHOD_
+
+ Chunk *c = get_chunk(p_id);
+ ERR_FAIL_COND_V(!c,ERR_INVALID_PARAMETER);
+
+ ERR_FAIL_COND_V( c->lock<=0, ERR_INVALID_PARAMETER );
+ c->lock--;
+
+ return OK;
+}
+
+size_t MemoryPoolDynamicStatic::get_available_mem() const {
+
+ return Memory::get_static_mem_available();
+}
+
+size_t MemoryPoolDynamicStatic::get_total_usage() const {
+ _THREAD_SAFE_METHOD_
+
+ return total_usage;
+}
+
+MemoryPoolDynamicStatic::MemoryPoolDynamicStatic() {
+
+ last_check=1;
+ last_alloc=0;
+ total_usage=0;
+ max_usage=0;
+}
+
+MemoryPoolDynamicStatic::~MemoryPoolDynamicStatic() {
+
+#ifdef DEBUG_MEMORY_ENABLED
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+
+ if (total_usage>0) {
+
+ ERR_PRINT("DYNAMIC ALLOC: ** MEMORY LEAKS DETECTED **");
+ ERR_PRINT(String("DYNAMIC ALLOC: "+String::num(total_usage)+" bytes of memory in use at exit.").ascii().get_data());
+
+ ERR_PRINT("DYNAMIC ALLOC: Following is the list of leaked allocations:");
+
+ for (int i=0;i<MAX_CHUNKS;i++) {
+
+ if (chunk[i].mem) {
+
+ ERR_PRINT(String("\t"+String::num(chunk[i].size)+" bytes - "+String(chunk[i].descr)).ascii().get_data());
+ }
+ }
+
+ ERR_PRINT("DYNAMIC ALLOC: End of Report.");
+
+ print_line("INFO: dynmem - max: "+itos(max_usage)+", "+itos(total_usage)+" leaked.");
+ } else {
+
+ print_line("INFO: dynmem - max: "+itos(max_usage)+", no leaks.");
+ }
+ }
+
+#endif
+}
diff --git a/core/os/memory_pool_dynamic_static.h b/core/os/memory_pool_dynamic_static.h
new file mode 100644
index 0000000000..ce038bc00a
--- /dev/null
+++ b/core/os/memory_pool_dynamic_static.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* memory_pool_dynamic_static.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 MEMORY_POOL_DYNAMIC_STATIC_H
+#define MEMORY_POOL_DYNAMIC_STATIC_H
+
+#include "os/memory_pool_dynamic.h"
+#include "typedefs.h"
+#include "os/thread_safe.h"
+
+class MemoryPoolDynamicStatic : public MemoryPoolDynamic {
+
+ _THREAD_SAFE_CLASS_
+
+ enum {
+ MAX_CHUNKS=16384
+ };
+
+
+ struct Chunk {
+
+ uint64_t lock;
+ uint64_t check;
+ void *mem;
+ size_t size;
+ const char *descr;
+
+ Chunk() { mem=NULL; lock=0; check=0; }
+ };
+
+ Chunk chunk[MAX_CHUNKS];
+ uint64_t last_check;
+ int last_alloc;
+ size_t total_usage;
+ size_t max_usage;
+
+ Chunk *get_chunk(ID p_id);
+ const Chunk *get_chunk(ID p_id) const;
+public:
+
+ virtual ID alloc(size_t p_amount,const char* p_description);
+ virtual void free(ID p_id);
+ virtual Error realloc(ID p_id, size_t p_amount);
+ virtual bool is_valid(ID p_id);
+ virtual size_t get_size(ID p_id) const;
+ virtual const char* get_description(ID p_id) const;
+
+ virtual bool is_locked(ID p_id) const;
+ virtual Error lock(ID p_id);
+ virtual void * get(ID p_ID);
+ virtual Error unlock(ID p_id);
+
+ virtual size_t get_available_mem() const;
+ virtual size_t get_total_usage() const;
+
+ MemoryPoolDynamicStatic();
+ virtual ~MemoryPoolDynamicStatic();
+
+};
+
+#endif
diff --git a/core/os/memory_pool_static.cpp b/core/os/memory_pool_static.cpp
new file mode 100644
index 0000000000..9dd5baf4e4
--- /dev/null
+++ b/core/os/memory_pool_static.cpp
@@ -0,0 +1,49 @@
+/*************************************************************************/
+/* memory_pool_static.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 "memory_pool_static.h"
+
+MemoryPoolStatic *MemoryPoolStatic::singleton=0;
+
+MemoryPoolStatic *MemoryPoolStatic::get_singleton() {
+
+ return singleton;
+}
+
+
+MemoryPoolStatic::MemoryPoolStatic() {
+
+ singleton=this;
+}
+
+
+MemoryPoolStatic::~MemoryPoolStatic() {
+ singleton=NULL;
+}
+
+
diff --git a/core/os/memory_pool_static.h b/core/os/memory_pool_static.h
new file mode 100644
index 0000000000..f2b372d03b
--- /dev/null
+++ b/core/os/memory_pool_static.h
@@ -0,0 +1,69 @@
+/*************************************************************************/
+/* memory_pool_static.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 MEMORY_POOL_STATIC_H
+#define MEMORY_POOL_STATIC_H
+
+#include <stddef.h>
+
+#include "core/typedefs.h"
+
+/**
+ @author Juan Linietsky <red@lunatea>
+*/
+class MemoryPoolStatic {
+private:
+
+ static MemoryPoolStatic *singleton;
+
+public:
+
+ static MemoryPoolStatic *get_singleton();
+
+ virtual void* alloc(size_t p_bytes,const char *p_description)=0; ///< Pointer in p_description shold be to a const char const like "hello"
+ virtual void* realloc(void * p_memory,size_t p_bytes)=0; ///< Pointer in p_description shold be to a const char const like "hello"
+ virtual void free(void *p_ptr)=0; ///< Pointer in p_description shold be to a const char const
+
+ virtual size_t get_available_mem() const=0;
+ virtual size_t get_total_usage()=0;
+ virtual size_t get_max_usage()=0;
+
+ /* Most likely available only if memory debugger was compiled in */
+ virtual int get_alloc_count()=0;
+ virtual void * get_alloc_ptr(int p_alloc_idx)=0;
+ virtual const char* get_alloc_description(int p_alloc_idx)=0;
+ virtual size_t get_alloc_size(int p_alloc_idx)=0;
+
+ virtual void dump_mem_to_file(const char* p_file)=0;
+
+ MemoryPoolStatic();
+ virtual ~MemoryPoolStatic();
+
+};
+
+#endif
diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp
new file mode 100644
index 0000000000..03d423ae04
--- /dev/null
+++ b/core/os/mutex.cpp
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* mutex.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 "mutex.h"
+#include "error_macros.h"
+#include <stddef.h>
+
+
+
+Mutex* (*Mutex::create_func)(bool)=0;
+
+Mutex *Mutex::create(bool p_recursive) {
+
+ ERR_FAIL_COND_V( !create_func, 0 );
+
+ return create_func(p_recursive);
+}
+
+
+Mutex::~Mutex() {
+
+
+}
+
+Mutex *_global_mutex=NULL;;
+
+void _global_lock() {
+
+ if (_global_mutex)
+ _global_mutex->lock();
+}
+void _global_unlock() {
+
+ if (_global_mutex)
+ _global_mutex->unlock();
+}
+
diff --git a/core/os/mutex.h b/core/os/mutex.h
new file mode 100644
index 0000000000..512180d6c7
--- /dev/null
+++ b/core/os/mutex.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* mutex.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 MUTEX_H
+#define MUTEX_H
+
+#include "error_list.h"
+
+
+/**
+ * @class Mutex
+ * @author Juan Linietsky
+ * Portable Mutex (thread-safe locking) implementation.
+ * Mutexes are always recursive ( they don't self-lock in a single thread ).
+ * Mutexes can be used with a Lockp object like this, to avoid having to worry about unlocking:
+ * Lockp( mutex );
+ */
+
+
+class Mutex {
+protected:
+ static Mutex* (*create_func)(bool);
+
+public:
+
+ virtual void lock()=0; ///< Lock the mutex, block if locked by someone else
+ virtual void unlock()=0; ///< Unlock the mutex, let other threads continue
+ virtual Error try_lock()=0; ///< Attempt to lock the mutex, true on success, false means it can't lock.
+
+ static Mutex * create(bool p_recursive=true); ///< Create a mutex
+
+ virtual ~Mutex();
+};
+
+class MutexLock {
+
+ Mutex *mutex;
+public:
+
+ MutexLock(Mutex* p_mutex) { mutex=p_mutex; if (mutex) mutex->lock(); }
+ ~MutexLock() { if (mutex) mutex->unlock(); }
+
+};
+
+#endif
diff --git a/core/os/os.cpp b/core/os/os.cpp
new file mode 100644
index 0000000000..1ee87099a2
--- /dev/null
+++ b/core/os/os.cpp
@@ -0,0 +1,461 @@
+/*************************************************************************/
+/* os.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.h"
+#include "os/file_access.h"
+#include <stdarg.h>
+#include "dir_access.h"
+#include "globals.h"
+
+
+OS* OS::singleton=NULL;
+
+OS* OS::get_singleton() {
+
+ return singleton;
+}
+
+uint32_t OS::get_ticks_msec() const
+{ return get_ticks_usec()/1000; }
+
+uint64_t OS::get_unix_time() const {
+
+ return 0;
+};
+
+void OS::debug_break() {
+
+ // something
+};
+
+
+void OS::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
+
+ if (p_rationale && *p_rationale)
+ print("**ERROR**: %s\n ",p_rationale);
+ print("**ERROR**: At: %s:%i:%s() - %s\n",p_file,p_line,p_function,p_code);
+}
+
+void OS::print(const char* p_format, ...) {
+
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ vprint(p_format, argp);
+
+ va_end(argp);
+};
+
+void OS::printerr(const char* p_format, ...) {
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ vprint(p_format, argp, true);
+
+ va_end(argp);
+};
+
+
+void OS::set_iterations_per_second(int p_ips) {
+
+ ips=p_ips;
+}
+int OS::get_iterations_per_second() const {
+
+ return ips;
+}
+
+void OS::set_low_processor_usage_mode(bool p_enabled) {
+
+ low_processor_usage_mode=p_enabled;
+}
+
+bool OS::is_in_low_processor_usage_mode() const {
+
+ return low_processor_usage_mode;
+}
+
+void OS::set_clipboard(const String& p_text) {
+
+ _local_clipboard=p_text;
+}
+String OS::get_clipboard() const {
+
+ return _local_clipboard;
+}
+
+String OS::get_executable_path() const {
+
+ return _execpath;
+}
+
+uint64_t OS::get_frames_drawn() {
+
+ return frames_drawn;
+}
+
+bool OS::is_stdout_verbose() const {
+
+ return _verbose_stdout;
+}
+
+void OS::set_last_error(const char* p_error) {
+
+ GLOBAL_LOCK_FUNCTION
+ if (p_error==NULL)
+ p_error="Unknown Error";
+
+ if (last_error)
+ memfree(last_error);
+ last_error=NULL;
+ int len =0;
+ while(p_error[len++]);
+
+ last_error=(char*)memalloc(len);
+ for(int i=0;i<len;i++)
+ last_error[i]=p_error[i];
+
+}
+
+const char *OS::get_last_error() const {
+ GLOBAL_LOCK_FUNCTION
+ return last_error?last_error:"";
+}
+
+void OS::dump_memory_to_file(const char* p_file) {
+
+ Memory::dump_static_mem_to_file(p_file);
+}
+
+static FileAccess *_OSPRF=NULL;
+
+static void _OS_printres(Object *p_obj) {
+
+ Resource *res = p_obj->cast_to<Resource>();
+ if (!res)
+ return;
+
+ String str = itos(res->get_instance_ID())+String(res->get_type())+":"+String(res->get_name())+" - "+res->get_path();
+ if (_OSPRF)
+ _OSPRF->store_line(str);
+ else
+ print_line(str);
+
+}
+
+bool OS::has_virtual_keyboard() const {
+
+ return false;
+}
+void OS::show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect) {
+
+
+
+}
+
+void OS::hide_virtual_keyboard(){
+
+
+}
+
+
+void OS::print_all_resources(String p_to_file) {
+
+ ERR_FAIL_COND(p_to_file!="" && _OSPRF);
+ if (p_to_file!="") {
+
+ Error err;
+ _OSPRF=FileAccess::open(p_to_file,FileAccess::WRITE,&err);
+ if (err!=OK) {
+ _OSPRF=NULL;
+ ERR_FAIL_COND(err!=OK);
+ }
+ }
+
+ ObjectDB::debug_objects(_OS_printres);
+
+ if (p_to_file!="") {
+
+ if (_OSPRF)
+ memdelete(_OSPRF);
+ _OSPRF=NULL;
+ }
+}
+
+void OS::print_resources_in_use(bool p_short) {
+
+
+ //ResourceCache::dump(NULL,p_short);
+}
+
+void OS::dump_resources_to_file(const char* p_file) {
+
+ ResourceCache::dump(p_file);
+}
+
+
+void OS::clear_last_error() {
+
+ GLOBAL_LOCK_FUNCTION
+ if (last_error)
+ memfree(last_error);
+ last_error=NULL;
+}
+void OS::set_frame_delay(uint32_t p_msec) {
+
+ _frame_delay=p_msec;
+}
+
+uint32_t OS::get_frame_delay() const {
+
+ return _frame_delay;
+}
+
+void OS::set_no_window_mode(bool p_enable) {
+
+ _no_window=p_enable;
+}
+
+bool OS::is_no_window_mode_enabled() const {
+
+ return _no_window;
+}
+
+int OS::get_exit_code() const {
+
+ return _exit_code;
+}
+void OS::set_exit_code(int p_code) {
+
+ _exit_code=p_code;
+}
+
+String OS::get_locale() const {
+
+ return "en";
+}
+
+String OS::get_resource_dir() const {
+
+ return Globals::get_singleton()->get_resource_path();
+}
+
+String OS::get_data_dir() const {
+
+ return ".";
+};
+
+Error OS::shell_open(String p_uri) {
+ return ERR_UNAVAILABLE;
+};
+
+// implement these with the canvas?
+Error OS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object* p_obj, String p_callback) {
+
+ while (true) {
+
+ print("%ls\n--------\n%ls\n", p_title.c_str(), p_description.c_str());
+ for (int i=0; i<p_buttons.size(); i++) {
+ if (i>0) print(", ");
+ print("%i=%ls", i+1, p_buttons[i].c_str());
+ };
+ print("\n");
+ String res = get_stdin_string().strip_edges();
+ if (!res.is_numeric())
+ continue;
+ int n = res.to_int();
+ if (n < 0 || n >= p_buttons.size())
+ continue;
+ if (p_obj && p_callback != "")
+ p_obj->call_deferred(p_callback, n);
+ break;
+ };
+ return OK;
+};
+
+Error OS::dialog_input_text(String p_title, String p_description, String p_partial, Object* p_obj, String p_callback) {
+
+ ERR_FAIL_COND_V(!p_obj, FAILED);
+ ERR_FAIL_COND_V(p_callback == "", FAILED);
+ print("%ls\n---------\n%ls\n[%ls]:\n", p_title.c_str(), p_description.c_str(), p_partial.c_str());
+
+ String res = get_stdin_string().strip_edges();
+ bool success = true;
+ if (res == "") {
+ res = p_partial;
+ };
+
+ p_obj->call_deferred(p_callback, success, res);
+
+ return OK;
+};
+
+int OS::get_static_memory_usage() const {
+
+ return Memory::get_static_mem_usage();
+}
+int OS::get_dynamic_memory_usage() const{
+
+ return Memory::get_dynamic_mem_usage();
+}
+
+int OS::get_static_memory_peak_usage() const {
+
+ return Memory::get_static_mem_max_usage();
+}
+
+Error OS::set_cwd(const String& p_cwd) {
+
+ return ERR_CANT_OPEN;
+}
+
+bool OS::has_touchscreen_ui_hint() const {
+
+ //return false;
+ return GLOBAL_DEF("display/emulate_touchscreen",false);
+}
+
+int OS::get_free_static_memory() const {
+
+ return Memory::get_static_mem_available();
+}
+
+void OS::yield() {
+
+
+}
+
+void OS::set_screen_orientation(ScreenOrientation p_orientation) {
+
+ _orientation=p_orientation;
+}
+
+OS::ScreenOrientation OS::get_screen_orientation() const {
+
+ return (OS::ScreenOrientation)_orientation;
+}
+
+
+void OS::_ensure_data_dir() {
+
+ String dd = get_data_dir();
+ DirAccess *da = DirAccess::open(dd);
+ if (da) {
+ memdelete(da);
+ return;
+ }
+
+ da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Error err = da->make_dir(dd);
+ if (err!=OK) {
+ ERR_EXPLAIN("Error attempting to create data dir: "+dd);
+ }
+ ERR_FAIL_COND(err!=OK);
+
+ memdelete(da);
+
+
+}
+
+void OS::set_icon(const Image& p_icon) {
+
+
+}
+
+String OS::get_model_name() const {
+
+ return "GenericDevice";
+}
+
+
+void OS::set_cmdline(const char* p_execpath, const List<String>& p_args) {
+
+ _execpath = p_execpath;
+ _cmdline = p_args;
+};
+
+void OS::release_rendering_thread() {
+
+
+}
+
+void OS::make_rendering_thread() {
+
+
+}
+
+void OS::swap_buffers() {
+
+}
+
+String OS::get_unique_ID() const {
+
+ ERR_FAIL_V("");
+}
+
+int OS::get_processor_count() const {
+
+ return 1;
+}
+
+void OS::set_mouse_mode(MouseMode p_mode) {
+
+
+}
+
+OS::MouseMode OS::get_mouse_mode() const{
+
+ return MOUSE_MODE_VISIBLE;
+}
+
+
+OS::OS() {
+ last_error=NULL;
+ frames_drawn=0;
+ singleton=this;
+ ips=60;
+ low_processor_usage_mode=false;
+ _verbose_stdout=false;
+ _frame_delay=0;
+ _no_window=false;
+ _exit_code=0;
+ _orientation=SCREEN_LANDSCAPE;
+ _fps=1;
+ _render_thread_mode=RENDER_THREAD_SAFE;
+ Math::seed(1234567);
+}
+
+
+OS::~OS() {
+
+ singleton=NULL;
+}
+
+
diff --git a/core/os/os.h b/core/os/os.h
new file mode 100644
index 0000000000..5fc4893a97
--- /dev/null
+++ b/core/os/os.h
@@ -0,0 +1,328 @@
+/*************************************************************************/
+/* os.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_H
+#define OS_H
+
+#include "ustring.h"
+#include "list.h"
+#include "vector.h"
+#include "os/main_loop.h"
+#include <stdarg.h>
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class OS {
+
+ static OS* singleton;
+ String _execpath;
+ String _custom_level;
+ List<String> _cmdline;
+ int ips;
+ bool low_processor_usage_mode;
+ bool _verbose_stdout;
+ String _local_clipboard;
+ uint64_t frames_drawn;
+ uint32_t _frame_delay;
+ bool _no_window;
+ int _exit_code;
+ int _orientation;
+ float _fps;
+
+ char *last_error;
+
+public:
+ enum RenderThreadMode {
+
+ RENDER_THREAD_UNSAFE,
+ RENDER_THREAD_SAFE,
+ RENDER_SEPARATE_THREAD
+ };
+ struct VideoMode {
+
+ int width,height;
+ bool fullscreen;
+ bool resizable;
+ float get_aspect() const { return (float)width/(float)height; }
+ VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) { width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
+ };
+protected:
+friend class Main;
+
+ RenderThreadMode _render_thread_mode;
+
+ // functions used by main to initialize/deintialize the OS
+ virtual int get_video_driver_count() const=0;
+ virtual const char * get_video_driver_name(int p_driver) const=0;
+
+ virtual VideoMode get_default_video_mode() const=0;
+
+ virtual int get_audio_driver_count() const=0;
+ virtual const char * get_audio_driver_name(int p_driver) const=0;
+
+ virtual void initialize_core()=0;
+ virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver)=0;
+
+ virtual void set_main_loop( MainLoop * p_main_loop )=0;
+ virtual void delete_main_loop()=0;
+
+ virtual void finalize()=0;
+ virtual void finalize_core()=0;
+
+ virtual void set_cmdline(const char* p_execpath, const List<String>& p_args);
+
+ void _ensure_data_dir();
+
+public:
+
+ typedef int64_t ProcessID;
+
+ static OS* get_singleton();
+
+ enum ErrorType {
+ ERR_ERROR,
+ ERR_WARNING,
+ ERR_SCRIPT
+ };
+
+ virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);
+
+ virtual void print(const char *p_format, ... );
+ virtual void printerr(const char *p_format, ... );
+ virtual void vprint(const char* p_format, va_list p_list, bool p_stderr=false)=0;
+ virtual void alert(const String& p_alert,const String& p_title="ALERT!")=0;
+ virtual String get_stdin_string(bool p_block = true)=0;
+
+ virtual void set_last_error(const char* p_error);
+ virtual const char *get_last_error() const;
+ virtual void clear_last_error();
+
+
+
+ enum MouseMode {
+ MOUSE_MODE_VISIBLE,
+ MOUSE_MODE_HIDDEN,
+ MOUSE_MODE_CAPTURED
+ };
+
+ virtual void set_mouse_mode(MouseMode p_mode);
+ virtual MouseMode get_mouse_mode() const;
+
+
+ virtual Point2 get_mouse_pos() const=0;
+ virtual int get_mouse_button_state() const=0;
+ virtual void set_window_title(const String& p_title)=0;
+
+ virtual void set_clipboard(const String& p_text);
+ virtual String get_clipboard() const;
+
+ virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0)=0;
+ virtual VideoMode get_video_mode(int p_screen=0) const=0;
+ virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const=0;
+
+ virtual void set_iterations_per_second(int p_ips);
+ virtual int get_iterations_per_second() const;
+
+ virtual float get_frames_per_second() const { return _fps; };
+
+ virtual void set_low_processor_usage_mode(bool p_enabled);
+ virtual bool is_in_low_processor_usage_mode() const;
+
+ virtual String get_executable_path() const;
+ virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL)=0;
+ virtual Error kill(const ProcessID& p_pid)=0;
+
+ virtual Error shell_open(String p_uri);
+ virtual Error set_cwd(const String& p_cwd);
+
+ virtual bool has_environment(const String& p_var) const=0;
+ virtual String get_environment(const String& p_var) const=0;
+
+ virtual String get_name()=0;
+ virtual List<String> get_cmdline_args() const { return _cmdline; }
+ virtual String get_model_name() const;
+
+ virtual MainLoop *get_main_loop() const=0;
+
+ String get_custom_level() const { return _custom_level; }
+
+ virtual void yield();
+
+ enum Weekday {
+ DAY_SUNDAY,
+ DAY_MONDAY,
+ DAY_TUESDAY,
+ DAY_WEDNESDAY,
+ DAY_THURSDAY,
+ DAY_FRIDAY,
+ DAY_SATURDAY
+ };
+
+ enum Month {
+ MONTH_JANUARY,
+ MONTH_FEBRUARY,
+ MONTH_MARCH,
+ MONTH_APRIL,
+ MONTH_MAY,
+ MONTH_JUNE,
+ MONTH_JULY,
+ MONTH_AUGUST,
+ MONTH_SEPTEMBER,
+ MONTH_OCTOBER,
+ MONTH_NOVEMBER,
+ MONTH_DECEMBER
+ };
+
+ struct Date {
+
+ int year;
+ Month month;
+ int day;
+ Weekday weekday;
+ bool dst;
+ };
+
+ struct Time {
+
+ int hour;
+ int min;
+ int sec;
+ };
+
+ virtual Date get_date() const=0;
+ virtual Time get_time() const=0;
+ virtual uint64_t get_unix_time() const;
+
+ virtual void delay_usec(uint32_t p_usec) const=0;
+ virtual uint64_t get_ticks_usec() const=0;
+ uint32_t get_ticks_msec() const;
+
+ void set_frame_delay(uint32_t p_msec);
+ uint32_t get_frame_delay() const;
+
+ virtual bool can_draw() const = 0;
+
+ uint64_t get_frames_drawn();
+
+ bool is_stdout_verbose() const;
+
+ enum CursorShape {
+ CURSOR_ARROW,
+ CURSOR_IBEAM,
+ CURSOR_POINTING_HAND,
+ CURSOR_CROSS,
+ CURSOR_WAIT,
+ CURSOR_BUSY,
+ CURSOR_DRAG,
+ CURSOR_CAN_DROP,
+ CURSOR_FORBIDDEN,
+ CURSOR_VSIZE,
+ CURSOR_HSIZE,
+ CURSOR_BDIAGSIZE,
+ CURSOR_FDIAGSIZE,
+ CURSOR_MOVE,
+ CURSOR_VSPLIT,
+ CURSOR_HSPLIT,
+ CURSOR_HELP,
+ CURSOR_MAX
+ };
+
+
+ virtual bool has_virtual_keyboard() const;
+ virtual void show_virtual_keyboard(const String& p_existing_text,const Rect2& p_screen_rect=Rect2());
+ virtual void hide_virtual_keyboard();
+
+ virtual void set_cursor_shape(CursorShape p_shape)=0;
+
+ virtual bool get_swap_ok_cancel() { return false; }
+ virtual void dump_memory_to_file(const char* p_file);
+ virtual void dump_resources_to_file(const char* p_file);
+ virtual void print_resources_in_use(bool p_short=false);
+ virtual void print_all_resources(String p_to_file="");
+
+ virtual int get_static_memory_usage() const;
+ virtual int get_static_memory_peak_usage() const;
+ virtual int get_dynamic_memory_usage() const;
+ virtual int get_free_static_memory() const;
+
+ RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; }
+
+ virtual String get_locale() const;
+
+ virtual String get_data_dir() const;
+ virtual String get_resource_dir() const;
+
+ virtual void set_no_window_mode(bool p_enable);
+ virtual bool is_no_window_mode_enabled() const;
+
+ virtual bool has_touchscreen_ui_hint() const;
+
+ enum ScreenOrientation {
+
+ SCREEN_LANDSCAPE,
+ SCREEN_PORTRAIT,
+ SCREEN_REVERSE_LANDSCAPE,
+ SCREEN_REVERSE_PORTRAIT,
+ SCREEN_SENSOR_LANDSCAPE,
+ SCREEN_SENSOR_PORTRAIT,
+ SCREEN_SENSOR,
+ };
+
+ virtual void set_screen_orientation(ScreenOrientation p_orientation);
+ ScreenOrientation get_screen_orientation() const;
+
+ virtual void move_window_to_foreground() {};
+
+ virtual void debug_break();
+
+ virtual void release_rendering_thread();
+ virtual void make_rendering_thread();
+ virtual void swap_buffers();
+
+
+ virtual void set_icon(const Image& p_icon);
+
+ virtual int get_exit_code() const;
+ virtual void set_exit_code(int p_code);
+
+ virtual int get_processor_count() const;
+
+ virtual String get_unique_ID() const;
+
+
+ virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object* p_obj, String p_callback);
+ virtual Error dialog_input_text(String p_title, String p_description, String p_partial, Object* p_obj, String p_callback);
+
+ OS();
+ virtual ~OS();
+
+};
+
+#endif
+
diff --git a/core/os/pc_joystick_map.h b/core/os/pc_joystick_map.h
new file mode 100644
index 0000000000..171723439b
--- /dev/null
+++ b/core/os/pc_joystick_map.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* pc_joystick_map.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 PC_JOYSTICK_MAP_H
+#define PC_JOYSTICK_MAP_H
+
+#include "input_event.h"
+
+static const int _pc_joystick_button_remap[JOY_BUTTON_MAX]={
+
+ JOY_SELECT,
+ JOY_L3,
+ JOY_R3,
+ JOY_START,
+
+ JOY_DPAD_UP,
+ JOY_DPAD_RIGHT,
+ JOY_DPAD_DOWN,
+ JOY_DPAD_LEFT,
+
+ JOY_L2,
+ JOY_R2,
+ JOY_L,
+ JOY_R,
+
+ JOY_SNES_X,
+ JOY_SNES_A,
+ JOY_SNES_B,
+ JOY_SNES_Y,
+
+ // JOY_HOME = 16
+};
+
+
+static int _pc_joystick_get_native_button(int p_pc_button) {
+
+ if (p_pc_button<0 || p_pc_button>=JOY_BUTTON_MAX)
+ return p_pc_button;
+ return _pc_joystick_button_remap[p_pc_button];
+}
+
+static const int _pc_joystick_axis_remap[JOY_AXIS_MAX]={
+ JOY_ANALOG_0_X,
+ JOY_ANALOG_0_Y,
+ JOY_ANALOG_1_X,
+ JOY_ANALOG_1_Y,
+ JOY_ANALOG_2_X,
+ JOY_ANALOG_2_Y,
+ JOY_AXIS_6,
+ JOY_AXIS_7
+};
+
+
+static int _pc_joystick_get_native_axis(int p_pc_axis) {
+
+ if (p_pc_axis<0 || p_pc_axis>=JOY_BUTTON_MAX)
+ return p_pc_axis;
+ return _pc_joystick_axis_remap[p_pc_axis];
+}
+
+#endif // PC_JOYSTICK_MAP_H
diff --git a/core/os/semaphore.cpp b/core/os/semaphore.cpp
new file mode 100644
index 0000000000..3abab34886
--- /dev/null
+++ b/core/os/semaphore.cpp
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* semaphore.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 "semaphore.h"
+#include "error_macros.h"
+
+Semaphore* (*Semaphore::create_func)()=0;
+
+Semaphore *Semaphore::create() {
+
+ ERR_FAIL_COND_V( !create_func, 0 );
+
+ return create_func();
+}
+
+
+Semaphore::~Semaphore() {
+
+}
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
new file mode 100644
index 0000000000..b188f07399
--- /dev/null
+++ b/core/os/semaphore.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* semaphore.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 SEMAPHORE_H
+#define SEMAPHORE_H
+
+#include "error_list.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class Semaphore {
+protected:
+ static Semaphore* (*create_func)();
+
+public:
+
+ virtual Error wait()=0; ///< wait until semaphore has positive value, then decrement and pass
+ virtual Error post()=0; ///< unlock the semaphore, incrementing the value
+ virtual int get() const=0; ///< get semaphore value
+
+ static Semaphore * create(); ///< Create a mutex
+
+ virtual ~Semaphore();
+};
+
+
+#endif
diff --git a/core/os/shell.cpp b/core/os/shell.cpp
new file mode 100644
index 0000000000..565929eae5
--- /dev/null
+++ b/core/os/shell.cpp
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* shell.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 "shell.h"
+
+
+Shell * Shell::singleton=NULL;
+
+
+Shell * Shell::get_singleton() {
+
+ return singleton;
+}
+
+
+Shell::~Shell() {
+
+}
+
+Shell::Shell() {
+
+ singleton=this;
+}
+
+
+
diff --git a/core/os/shell.h b/core/os/shell.h
new file mode 100644
index 0000000000..38b29c6eca
--- /dev/null
+++ b/core/os/shell.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* shell.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 SHELL_H
+#define SHELL_H
+
+#include "typedefs.h"
+#include "ustring.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class Shell {
+
+ static Shell * singleton;
+public:
+
+ static Shell * get_singleton();
+ virtual void execute(String p_path)=0;
+
+ Shell();
+ virtual ~Shell();
+};
+
+#endif
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
new file mode 100644
index 0000000000..d8d9f3e291
--- /dev/null
+++ b/core/os/thread.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* thread.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 "thread.h"
+
+
+Thread* (*Thread::create_func)(ThreadCreateCallback,void *,const Settings&)=NULL;
+Thread::ID (*Thread::get_thread_ID_func)()=NULL;
+void (*Thread::wait_to_finish_func)(Thread*)=NULL;
+
+Thread::ID Thread::_main_thread_id=0;
+
+Thread::ID Thread::get_caller_ID() {
+
+ if (get_thread_ID_func)
+ return get_thread_ID_func();
+ return 0;
+}
+
+Thread* Thread::create(ThreadCreateCallback p_callback,void * p_user,const Settings& p_settings) {
+
+ if (create_func) {
+
+ return create_func(p_callback,p_user,p_settings);
+ }
+ return NULL;
+}
+
+void Thread::wait_to_finish(Thread *p_thread) {
+
+ if (wait_to_finish_func)
+ wait_to_finish_func(p_thread);
+
+}
+
+Thread::Thread()
+{
+}
+
+
+Thread::~Thread()
+{
+}
+
+
diff --git a/core/os/thread.h b/core/os/thread.h
new file mode 100644
index 0000000000..864fc6db05
--- /dev/null
+++ b/core/os/thread.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* thread.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 THREAD_H
+#define THREAD_H
+
+
+#include "typedefs.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+
+typedef void (*ThreadCreateCallback)(void *p_userdata);
+
+class Thread {
+public:
+
+ enum Priority {
+
+ PRIORITY_LOW,
+ PRIORITY_NORMAL,
+ PRIORITY_HIGH
+ };
+
+ struct Settings {
+
+ Priority priority;
+ Settings() { priority=PRIORITY_NORMAL; }
+ };
+
+
+
+ typedef uint64_t ID;
+
+protected:
+ static Thread* (*create_func)(ThreadCreateCallback p_callback,void *,const Settings&);
+ static ID (*get_thread_ID_func)();
+ static void (*wait_to_finish_func)(Thread*);
+
+ friend class Main;
+
+ static ID _main_thread_id;
+
+
+ Thread();
+public:
+
+
+
+ virtual ID get_ID() const=0;
+
+ _FORCE_INLINE_ static ID get_main_ID() { return _main_thread_id; } ///< get the ID of the main thread
+ static ID get_caller_ID(); ///< get the ID of the caller function ID
+ static void wait_to_finish(Thread *p_thread); ///< waits until thread is finished, and deallocates it.
+ static Thread * create(ThreadCreateCallback p_callback,void * p_user,const Settings& p_settings=Settings()); ///< Static function to create a thread, will call p_callback
+
+
+ virtual ~Thread();
+
+};
+
+#endif
+
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
new file mode 100644
index 0000000000..1974bf615b
--- /dev/null
+++ b/core/os/thread_dummy.cpp
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* thread_dummy.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 "thread_dummy.h"
+
+#include "memory.h"
+
+Thread* ThreadDummy::create(ThreadCreateCallback p_callback,void * p_user,const Thread::Settings& p_settings) {
+ return memnew(ThreadDummy);
+};
+
+void ThreadDummy::make_default() {
+ Thread::create_func = &ThreadDummy::create;
+};
+
+Mutex* MutexDummy::create(bool p_recursive) {
+ return memnew(MutexDummy);
+};
+
+void MutexDummy::make_default() {
+ Mutex::create_func = &MutexDummy::create;
+};
+
+
+Semaphore* SemaphoreDummy::create() {
+ return memnew(SemaphoreDummy);
+};
+
+void SemaphoreDummy::make_default() {
+ Semaphore::create_func = &SemaphoreDummy::create;
+};
+
+
+
diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h
new file mode 100644
index 0000000000..b681005fb6
--- /dev/null
+++ b/core/os/thread_dummy.h
@@ -0,0 +1,72 @@
+/*************************************************************************/
+/* thread_dummy.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 THREAD_DUMMY_H
+#define THREAD_DUMMY_H
+
+#include "thread.h"
+#include "mutex.h"
+#include "semaphore.h"
+
+class ThreadDummy : public Thread {
+
+ static Thread* create(ThreadCreateCallback p_callback,void * p_user,const Settings& p_settings=Settings());
+
+public:
+ virtual ID get_ID() const { return 0; };
+
+ static void make_default();
+};
+
+class MutexDummy : public Mutex {
+
+ static Mutex* create(bool p_recursive);
+
+public:
+
+ virtual void lock() {};
+ virtual void unlock() {};
+ virtual Error try_lock() { return OK; };
+
+ static void make_default();
+};
+
+class SemaphoreDummy : public Semaphore {
+
+ static Semaphore* create();
+
+public:
+ virtual Error wait() { return OK; };
+ virtual Error post() { return OK; };
+ virtual int get() const { return 0; }; ///< get semaphore value
+
+ static void make_default();
+
+};
+
+#endif
diff --git a/core/os/thread_safe.cpp b/core/os/thread_safe.cpp
new file mode 100644
index 0000000000..9c7648be94
--- /dev/null
+++ b/core/os/thread_safe.cpp
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* thread_safe.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 "thread_safe.h"
+#include "error_macros.h"
+#include "os/memory.h"
+
+ThreadSafe::ThreadSafe() {
+
+ mutex = Mutex::create();
+ if (!mutex) {
+
+ WARN_PRINT("THREAD_SAFE defined, but no default mutex type");
+ }
+}
+
+ThreadSafe::~ThreadSafe() {
+
+ if (mutex)
+ memdelete( mutex );
+}
diff --git a/core/os/thread_safe.h b/core/os/thread_safe.h
new file mode 100644
index 0000000000..8b20c31cc9
--- /dev/null
+++ b/core/os/thread_safe.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* thread_safe.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 THREAD_SAFE_H
+#define THREAD_SAFE_H
+
+
+#include "os/mutex.h"
+
+class ThreadSafe {
+
+ Mutex *mutex;
+public:
+
+ inline void lock() const { if (mutex) mutex->lock(); }
+ inline void unlock() const { if (mutex) mutex->unlock(); }
+
+ ThreadSafe();
+ ~ThreadSafe();
+
+};
+
+
+class ThreadSafeMethod {
+
+ const ThreadSafe *_ts;
+public:
+ ThreadSafeMethod(const ThreadSafe *p_ts) {
+
+ _ts=p_ts;
+ _ts->lock();
+ }
+
+ ~ThreadSafeMethod() { _ts->unlock(); }
+};
+
+
+#ifndef NO_THREADS
+
+#define _THREAD_SAFE_CLASS_ ThreadSafe __thread__safe__;
+#define _THREAD_SAFE_METHOD_ ThreadSafeMethod __thread_safe_method__(&__thread__safe__);
+#define _THREAD_SAFE_LOCK_ __thread__safe__.lock();
+#define _THREAD_SAFE_UNLOCK_ __thread__safe__.unlock();
+
+#else
+
+#define _THREAD_SAFE_CLASS_
+#define _THREAD_SAFE_METHOD_
+#define _THREAD_SAFE_LOCK_
+#define _THREAD_SAFE_UNLOCK_
+
+#endif
+
+
+
+
+#endif