Переглянути джерело

Merge branch 'master' into audio

Conflicts:
	engine/CMakeLists.txt
	engine/compilers/BundleCompiler.cpp
	engine/compilers/BundleCompiler.h
mikymod 12 роки тому
батько
коміт
785075e692
64 змінених файлів з 2368 додано та 770 видалено
  1. 2 3
      engine/Android.mk
  2. 14 5
      engine/CMakeLists.txt
  3. 102 20
      engine/Device.cpp
  4. 27 0
      engine/Device.h
  5. 94 0
      engine/EventBuffer.cpp
  6. 75 0
      engine/EventBuffer.h
  7. 23 12
      engine/compilers/BundleCompiler.cpp
  8. 2 0
      engine/compilers/BundleCompiler.h
  9. 17 2
      engine/compilers/lua/LuaCompiler.cpp
  10. 139 0
      engine/compilers/package/PackageCompiler.cpp
  11. 25 29
      engine/compilers/package/PackageCompiler.h
  12. 26 12
      engine/core/json/JSONParser.cpp
  13. 5 2
      engine/core/json/JSONParser.h
  14. 1 0
      engine/core/strings/StringStream.h
  15. 38 31
      engine/input/InputManager.cpp
  16. 29 4
      engine/lua/LuaDevice.cpp
  17. 57 135
      engine/lua/LuaEnvironment.cpp
  18. 13 19
      engine/lua/LuaEnvironment.h
  19. 87 0
      engine/lua/LuaResourcePackage.cpp
  20. 5 39
      engine/os/OS.cpp
  21. 8 38
      engine/os/OS.h
  22. 88 0
      engine/os/OsEvents.h
  23. 46 6
      engine/os/android/AndroidDevice.cpp
  24. 38 18
      engine/os/android/AndroidOS.cpp
  25. 2 2
      engine/os/android/ApkFilesystem.cpp
  26. 2 2
      engine/os/android/Config.h
  27. 18 21
      engine/os/android/OsWindow.cpp
  28. 1 2
      engine/os/android/OsWindow.h
  29. 12 40
      engine/os/android/java/CrownActivity.java
  30. 0 0
      engine/os/android/java/CrownEnum.java
  31. 19 10
      engine/os/android/java/CrownLib.java
  32. 31 23
      engine/os/android/java/CrownMainThread.java
  33. 2 2
      engine/os/android/java/CrownSensor.java
  34. 61 17
      engine/os/android/java/CrownSurfaceView.java
  35. 4 5
      engine/os/android/java/CrownTouch.java
  36. 24 0
      engine/os/linux/LinuxOS.cpp
  37. 19 18
      engine/os/linux/OsWindow.cpp
  38. 35 4
      engine/os/linux/main.cpp
  39. 35 0
      engine/os/posix/Cond.h
  40. 36 0
      engine/os/posix/Mutex.h
  41. 56 12
      engine/os/posix/Semaphore.h
  42. 0 125
      engine/os/posix/Thread.cpp
  43. 113 45
      engine/os/posix/Thread.h
  44. 51 5
      engine/os/win/Thread.cpp
  45. 19 2
      engine/os/win/Thread.h
  46. 90 9
      engine/os/win/WinOS.cpp
  47. 305 0
      engine/os/win/inttypes.h
  48. 5 6
      engine/renderers/gles/GLESRenderer.cpp
  49. 72 32
      engine/renderers/gles/egl/GLContext.cpp
  50. 4 7
      engine/renderers/gles/egl/GLContext.h
  51. 1 0
      engine/resource/FileBundle.cpp
  52. 0 1
      engine/resource/LuaResource.h
  53. 122 0
      engine/resource/PackageResource.h
  54. 2 0
      engine/resource/Resource.h
  55. 2 2
      engine/resource/ResourceLoader.cpp
  56. 21 1
      engine/resource/ResourceLoader.h
  57. 1 0
      engine/resource/ResourceManager.h
  58. 107 0
      engine/resource/ResourcePackage.h
  59. 2 0
      engine/resource/ResourceRegistry.cpp
  60. 6 1
      engine/tests/CMakeLists.txt
  61. 90 0
      engine/tests/events.cpp
  62. 31 0
      engine/tests/threads.cpp
  63. 5 0
      samples/01.hello-world/crown.config
  64. 1 1
      utils/crown-android.rb

+ 2 - 3
engine/Android.mk

@@ -69,9 +69,6 @@ LOCAL_SRC_FILES :=\
 	os/android/ApkFile.cpp\
 	os/android/ApkFile.cpp\
 	os/android/ApkFilesystem.cpp\
 	os/android/ApkFilesystem.cpp\
 	os/posix/OsFile.cpp\
 	os/posix/OsFile.cpp\
-	os/posix/Thread.cpp\
-	os/posix/Mutex.cpp\
-	os/posix/Cond.cpp\
 	os/posix/TCPSocket.cpp\
 	os/posix/TCPSocket.cpp\
 	os/posix/UDPSocket.cpp\
 	os/posix/UDPSocket.cpp\
 \
 \
@@ -104,11 +101,13 @@ LOCAL_SRC_FILES :=\
 	lua/LuaIntSetting.cpp\
 	lua/LuaIntSetting.cpp\
 	lua/LuaFloatSetting.cpp\
 	lua/LuaFloatSetting.cpp\
 	lua/LuaStringSetting.cpp\
 	lua/LuaStringSetting.cpp\
+	lua/LuaResourcePackage.cpp\
 \
 \
 	Camera.cpp\
 	Camera.cpp\
 	Device.cpp\
 	Device.cpp\
 	FPSSystem.cpp\
 	FPSSystem.cpp\
 	ConsoleServer.cpp\
 	ConsoleServer.cpp\
+	EventBuffer.cpp\
 \
 \
 
 
 LOCAL_C_INCLUDES	:=\
 LOCAL_C_INCLUDES	:=\

+ 14 - 5
engine/CMakeLists.txt

@@ -61,11 +61,13 @@ set (CROWN_INCLUDES
 	${CMAKE_SOURCE_DIR}/engine/compilers/texture
 	${CMAKE_SOURCE_DIR}/engine/compilers/texture
 	${CMAKE_SOURCE_DIR}/engine/compilers/sound
 	${CMAKE_SOURCE_DIR}/engine/compilers/sound
 	${CMAKE_SOURCE_DIR}/engine/compilers/mesh
 	${CMAKE_SOURCE_DIR}/engine/compilers/mesh
+	${CMAKE_SOURCE_DIR}/engine/compilers/package
 )
 )
 
 
 set (SRC
 set (SRC
 	Camera.cpp
 	Camera.cpp
 	Device.cpp
 	Device.cpp
+	EventBuffer.cpp
 	ConsoleServer.cpp
 	ConsoleServer.cpp
 	FPSSystem.cpp
 	FPSSystem.cpp
 )
 )
@@ -75,6 +77,7 @@ set (HEADERS
 	Config.h
 	Config.h
 	Crown.h
 	Crown.h
 	Device.h
 	Device.h
+	EventBuffer.h
 	ConsoleServer.h
 	ConsoleServer.h
 	FPSSystem.h
 	FPSSystem.h
 )
 )
@@ -285,7 +288,6 @@ else ()
 endif (CROWN_DEBUG OR CROWN_DEVELOPMENT)
 endif (CROWN_DEBUG OR CROWN_DEVELOPMENT)
 
 
 set (RESOURCE_HEADERS
 set (RESOURCE_HEADERS
-
 	resource/Resource.h
 	resource/Resource.h
 	resource/ResourceFormat.h
 	resource/ResourceFormat.h
 	resource/ResourceLoader.h
 	resource/ResourceLoader.h
@@ -298,6 +300,8 @@ set (RESOURCE_HEADERS
 	resource/FontResource.h
 	resource/FontResource.h
 	resource/SoundResource.h
 	resource/SoundResource.h
 	resource/MaterialResource.h
 	resource/MaterialResource.h
+	resource/PackageResource.h
+	resource/ResourcePackage.h
 )
 )
 
 
 set (OS_SRC
 set (OS_SRC
@@ -307,6 +311,7 @@ set (OS_SRC
 set (OS_HEADERS
 set (OS_HEADERS
 	os/OS.h
 	os/OS.h
 	os/NetAddress.h
 	os/NetAddress.h
+	os/OsEvents.h
 )
 )
 
 
 set (LUA_SRC
 set (LUA_SRC
@@ -325,6 +330,7 @@ set (LUA_SRC
 	lua/LuaAccelerometer.cpp
 	lua/LuaAccelerometer.cpp
 	lua/LuaDevice.cpp
 	lua/LuaDevice.cpp
 	lua/LuaWindow.cpp
 	lua/LuaWindow.cpp
+	lua/LuaResourcePackage.cpp
 )
 )
 
 
 set (LUA_HEADERS
 set (LUA_HEADERS
@@ -338,6 +344,7 @@ set (COMPILER_SRC
 	compilers/lua/LuaCompiler.cpp
 	compilers/lua/LuaCompiler.cpp
 	compilers/texture/TextureCompiler.cpp
 	compilers/texture/TextureCompiler.cpp
 	compilers/sound/SoundCompiler.cpp
 	compilers/sound/SoundCompiler.cpp
+	compilers/package/PackageCompiler.cpp
 )
 )
 
 
 set (COMPILER_HEADER
 set (COMPILER_HEADER
@@ -346,6 +353,7 @@ set (COMPILER_HEADER
 	compilers/lua/LuaCompiler.h
 	compilers/lua/LuaCompiler.h
 	compilers/texture/TextureCompiler.h
 	compilers/texture/TextureCompiler.h
 	compilers/sound/SoundCompiler.h
 	compilers/sound/SoundCompiler.h
+	compilers/package/PackageCompiler.h
 )
 )
 
 
 set (CROWN_LIBRARIES)
 set (CROWN_LIBRARIES)
@@ -366,6 +374,7 @@ if (LINUX)
 		os/linux/Thread.h
 		os/linux/Thread.h
 		os/linux/Mutex.h
 		os/linux/Mutex.h
 		os/linux/Cond.h
 		os/linux/Cond.h
+		os/posix/Semaphore.h
 	)
 	)
 
 
 	list (APPEND OS_SRC
 	list (APPEND OS_SRC
@@ -374,9 +383,6 @@ if (LINUX)
 		os/posix/TCPSocket.cpp
 		os/posix/TCPSocket.cpp
 		os/posix/UDPSocket.cpp	
 		os/posix/UDPSocket.cpp	
 		os/posix/OsFile.cpp
 		os/posix/OsFile.cpp
-		os/posix/Thread.cpp
-		os/posix/Mutex.cpp
-		os/posix/Cond.cpp
 	)
 	)
 
 
 	list (APPEND RENDERERS_SRC
 	list (APPEND RENDERERS_SRC
@@ -451,6 +457,7 @@ if (WINDOWS)
 		os/win/Thread.h
 		os/win/Thread.h
 		os/win/Mutex.h
 		os/win/Mutex.h
 		os/win/Cond.h
 		os/win/Cond.h
+		os/win/inttypes.h
 	)
 	)
 
 
 	list (APPEND OS_SRC
 	list (APPEND OS_SRC
@@ -481,7 +488,9 @@ if (WINDOWS)
 		lua51
 		lua51
 	)
 	)
 
 
-	set (COMPILER_FLAGS)
+	set (COMPILER_FLAGS
+		/Wall
+	)
 
 
 	set (CROWN_MAIN_SRC os/win/main.cpp)
 	set (CROWN_MAIN_SRC os/win/main.cpp)
 endif(WINDOWS)
 endif(WINDOWS)

+ 102 - 20
engine/Device.cpp

@@ -54,6 +54,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Types.h"
 #include "Bundle.h"
 #include "Bundle.h"
 #include "TempAllocator.h"
 #include "TempAllocator.h"
+#include "ResourcePackage.h"
+#include "EventBuffer.h"
 
 
 #if defined(LINUX) || defined(WINDOWS)
 #if defined(LINUX) || defined(WINDOWS)
 	#include "BundleCompiler.h"
 	#include "BundleCompiler.h"
@@ -81,6 +83,8 @@ Device::Device() :
 
 
 	m_is_init(false),
 	m_is_init(false),
 	m_is_running(false),
 	m_is_running(false),
+	m_is_paused(false),
+	m_is_really_paused(false),
 
 
 	m_frame_count(0),
 	m_frame_count(0),
 
 
@@ -97,7 +101,9 @@ Device::Device() :
 	m_resource_manager(NULL),
 	m_resource_manager(NULL),
 	m_resource_bundle(NULL),
 	m_resource_bundle(NULL),
 
 
-	m_console_server(NULL)
+	m_console_server(NULL),
+
+	m_renderer_init_request(false)
 {
 {
 	// Bundle dir is current dir by default.
 	// Bundle dir is current dir by default.
 	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
 	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
@@ -140,6 +146,14 @@ bool Device::init(int argc, char** argv)
 		}
 		}
 	#endif
 	#endif
 
 
+	init();
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+void Device::init()
+{
 	// Initialize
 	// Initialize
 	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);
 	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);
 
 
@@ -176,7 +190,8 @@ bool Device::init(int argc, char** argv)
 	m_input_manager = CE_NEW(m_allocator, InputManager)();
 	m_input_manager = CE_NEW(m_allocator, InputManager)();
 	Log::d("Input manager created.");
 	Log::d("Input manager created.");
 
 
-	m_window = CE_NEW(m_allocator, OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
+	// default_allocator, maybe it needs fix
+	m_window = CE_NEW(default_allocator(), OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
 
 
 	CE_ASSERT(m_window != NULL, "Unable to create the window");
 	CE_ASSERT(m_window != NULL, "Unable to create the window");
 
 
@@ -187,6 +202,7 @@ bool Device::init(int argc, char** argv)
 	// Create renderer
 	// Create renderer
 	m_renderer = Renderer::create(m_allocator);
 	m_renderer = Renderer::create(m_allocator);
 	m_renderer->init();
 	m_renderer->init();
+	m_renderer_init_request = false;
 	Log::d("Renderer created.");
 	Log::d("Renderer created.");
 
 
 	// Create debug renderer
 	// Create debug renderer
@@ -203,22 +219,27 @@ bool Device::init(int argc, char** argv)
 	m_is_init = true;
 	m_is_init = true;
 	start();
 	start();
 
 
-	ResourceId luagame_id = m_resource_manager->load("lua", m_boot_file);
-	m_resource_manager->flush();
-	m_lua_environment->load((LuaResource*) m_resource_manager->data(luagame_id));
-	m_lua_environment->call_global("init", 0);
-	m_resource_manager->unload(luagame_id);
-
-	if (m_quit_after_init == 1)
+	// Execute lua boot file
+	if (m_lua_environment->load_and_execute(m_boot_file))
 	{
 	{
-		stop();
-		shutdown();
+		if (!m_lua_environment->call_global("init", 0))
+		{
+			pause();
+		}
+	}
+	else
+	{
+		pause();
 	}
 	}
 
 
 	// Show main window
 	// Show main window
 	m_window->show();
 	m_window->show();
 
 
-	return true;
+	if (m_quit_after_init == 1)
+	{
+		stop();
+		shutdown();
+	}
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -269,7 +290,7 @@ void Device::shutdown()
 	Log::i("Releasing Window...");
 	Log::i("Releasing Window...");
 	if (m_window)
 	if (m_window)
 	{
 	{
-		CE_DELETE(m_allocator, m_window);
+		CE_DELETE(default_allocator(), m_window);
 	}
 	}
 
 
 	Log::i("Releasing ResourceManager...");
 	Log::i("Releasing ResourceManager...");
@@ -289,6 +310,14 @@ void Device::shutdown()
 		CE_DELETE(m_allocator, m_filesystem);
 		CE_DELETE(m_allocator, m_filesystem);
 	}
 	}
 
 
+	#if (defined(LINUX) || defined(WINDOWS)) && (defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT))
+		Log::i("Releasing BundleCompiler...");
+		if (m_bundle_compiler)
+		{
+			CE_DELETE(m_allocator, m_bundle_compiler);
+		}
+	#endif
+
 	m_allocator.clear();
 	m_allocator.clear();
 
 
 	m_is_init = false;
 	m_is_init = false;
@@ -300,6 +329,12 @@ bool Device::is_init() const
 	return m_is_init;
 	return m_is_init;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+bool Device::is_paused() const
+{
+	return m_is_paused;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 Filesystem* Device::filesystem()
 Filesystem* Device::filesystem()
 {
 {
@@ -389,6 +424,23 @@ void Device::stop()
 	m_is_running = false;
 	m_is_running = false;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+void Device::pause()
+{
+	m_is_paused = true;
+
+	Log::d("Engine paused");
+}
+
+//-----------------------------------------------------------------------------
+void Device::unpause()
+{
+	m_is_paused = false;
+	m_is_really_paused = false;
+
+	Log::d("Engine unpaused");
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool Device::is_running() const
 bool Device::is_running() const
 {
 {
@@ -414,18 +466,48 @@ void Device::frame()
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	m_last_time = m_current_time;
 	m_last_time = m_current_time;
 
 
-	m_resource_manager->poll_resource_loader();
+	if (!m_is_paused)
+	{
+		m_resource_manager->poll_resource_loader();
 
 
-	m_window->frame();
-	m_input_manager->frame(frame_count());
-	m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time());
+		m_window->frame();
+		m_input_manager->frame(frame_count());
 
 
-	// m_console_server->execute();
+		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
+		{
+			pause();
+		}
 
 
-	m_debug_renderer->draw_all();
-	m_renderer->frame();
+		m_debug_renderer->draw_all();
+		m_renderer->frame();
+	}
 
 
 	m_frame_count++;
 	m_frame_count++;
+
+	os_event_buffer()->clear();
+}
+
+//-----------------------------------------------------------------------------
+ResourcePackage* Device::create_resource_package(const char* name)
+{
+	CE_ASSERT_NOT_NULL(name);
+
+	ResourceId package_id = m_resource_manager->load("package", name);
+	m_resource_manager->flush();
+
+	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
+	ResourcePackage* package = CE_NEW(m_allocator, ResourcePackage)(*m_resource_manager, package_id, package_res);
+
+	return package;
+}
+
+//-----------------------------------------------------------------------------
+void Device::destroy_resource_package(ResourcePackage* package)
+{
+	CE_ASSERT_NOT_NULL(package);
+
+	m_resource_manager->unload(package->resource_id());
+	CE_DELETE(m_allocator, package);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 27 - 0
engine/Device.h

@@ -51,6 +51,7 @@ class Accelerometer;
 class LuaEnvironment;
 class LuaEnvironment;
 class ConsoleServer;
 class ConsoleServer;
 class BundleCompiler;
 class BundleCompiler;
+class ResourcePackage;
 
 
 /// The Engine.
 /// The Engine.
 /// It is the place where to look for accessing all of
 /// It is the place where to look for accessing all of
@@ -76,6 +77,9 @@ public:
 	/// Returns whether the engine is correctly initialized
 	/// Returns whether the engine is correctly initialized
 	bool					is_init() const;
 	bool					is_init() const;
 
 
+	/// Returns wheter the engine is paused
+	bool 					is_paused() const;
+
 	/// Return the number of frames rendered from the first
 	/// Return the number of frames rendered from the first
 	/// call to Device::start()
 	/// call to Device::start()
 	uint64_t				frame_count() const;
 	uint64_t				frame_count() const;
@@ -91,9 +95,24 @@ public:
 	/// and normally terminates the program.
 	/// and normally terminates the program.
 	void					stop();
 	void					stop();
 
 
+	/// Pauses the engine
+	void					pause();
+
+	/// Unpauses the engine
+	void					unpause();
+
 	/// Updates all the subsystems
 	/// Updates all the subsystems
 	void					frame();
 	void					frame();
 
 
+	/// Returns the resource package with the given @a package_name name.
+	ResourcePackage*		create_resource_package(const char* name);
+
+	/// Destroy a previously created resource @a package.
+	/// @note
+	/// To unload the resources loaded by the package, you have to call
+	/// ResourcePackage::unload() first.
+	void					destroy_resource_package(ResourcePackage* package);
+
 	void					compile(const char* bundle_dir, const char* source_dir, const char* resource);
 	void					compile(const char* bundle_dir, const char* source_dir, const char* resource);
 
 
 	void					reload(ResourceId name);
 	void					reload(ResourceId name);
@@ -116,6 +135,7 @@ public:
 	
 	
 private:
 private:
 
 
+	void					init();
 	void					parse_command_line(int argc, char** argv);
 	void					parse_command_line(int argc, char** argv);
 	void					check_preferred_settings();
 	void					check_preferred_settings();
 	void					read_engine_settings();
 	void					read_engine_settings();
@@ -142,6 +162,9 @@ private:
 
 
 	bool					m_is_init		: 1;
 	bool					m_is_init		: 1;
 	bool					m_is_running	: 1;
 	bool					m_is_running	: 1;
+	bool					m_is_paused		: 1;
+
+	bool 					m_is_really_paused :1;
 
 
 	uint64_t				m_frame_count;
 	uint64_t				m_frame_count;
 
 
@@ -166,11 +189,15 @@ private:
 	// Debug subsystems
 	// Debug subsystems
 	ConsoleServer*			m_console_server;
 	ConsoleServer*			m_console_server;
 
 
+	bool 					m_renderer_init_request;
+
 private:
 private:
 
 
 	// Disable copying
 	// Disable copying
 	Device(const Device&);
 	Device(const Device&);
 	Device& operator=(const Device&);
 	Device& operator=(const Device&);
+
+	friend class MainThread;
 };
 };
 
 
 CE_EXPORT Device* device();
 CE_EXPORT Device* device();

+ 94 - 0
engine/EventBuffer.cpp

@@ -0,0 +1,94 @@
+#include "EventBuffer.h"
+#include "Log.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+EventBuffer::EventBuffer() : m_size(0), m_read(0)
+{
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::push_event(uint32_t event_type, void* event_data, size_t event_size)
+{
+	if (m_size + sizeof(event_type) + sizeof(event_size) + event_size > MAX_OS_EVENT_BUFFER_SIZE)
+	{
+		flush();
+	}
+
+	char* cur = m_buffer + m_size;
+
+	*(uint32_t*) cur = event_type;
+	*(size_t*) (cur + sizeof(event_type)) = event_size;
+	memcpy(cur + sizeof(event_type) + sizeof(event_size), event_data, event_size);
+
+	m_size += sizeof(event_type) + sizeof(event_size) + event_size;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::push_event_buffer(char* event_buffer, size_t buffer_size)
+{
+	if (m_size + buffer_size > MAX_OS_EVENT_BUFFER_SIZE)
+	{
+		flush();
+	}
+
+	char* cur = m_buffer + m_size;
+
+	memcpy(cur, event_buffer, buffer_size);
+
+	m_size += buffer_size;
+}
+
+
+//-----------------------------------------------------------------------------
+void* EventBuffer::get_next_event(uint32_t& event_type, size_t& event_size)
+{
+	if (m_read < m_size)
+	{
+		char* cur = m_buffer + m_read;
+
+		// Saves type
+		event_type = *(uint32_t*) cur;
+		// Saves size
+		event_size = *(size_t*)(cur + sizeof(uint32_t));
+
+		// Set read to next event
+		m_read += sizeof(size_t) + sizeof(uint32_t) + event_size;
+
+		return cur + sizeof(size_t) + sizeof(uint32_t);
+	}
+
+	m_read = 0;
+
+	return NULL;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::clear()
+{
+	m_size = 0;
+	m_read = 0;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::flush()
+{
+	m_size = 0;
+	m_read = 0;
+}
+
+//-----------------------------------------------------------------------------
+size_t EventBuffer::size() const
+{
+	return m_size;
+}
+
+//-----------------------------------------------------------------------------
+char* EventBuffer::buffer()
+{
+	return m_buffer;
+}
+
+} // namespace crown

+ 75 - 0
engine/EventBuffer.h

@@ -0,0 +1,75 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include <cstring>
+
+#include "Types.h"
+
+#define MAX_OS_EVENT_BUFFER_SIZE 1024
+
+namespace crown
+{
+
+
+///	__EventBuffer__ is a global buffer used for storing events.
+///	Each subsystem can read its relative events and modifies its behaviour consequently.
+///
+/// [type #0][size #0][data #0] ... [type #n][size #n][data #n]
+class EventBuffer
+{
+
+public:
+	/// Constructor
+				EventBuffer();
+
+	/// Pushes an @a event_data of size @a event_size with type @a event_type 
+	void		push_event(uint32_t event_type, void* event_data, size_t event_size);
+	/// Pushes an entire @a event_buffer of size @a buffer_size
+	void		push_event_buffer(char* event_buffer, size_t buffer_size);
+	/// Retrieves the @a event_type and @a event_size of next os event
+	void*		get_next_event(uint32_t& event_type, size_t& event_size);
+
+	/// Clears entire os buffer
+	void		clear();
+	/// Flushes entire os buffer
+	void		flush();
+
+	/// Returns buffer's size
+	size_t		size() const;
+	/// Return buffer
+	char*		buffer();
+
+public:
+
+	size_t		m_size;
+	char		m_buffer[MAX_OS_EVENT_BUFFER_SIZE];
+
+	uint32_t	m_read;
+};
+
+} // namespace crown

+ 23 - 12
engine/compilers/BundleCompiler.cpp

@@ -57,9 +57,24 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		temp.create_directory(bundle_dir);
 		temp.create_directory(bundle_dir);
 	}
 	}
 
 
+	// Copy crown.config to bundle dir
 	DiskFilesystem src_fs(source_dir);
 	DiskFilesystem src_fs(source_dir);
 	DiskFilesystem dst_fs(bundle_dir);
 	DiskFilesystem dst_fs(bundle_dir);
 
 
+	if (src_fs.is_file("crown.config"))
+	{
+		File* src = src_fs.open("crown.config", FOM_READ);
+		File* dst = dst_fs.open("crown.config", FOM_WRITE);
+		src->copy_to(*dst, src->size());
+		src_fs.close(src);
+		dst_fs.close(dst);
+	}
+	else
+	{
+		Log::d("'crown.config' does not exist.");
+		return false;
+	}
+
 	// Compile all resources
 	// Compile all resources
 	for (uint32_t i = 0; i < files.size(); i++)
 	for (uint32_t i = 0; i < files.size(); i++)
 	{
 	{
@@ -71,23 +86,15 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		path::extension(filename, filename_extension, 32);
 		path::extension(filename, filename_extension, 32);
 		uint32_t resource_type_hash = hash::murmur2_32(filename_extension, string::strlen(filename_extension), 0);
 		uint32_t resource_type_hash = hash::murmur2_32(filename_extension, string::strlen(filename_extension), 0);
 
 
-		// Do not compile if curr resource is a config file
+		char out_name[65];
+		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
+
+		// Skip crown.config file
 		if (resource_type_hash == CONFIG_TYPE)
 		if (resource_type_hash == CONFIG_TYPE)
 		{
 		{
-			File* src = src_fs.open(filename, FOM_READ);
-			File* dst = dst_fs.open(filename, FOM_WRITE);
-
-			src->copy_to(*dst, src->size());
-
-			src_fs.close(src);
-			dst_fs.close(dst);
-
 			continue;
 			continue;
 		}
 		}
 
 
-		char out_name[65];
-		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
-
 		Log::i("%s <= %s", out_name, filename);
 		Log::i("%s <= %s", out_name, filename);
 
 
 		bool result = false;
 		bool result = false;
@@ -103,6 +110,10 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		{
 		{
 			result = m_sound.compile(source_dir, bundle_dir, filename, out_name);
 			result = m_sound.compile(source_dir, bundle_dir, filename, out_name);
 		}
 		}
+		else if (resource_type_hash == PACKAGE_TYPE)
+		{
+			result = m_package.compile(source_dir, bundle_dir, filename, out_name);
+		}
 		else
 		else
 		{
 		{
 			Log::e("Oops, unknown resource type!");
 			Log::e("Oops, unknown resource type!");

+ 2 - 0
engine/compilers/BundleCompiler.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "TextureCompiler.h"
 #include "TextureCompiler.h"
 #include "LuaCompiler.h"
 #include "LuaCompiler.h"
 #include "SoundCompiler.h"
 #include "SoundCompiler.h"
+#include "PackageCompiler.h"
 #include "DynamicString.h"
 #include "DynamicString.h"
 #include "Vector.h"
 #include "Vector.h"
 #include "DiskFilesystem.h"
 #include "DiskFilesystem.h"
@@ -53,6 +54,7 @@ private:
 	TextureCompiler	m_texture;
 	TextureCompiler	m_texture;
 	LuaCompiler 	m_lua;
 	LuaCompiler 	m_lua;
 	SoundCompiler	m_sound;
 	SoundCompiler	m_sound;
+	PackageCompiler m_package;
 };
 };
 
 
 } // namespace crown
 } // namespace crown

+ 17 - 2
engine/compilers/lua/LuaCompiler.cpp

@@ -24,6 +24,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
+#include "Config.h"
 #include "LuaCompiler.h"
 #include "LuaCompiler.h"
 #include "LuaResource.h"
 #include "LuaResource.h"
 #include "TempAllocator.h"
 #include "TempAllocator.h"
@@ -34,6 +35,20 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 namespace crown
 {
 {
 
 
+#ifdef WINDOWS
+	#define LUAJIT_EXECUTABLE "luajit.exe"
+#else
+	#define LUAJIT_EXECUTABLE "./luajit"
+#endif
+
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+	#define LUAJIT_FLAGS "-bg" // Keep debug info
+#else
+	#define LUAJIT_FLAGS "-b"
+#endif
+
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 LuaCompiler::LuaCompiler()
 LuaCompiler::LuaCompiler()
 	: m_luajit_blob_size(0), m_luajit_blob(NULL)
 	: m_luajit_blob_size(0), m_luajit_blob(NULL)
@@ -57,8 +72,8 @@ size_t LuaCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 
 
 	const char* luajit[] =
 	const char* luajit[] =
 	{
 	{
-		"./luajit",
-		"-b",
+		LUAJIT_EXECUTABLE,
+		LUAJIT_FLAGS,
 		res_abs_path.c_str(),
 		res_abs_path.c_str(),
 		bc_abs_path.c_str(),
 		bc_abs_path.c_str(),
 		NULL
 		NULL

+ 139 - 0
engine/compilers/package/PackageCompiler.cpp

@@ -0,0 +1,139 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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 "Allocator.h"
+#include "File.h"
+#include "Filesystem.h"
+#include "Hash.h"
+#include "JSONParser.h"
+#include "PackageCompiler.h"
+#include "PackageResource.h"
+#include "TempAllocator.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+PackageCompiler::PackageCompiler()
+	: m_has_texture(false), m_has_lua(false), m_textures(default_allocator()), m_scripts(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t PackageCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+
+	char file_buf[4096];
+	file->read(file_buf, file->size());
+	fs.close(file);
+
+	JSONParser json(file_buf);
+	JSONElement root = json.root();
+
+	// Check for resource types
+	if (root.has_key("texture"))
+	{
+		JSONElement texture_array = root.key("texture");
+		uint32_t texture_array_size = texture_array.size();
+
+		for (uint32_t i = 0; i < texture_array_size; i++)
+		{
+			TempAllocator256 alloc;
+			DynamicString texture_name(alloc);
+			texture_name += texture_array[i].string_value();
+			texture_name += ".texture";
+
+			if (!fs.is_file(texture_name.c_str()))
+			{
+				Log::e("Texture '%s' does not exist.", texture_name.c_str());
+				return 0;
+			}
+
+			ResourceId id;
+			id.id = hash::murmur2_64(texture_name.c_str(), string::strlen(texture_name.c_str()), 0);
+			m_textures.push_back(id);
+		}
+	}
+
+	// Check for scripts
+	if (root.has_key("lua"))
+	{
+		JSONElement lua_array = root.key("lua");
+		//lua_array = root.key("lua");
+		uint32_t lua_array_size = lua_array.size();
+
+		for (uint32_t i = 0; i < lua_array_size; i++)
+		{
+			TempAllocator256 alloc;
+			DynamicString lua_name(alloc);
+			lua_name += lua_array[i].string_value();
+			lua_name += ".lua";
+
+			if (!fs.is_file(lua_name.c_str()))
+			{
+				Log::e("Lua script '%s' does not exist.", lua_name.c_str());
+				return 0;
+			}
+
+			ResourceId id;
+			id.id = hash::murmur2_64(lua_name.c_str(), string::strlen(lua_name.c_str()), 0);
+			m_scripts.push_back(id);
+		}
+	}
+
+	return sizeof(PackageHeader) +
+			m_textures.size() * sizeof(ResourceId) +
+			m_scripts.size() * sizeof(ResourceId);
+}
+
+//-----------------------------------------------------------------------------
+void PackageCompiler::write_impl(File* out_file)
+{
+	PackageHeader header;
+	header.num_textures = m_textures.size();
+	header.num_scripts = m_scripts.size();
+
+	header.textures_offset = sizeof(PackageHeader);
+	header.scripts_offset  = header.textures_offset + sizeof(ResourceId) * header.num_textures;
+
+	out_file->write((char*) &header, sizeof(PackageHeader));
+
+	if (m_textures.size() > 0)
+	{
+		out_file->write((char*) m_textures.begin(), sizeof(ResourceId) * header.num_textures);		
+	}
+	if (m_scripts.size() > 0)
+	{
+		out_file->write((char*) m_scripts.begin(), sizeof(ResourceId) * header.num_scripts);
+	}
+
+	// Cleanup
+	m_textures.clear();
+	m_scripts.clear();
+}
+
+} // namespace crown

+ 25 - 29
engine/os/android/MainThread.java → engine/compilers/package/PackageCompiler.h

@@ -24,35 +24,31 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
-package crown.android;
+#pragma once
 
 
-import android.view.SurfaceHolder;
+#include "Compiler.h"
+#include "Resource.h"
+#include "List.h"
 
 
-public class MainThread extends Thread
+namespace crown
 {
 {
-	private SurfaceHolder mHolder;
-	private CrownSurfaceView mView;
-
-	public MainThread(SurfaceHolder holder, CrownSurfaceView view)
-	{
-		super();
-
-		mHolder = holder;
-		mView = view;
-	}
-
-	// This is the classic main() replacement for Android
-	@Override
-	public void run()
-	{
-		CrownLib.setWindow(mHolder.getSurface());
-		CrownLib.init();
-
-		while (CrownLib.isRunning())
-		{
-			CrownLib.frame();
-		}
-
-		CrownLib.shutdown();
-	}
-}
+
+class PackageCompiler : public Compiler
+{
+public:
+
+	PackageCompiler();
+
+	size_t compile_impl(Filesystem& fs, const char* resource_path);
+	void write_impl(File* out_file);
+
+private:
+
+	bool m_has_texture;
+	bool m_has_lua;
+
+	List<ResourceId> m_textures;
+	List<ResourceId> m_scripts;
+};
+
+} // namespace crown

+ 26 - 12
engine/core/json/JSONParser.cpp

@@ -192,28 +192,42 @@ static bool is_escapee(char c)
 }
 }
 
 
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
-JSONElement::JSONElement() :
-	m_parser(NULL),
-	m_at(NULL),
-	m_begin(NULL)
+JSONElement::JSONElement()
+	: m_parser(NULL), m_begin(NULL), m_at(NULL)
 {
 {
 }
 }
 
 
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
-JSONElement::JSONElement(JSONParser& parser, const char* at) :
-	m_parser(&parser),
-	m_at(at),
-	m_begin(at)
+JSONElement::JSONElement(JSONParser& parser, const char* at)
+	: m_parser(&parser), m_begin(at), m_at(at)
 {
 {
 }
 }
 
 
+//--------------------------------------------------------------------------
+JSONElement::JSONElement(const JSONElement& other)
+	: m_parser(other.m_parser), m_begin(other.m_at), m_at(other.m_at)
+{
+}
+
+//--------------------------------------------------------------------------
+JSONElement& JSONElement::operator=(const JSONElement& other)
+{
+	m_parser = other.m_parser;
+
+	// Our begin is the other's at
+	m_begin = other.m_at;
+	m_at = other.m_at;
+
+	return *this;
+}
+
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
 JSONElement& JSONElement::operator[](uint32_t i)
 JSONElement& JSONElement::operator[](uint32_t i)
 {
 {
 	TempAllocator1024 alloc;
 	TempAllocator1024 alloc;
 	List<const char*> array(alloc);
 	List<const char*> array(alloc);
 
 
-	JSONParser::parse_array(m_at, array);
+	JSONParser::parse_array(m_begin, array);
 
 
 	CE_ASSERT(i < array.size(), "Index out of bounds");
 	CE_ASSERT(i < array.size(), "Index out of bounds");
 
 
@@ -234,7 +248,7 @@ JSONElement& JSONElement::key(const char* k)
 	TempAllocator1024 alloc;
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 	List<JSONPair> object(alloc);
 
 
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 
 	bool found = false;
 	bool found = false;
 
 
@@ -262,7 +276,7 @@ bool JSONElement::has_key(const char* k) const
 {
 {
 	TempAllocator1024 alloc;
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 
 	for (uint32_t i = 0; i < object.size(); i++)
 	for (uint32_t i = 0; i < object.size(); i++)
 	{
 	{
@@ -285,7 +299,7 @@ bool JSONElement::is_key_unique(const char* k) const
 {
 {
 	TempAllocator1024 alloc;
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 
 	bool found = false;
 	bool found = false;
 
 

+ 5 - 2
engine/core/json/JSONParser.h

@@ -63,6 +63,9 @@ public:
 	/// obtained from JSONParser::root() or copied from an
 	/// obtained from JSONParser::root() or copied from an
 	/// already existent and valid element.
 	/// already existent and valid element.
 						JSONElement();
 						JSONElement();
+						JSONElement(const JSONElement& other);
+
+	JSONElement&		operator=(const JSONElement& other);
 
 
 	/// Returns the @a i -th item of the current array.
 	/// Returns the @a i -th item of the current array.
 	JSONElement&		operator[](uint32_t i);
 	JSONElement&		operator[](uint32_t i);
@@ -128,11 +131,11 @@ public:
 
 
 private:
 private:
 
 
-						JSONElement(JSONParser& parser, const char* at);
+	explicit			JSONElement(JSONParser& parser, const char* at);
 
 
 	JSONParser*			m_parser;
 	JSONParser*			m_parser;
-	const char*			m_at;
 	const char*			m_begin;
 	const char*			m_begin;
+	const char*			m_at;
 
 
 	friend class 		JSONParser;
 	friend class 		JSONParser;
 };
 };

+ 1 - 0
engine/core/strings/StringStream.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <stdio.h>
 #include <stdio.h>
 #include "List.h"
 #include "List.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
+#include "OS.h"
 
 
 namespace crown
 namespace crown
 {
 {

+ 38 - 31
engine/input/InputManager.cpp

@@ -27,6 +27,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "InputManager.h"
 #include "InputManager.h"
 #include "OS.h"
 #include "OS.h"
 #include "Log.h"
 #include "Log.h"
+#include "EventBuffer.h"
+#include "OsEvents.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -98,7 +100,9 @@ EventDispatcher* InputManager::get_event_dispatcher()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void InputManager::frame(uint64_t frame_count)
 void InputManager::frame(uint64_t frame_count)
 {
 {
-	OsEvent event;
+	void* event;
+	uint32_t event_type;
+	size_t event_size;
 
 
 	// Update input devices
 	// Update input devices
 	m_keyboard.m_current_frame = frame_count;
 	m_keyboard.m_current_frame = frame_count;
@@ -106,9 +110,12 @@ void InputManager::frame(uint64_t frame_count)
 
 
 	while (1)
 	while (1)
 	{
 	{
-		event = pop_event();
+		if ((event = os_event_buffer()->get_next_event(event_type, event_size)) == NULL)
+		{
+			break;
+		}
 
 
-		switch (event.type)
+		switch (event_type)
 		{
 		{
 			case OSET_NONE:
 			case OSET_NONE:
 			{
 			{
@@ -118,12 +125,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_BUTTON_RELEASE:
 			case OSET_BUTTON_RELEASE:
 			{
 			{
 				MouseEvent mouse_event;
 				MouseEvent mouse_event;
-				mouse_event.x = event.data_a.int_value;
-				mouse_event.y = event.data_b.int_value;
-				mouse_event.button = event.data_c.int_value == 0 ? MB_LEFT : event.data_c.int_value == 1 ? MB_MIDDLE : MB_RIGHT;
+				mouse_event.x = ((OsMouseEvent*)event)->x;
+				mouse_event.y = ((OsMouseEvent*)event)->y;
+				mouse_event.button = ((OsMouseEvent*)event)->button == 0 ? MB_LEFT : ((OsMouseEvent*)event)->button == 1 ? MB_MIDDLE : MB_RIGHT;
 				mouse_event.wheel = 0.0f;
 				mouse_event.wheel = 0.0f;
 
 
-				if (event.type == OSET_BUTTON_PRESS)
+				if (event_type == OSET_BUTTON_PRESS)
 				{
 				{
 					m_mouse.update(frame_count, mouse_event.button, true);
 					m_mouse.update(frame_count, mouse_event.button, true);
 					m_event_dispatcher.button_pressed(mouse_event);
 					m_event_dispatcher.button_pressed(mouse_event);
@@ -140,12 +147,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_KEY_RELEASE:
 			case OSET_KEY_RELEASE:
 			{
 			{
 				KeyboardEvent keyboard_event;
 				KeyboardEvent keyboard_event;
-				keyboard_event.key = (KeyCode)event.data_a.int_value;
-				keyboard_event.modifier = (uint8_t)event.data_b.int_value;
+				keyboard_event.key = (KeyCode) ((OsKeyboardEvent*)event)->key;
+				keyboard_event.modifier = (uint8_t) ((OsKeyboardEvent*)event)->modifier;
 
 
 				m_keyboard.m_modifier = keyboard_event.modifier;
 				m_keyboard.m_modifier = keyboard_event.modifier;
 
 
-				if (event.type == OSET_KEY_PRESS)
+				if (event_type == OSET_KEY_PRESS)
 				{
 				{
 					m_keyboard.update(frame_count, keyboard_event.key, true);
 					m_keyboard.update(frame_count, keyboard_event.key, true);
 					m_event_dispatcher.key_pressed(keyboard_event);
 					m_event_dispatcher.key_pressed(keyboard_event);
@@ -162,9 +169,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_UP:
 			case OSET_TOUCH_UP:
 			{
 			{
 				TouchEvent touch_event;
 				TouchEvent touch_event;
-				touch_event.pointer_id = event.data_a.int_value;
-				touch_event.x = event.data_b.int_value;
-				touch_event.y = event.data_c.int_value;
+				touch_event.pointer_id = ((OsTouchEvent*)event)->pointer_id;
+				touch_event.x = ((OsTouchEvent*)event)->x;
+				touch_event.y = ((OsTouchEvent*)event)->y;
 
 
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
@@ -173,7 +180,7 @@ void InputManager::frame(uint64_t frame_count)
 				m_touch.m_pointers[touch_event.pointer_id].relative_x = 0.0f;
 				m_touch.m_pointers[touch_event.pointer_id].relative_x = 0.0f;
 				m_touch.m_pointers[touch_event.pointer_id].relative_y = 0.0f;
 				m_touch.m_pointers[touch_event.pointer_id].relative_y = 0.0f;
 
 
-				if (event.type == OSET_TOUCH_DOWN)
+				if (event_type == OSET_TOUCH_DOWN)
 				{
 				{
 					m_touch.m_pointers[touch_event.pointer_id].up = false;
 					m_touch.m_pointers[touch_event.pointer_id].up = false;
 					m_event_dispatcher.touch_down(touch_event);
 					m_event_dispatcher.touch_down(touch_event);
@@ -189,9 +196,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_MOVE:
 			case OSET_TOUCH_MOVE:
 			{
 			{
 				TouchEvent touch_event;
 				TouchEvent touch_event;
-				touch_event.pointer_id = event.data_a.int_value;
-				touch_event.x = event.data_b.int_value;
-				touch_event.y = event.data_c.int_value;
+				touch_event.pointer_id = ((OsTouchEvent*)event)->pointer_id;
+				touch_event.x = ((OsTouchEvent*)event)->x;
+				touch_event.y = ((OsTouchEvent*)event)->y;
 
 
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
@@ -204,20 +211,20 @@ void InputManager::frame(uint64_t frame_count)
 
 
 				break;
 				break;
 			}
 			}
-			case OSET_ACCELEROMETER:
-			{
-				AccelerometerEvent sensor_event;
-				sensor_event.x = event.data_a.float_value;
-				sensor_event.y = event.data_b.float_value;
-				sensor_event.z = event.data_c.float_value;
-
-				m_accelerometer.m_orientation.x = sensor_event.x;
-				m_accelerometer.m_orientation.y = sensor_event.y;
-				m_accelerometer.m_orientation.z = sensor_event.z;
-
-				m_event_dispatcher.accelerometer_changed(sensor_event);
-				break;
-			}
+			// case OSET_ACCELEROMETER:
+			// {
+			// 	AccelerometerEvent sensor_event;
+			// 	sensor_event.x = event.data_a.float_value;
+			// 	sensor_event.y = event.data_b.float_value;
+			// 	sensor_event.z = event.data_c.float_value;
+
+			// 	m_accelerometer.m_orientation.x = sensor_event.x;
+			// 	m_accelerometer.m_orientation.y = sensor_event.y;
+			// 	m_accelerometer.m_orientation.z = sensor_event.z;
+
+			// 	m_event_dispatcher.accelerometer_changed(sensor_event);
+			// 	break;
+			// }
 			default:
 			default:
 			{
 			{
 				break;
 				break;

+ 29 - 4
engine/lua/LuaDevice.cpp

@@ -25,6 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
 #include "Device.h"
 #include "Device.h"
+#include "ResourcePackage.h"
 #include "LuaEnvironment.h"
 #include "LuaEnvironment.h"
 #include "LuaStack.h"
 #include "LuaStack.h"
 
 
@@ -71,13 +72,37 @@ CE_EXPORT int device_stop(lua_State* /*L*/)
 	return 0;
 	return 0;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+CE_EXPORT int device_create_resource_package(lua_State* L)
+{
+	LuaStack stack(L);
+
+	const char* package = stack.get_string(1);
+	stack.push_lightdata(device()->create_resource_package(package));
+
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int device_destroy_resource_package(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	device()->destroy_resource_package(package);
+
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void load_device(LuaEnvironment& env)
 void load_device(LuaEnvironment& env)
 {
 {
-	env.load_module_function("Device", "frame_count", device_frame_count);
-	env.load_module_function("Device", "last_delta_time", device_last_delta_time);
-	env.load_module_function("Device", "start", device_start);
-	env.load_module_function("Device", "stop", device_stop);
+	env.load_module_function("Device", "frame_count",              device_frame_count);
+	env.load_module_function("Device", "last_delta_time",          device_last_delta_time);
+	env.load_module_function("Device", "start",                    device_start);
+	env.load_module_function("Device", "stop",                     device_stop);
+	env.load_module_function("Device", "create_resource_package",  device_create_resource_package);
+	env.load_module_function("Device", "destroy_resource_package", device_destroy_resource_package);
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 57 - 135
engine/lua/LuaEnvironment.cpp

@@ -44,20 +44,17 @@ CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
 	load_int_setting(*env);
 	load_int_setting(*env);
 	load_float_setting(*env);
 	load_float_setting(*env);
 	load_string_setting(*env);
 	load_string_setting(*env);
-
 	load_vec2(*env);
 	load_vec2(*env);
 	load_vec3(*env);
 	load_vec3(*env);
 	load_mat4(*env);
 	load_mat4(*env);
 	load_quat(*env);
 	load_quat(*env);
 	load_math(*env);
 	load_math(*env);
-
 	load_mouse(*env);
 	load_mouse(*env);
 	load_keyboard(*env);
 	load_keyboard(*env);
 	load_accelerometer(*env);
 	load_accelerometer(*env);
-
 	load_device(*env);
 	load_device(*env);
-
 	load_window(*env);
 	load_window(*env);
+	load_resource_package(*env);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -81,13 +78,9 @@ static int crown_lua_require(lua_State* L)
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-LuaEnvironment::LuaEnvironment() :
-	m_state(luaL_newstate()),
-	m_is_used(false)
+LuaEnvironment::LuaEnvironment()
+	: m_state(luaL_newstate()), m_is_used(false)
 {
 {
-	// Open Lua default libraries
-	string::strncpy(m_error_buffer, "", 1024);
-	string::strncpy(m_tmp_buffer, "", 1024);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -117,17 +110,6 @@ void LuaEnvironment::init()
 
 
 	lua_pop(m_state, 1);
 	lua_pop(m_state, 1);
 
 
-	// load_buffer(class_system, string::strlen(class_system));
-	// execute(0, 0);
-	// load_buffer(commands_list, string::strlen(commands_list));
-	// execute(0, 0);
-	// load_buffer(get_cmd_by_name, string::strlen(get_cmd_by_name));
-	// execute(0, 0);
-	// load_buffer(tmp_print_table, string::strlen(tmp_print_table));
-	// execute(0, 0);
-	// load_buffer(count_all, string::strlen(count_all));
-	// execute(0, 0);
-
 	m_is_used = true;
 	m_is_used = true;
 }
 }
 
 
@@ -135,37 +117,61 @@ void LuaEnvironment::init()
 void LuaEnvironment::shutdown()
 void LuaEnvironment::shutdown()
 {
 {
 	lua_close(m_state);
 	lua_close(m_state);
-
 	m_is_used = false;
 	m_is_used = false;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-const char* LuaEnvironment::error()
-{	
-	string::strncpy(m_tmp_buffer, m_error_buffer, 1024);
-	string::strncpy(m_error_buffer, "", 1024);
+bool LuaEnvironment::load_and_execute(const char* res_name)
+{
+	CE_ASSERT_NOT_NULL(res_name);
+
+	ResourceManager* resman = device()->resource_manager();
+
+	// Load the resource
+	ResourceId res_id = resman->load("lua", res_name);
+	resman->flush();
+	LuaResource* lr = (LuaResource*) resman->data(res_id);
+	
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
+	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), res_name) == 0)
+	{
+		if (lua_pcall(m_state, 0, 0, -2) == 0)
+		{
+			// Unloading is OK since the script data has been copied to Lua
+			resman->unload(res_id);
+			lua_pop(m_state, 2); // Pop debug.traceback
+			return true;
+		}
+	}
 
 
-	return m_tmp_buffer;
+	error();
+	lua_pop(m_state, 2); // Pop debug.traceback
+	return false;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void LuaEnvironment::load(const LuaResource* lr)
+void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
 {
 {
-	CE_ASSERT_NOT_NULL(lr);
+	luaL_Reg entry[2];
 
 
-	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), "") != 0)
-	{
-		lua_error();
-	}
+	entry[0].name = name;
+	entry[0].func = func;
+	entry[1].name = NULL;
+	entry[1].func = NULL;
 
 
-	if (lua_pcall(m_state, 0, 0, 0) != 0)
-	{
-		lua_error();
-	}
+	luaL_register(m_state, module, entry);
+}
+
+//-----------------------------------------------------------
+void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
+{
+	lua_pushinteger(m_state, value);
+	lua_setfield(m_state, -2, name);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
+bool LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 {
 {
 	CE_ASSERT_NOT_NULL(func);
 	CE_ASSERT_NOT_NULL(func);
 
 
@@ -174,6 +180,8 @@ void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 	va_list vl;
 	va_list vl;
 	va_start(vl, argc);
 	va_start(vl, argc);
 
 
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
 	lua_getglobal(m_state, func);
 	lua_getglobal(m_state, func);
 
 
 	for (uint8_t i = 0; i < argc; i++)
 	for (uint8_t i = 0; i < argc; i++)
@@ -196,110 +204,24 @@ void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 
 
 	va_end(vl);
 	va_end(vl);
 
 
-	if (lua_pcall(m_state, argc, 0, 0) != 0)
+	if (lua_pcall(m_state, argc, 0, -argc - 2) != 0)
 	{
 	{
-		lua_error();
+		error();
+		lua_pop(m_state, 2); // Pop debug.traceback
+		return false;
 	}
 	}
-}
 
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::lua_error()
-{
-	string::strncpy(m_error_buffer, "", 1024);
-	string::strncpy(m_error_buffer, lua_tostring(m_state, -1), 1024);
-}
+	lua_pop(m_state, 2); // Pop debug.traceback
 
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
-{
-	luaL_Reg entry[2];
-
-	entry[0].name = name;
-	entry[0].func = func;
-	entry[1].name = NULL;
-	entry[1].func = NULL;
-
-	luaL_register(m_state, module, entry);
+	return true;
 }
 }
 
 
-//-----------------------------------------------------------
-void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
+//-----------------------------------------------------------------------------
+void LuaEnvironment::error()
 {
 {
-	lua_pushinteger(m_state, value);
-	lua_setfield(m_state, -2, name);
+	const char* msg = lua_tostring(m_state, -1);
+	Log::e(msg);
+	lua_pop(m_state, 1);
 }
 }
 
 
-const char* LuaEnvironment::class_system =  "function class(klass, super) "
-    										"	if not klass then "
-        									"		klass = {} "
-                							"		local meta = {} "
-        									"		meta.__call = function(self, ...) "
-            								"			local object = {} "
-            								"			setmetatable(object, klass) "
-            								"			if object.init then object:init(...) end "
-            								"			return object "
-       										"		end "
-        									"		setmetatable(klass, meta) "
-    										"	end "  
-    										"	if super then "
-        									"		for k,v in pairs(super) do "
-            								"			klass[k] = v "
-        									"		end "
-    										"	end "
-    										"	klass.__index = klass "
-    										"	return klass "
-											"end";
-
-
-const char* LuaEnvironment::commands_list = "function get_all_commands() "
-											"	local cmds = {}; "
-											"	for class_name,class in pairs(_G) do "
-											"		if type(class) == 'table' then "
-			 								"			for func_name,func in pairs(class) do "
-			 								"				if type(func) == 'function' then "
-											"					cmds[#cmds+1] = class_name .. '.' .. func_name "
-											"				end "
-											"			end "
-											"		end "
-											"	end "
-											"	return cmds "
-											"end";
-
-const char* LuaEnvironment::get_cmd_by_name = 	"function get_command_by_name(text) "
-												"	local cmds = get_all_commands() "
-												"	local results = {} "
-												"	local index = 0 "
-												"	for i,cmd in pairs(cmds) do "
-												"		if string.find(cmd, text) then "
-												"			results[index] = cmds[i] "
-												"			index = index + 1 "
-												"		end "
-												"	end "
-												"	return results "
-												"end";
-
-const char* LuaEnvironment::tmp_print_table =	"function print_table(table) "												
-												"	for k,v in pairs(table) do "
-												"		print(v) "
-												"	end "
-												"end";
-
-const char* LuaEnvironment::count_all = 	"function count_all(f) "
-											"	local seen = {} "
-											"	local count_table "
-											"	count_table = function(t) "
-											"		if seen[t] then return end "
-											"		f(t) "
-											"		seen[t] = true "
-											"		for k,v in pairs(t) do "
-											"			if type(v) == 'table' then "
-											"				count_table(v) "
-											"			elseif type(v) == 'userdata' then "
-											"				f(v) "
-											"			end "
-											"		end "
-											"	end "
-											"	count_table(_G) "
-											"end";
-
 } // namespace crown
 } // namespace crown

+ 13 - 19
engine/lua/LuaEnvironment.h

@@ -53,16 +53,9 @@ public:
 	/// Close Lua state and shutdown LuaEnvironment
 	/// Close Lua state and shutdown LuaEnvironment
 	void					shutdown();
 	void					shutdown();
 
 
-	const char*				error();
-
-	/// Loads and execute the given @a lr lua script resource.
-	void					load(const LuaResource* lr);
-
-	/// Calls the global function @a func with @a argc argument number.
-	/// Each argument is a pair (type, value).
-	/// Example call:
-	/// call_global("myfunc", 1, ARGUMENT_FLOAT, 3.14f)
-	void					call_global(const char* func, uint8_t argc, ...);
+	/// Loads and execute the given @a res_name Lua resource, returns
+	/// true if success, false otherwise.
+	bool					load_and_execute(const char* res_name);
 
 
 	/// Load a function which will be used in Lua. @a module is the name of table contenitor,
 	/// Load a function which will be used in Lua. @a module is the name of table contenitor,
 	/// @a name is the name of function in module and @func is the pointer to the function.
 	/// @a name is the name of function in module and @func is the pointer to the function.
@@ -74,9 +67,17 @@ public:
 	/// @a name is module's name that refears _value_ and @value is an unsigned integer
 	/// @a name is module's name that refears _value_ and @value is an unsigned integer
 	void					load_module_enum(const char* module, const char* name, uint32_t value);
 	void					load_module_enum(const char* module, const char* name, uint32_t value);
 
 
+	/// Calls the global function @a func with @a argc argument number.
+	/// Each argument is a pair (type, value).
+	/// Example call:
+	/// call_global("myfunc", 1, ARGUMENT_FLOAT, 3.14f)
+	/// Returns true if success, false otherwise
+	bool					call_global(const char* func, uint8_t argc, ...);
+
+	void					error();
+
 private:
 private:
 
 
-	void					lua_error();
 	// Disable copying
 	// Disable copying
 							LuaEnvironment(const LuaEnvironment&);
 							LuaEnvironment(const LuaEnvironment&);
 	LuaEnvironment& 		operator=(const LuaEnvironment&);
 	LuaEnvironment& 		operator=(const LuaEnvironment&);
@@ -87,14 +88,6 @@ private:
 
 
 	/// LuaEnvironment is used right now?
 	/// LuaEnvironment is used right now?
 	bool					m_is_used;
 	bool					m_is_used;
-
-	char					m_error_buffer[1024];
-	char					m_tmp_buffer[1024];
-	static const char* 		class_system;
-	static const char*		commands_list;
-	static const char*		get_cmd_by_name;
-	static const char*		tmp_print_table;
-	static const char*		count_all;
 };
 };
 
 
 
 
@@ -114,5 +107,6 @@ void load_accelerometer(LuaEnvironment& env);
 void load_camera(LuaEnvironment& env);
 void load_camera(LuaEnvironment& env);
 void load_device(LuaEnvironment& env);
 void load_device(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
+void load_resource_package(LuaEnvironment& env);
 
 
 } // namespace crown
 } // namespace crown

+ 87 - 0
engine/lua/LuaResourcePackage.cpp

@@ -0,0 +1,87 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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 "ResourcePackage.h"
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int resource_package_load(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->load();
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int resource_package_unload(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->unload();
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int resource_package_flush(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->flush();
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int resource_package_has_loaded(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	stack.push_bool(package->has_loaded());
+
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+void load_resource_package(LuaEnvironment& env)
+{
+	env.load_module_function("ResourcePackage", "load",       resource_package_load);
+	env.load_module_function("ResourcePackage", "unload",     resource_package_unload);
+	env.load_module_function("ResourcePackage", "flush",      resource_package_flush);
+	env.load_module_function("ResourcePackage", "has_loaded", resource_package_has_loaded);
+}
+
+} // namespace crown

+ 5 - 39
engine/os/OS.cpp

@@ -1,4 +1,5 @@
 /*
 /*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
 Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
 Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
 
 
 Permission is hereby granted, free of charge, to any person
 Permission is hereby granted, free of charge, to any person
@@ -28,46 +29,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 namespace crown
 {
 {
 
 
-static const size_t		MAX_EVENTS = 512;
-static OsEvent			event_queue[MAX_EVENTS];
-static uint32_t			event_queue_head = 0;
-static uint32_t			event_queue_tail = 0;
+EventBuffer g_os_event_buffer;
 
 
-//-----------------------------------------------------------------------------
-void push_event(OsEventType type, OsEventParameter data_a, OsEventParameter data_b, OsEventParameter data_c, OsEventParameter data_d)
+EventBuffer* os_event_buffer()
 {
 {
-	if ((event_queue_tail + 1) % MAX_EVENTS == event_queue_head)
-	{
-		os::printf("OS event queue full!\n");
-		return;
-	}
-
-	OsEvent* event = &event_queue[event_queue_tail];
-	event_queue_tail = (event_queue_tail + 1) % MAX_EVENTS;
-
-	event->type = type;
-	event->data_a = data_a;
-	event->data_b = data_b;
-	event->data_c = data_c;
-	event->data_d = data_d;
+	return &g_os_event_buffer;
 }
 }
 
 
-//-----------------------------------------------------------------------------
-OsEvent& pop_event()
-{
-	static OsEvent event;
-
-	if (event_queue_head == event_queue_tail)
-	{
-		event.type = OSET_NONE;
-		return event;
-	}
-
-	event = event_queue[event_queue_head];
-	event_queue_head = (event_queue_head + 1) % MAX_EVENTS;
-
-	return event;
-}
-
-} // namespace crown
-
+} // namespace crown

+ 8 - 38
engine/os/OS.h

@@ -32,6 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Types.h"
 #include "Vector.h"
 #include "Vector.h"
 #include "DynamicString.h"
 #include "DynamicString.h"
+#include "EventBuffer.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -46,6 +47,8 @@ namespace crown
 
 
 	#define snprintf _snprintf
 	#define snprintf _snprintf
 
 
+	#define Thread os::Thread
+
 	#undef MK_SHIFT
 	#undef MK_SHIFT
 	#undef MK_ALT
 	#undef MK_ALT
 #elif defined(ANDROID)
 #elif defined(ANDROID)
@@ -105,6 +108,9 @@ bool			delete_directory(const char* path);
 /// Does not follow symbolic links.
 /// Does not follow symbolic links.
 void			list_files(const char* path, Vector<DynamicString>& files);
 void			list_files(const char* path, Vector<DynamicString>& files);
 
 
+/// Returns os-dependent path from os-indipendent @a path
+const char*		normalize_path(const char* path);
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // OS ambient variables
 // OS ambient variables
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -150,47 +156,11 @@ void*			lookup_symbol(void* library, const char* name);
 /// @a args[n] is NULL.
 /// @a args[n] is NULL.
 void			execute_process(const char* args[]);
 void			execute_process(const char* args[]);
 
 
-} // namespace os
-
-//-----------------------------------------------------------------------------
-// Events
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-enum OsEventType
-{
-	OSET_NONE				= 0,
 
 
-	OSET_KEY_PRESS			= 1,
-	OSET_KEY_RELEASE		= 2,
-
-	OSET_BUTTON_PRESS		= 3,
-	OSET_BUTTON_RELEASE		= 4,
-	OSET_MOTION_NOTIFY		= 5,
-	OSET_TOUCH_DOWN			= 6,
-	OSET_TOUCH_MOVE			= 7,
-	OSET_TOUCH_UP			= 8,
-	OSET_ACCELEROMETER		= 9
-};
-
-union OsEventParameter
-{
-	int32_t int_value;
-	float	float_value;
-};
+} // namespace os
 
 
-struct OsEvent
-{
-	OsEventType			type;
-	OsEventParameter	data_a;
-	OsEventParameter	data_b;
-	OsEventParameter	data_c;
-	OsEventParameter	data_d;
-};
-
-/// Pushes the event @a type along with its parameters into the os' event queue.
-void			push_event(OsEventType type, OsEventParameter data_a, OsEventParameter data_b, OsEventParameter data_c, OsEventParameter data_d);
-
-/// Returns and pops the first event in the os' event queue.
-OsEvent&		pop_event();
+EventBuffer* 	os_event_buffer();
 
 
 } // namespace crown
 } // namespace crown
 
 

+ 88 - 0
engine/os/OsEvents.h

@@ -0,0 +1,88 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Types.h"
+
+namespace crown
+{
+
+/// __OsEventType__ represents an event fired by the OS
+enum OsEventType
+{
+	OSET_NONE				= 0,
+
+	OSET_KEY_PRESS			= 1,
+	OSET_KEY_RELEASE		= 2,
+
+	OSET_BUTTON_PRESS		= 3,
+	OSET_BUTTON_RELEASE		= 4,
+
+	OSET_MOTION_NOTIFY		= 5,
+	OSET_TOUCH_DOWN			= 6,
+	OSET_TOUCH_MOVE			= 7,
+	OSET_TOUCH_UP			= 8,
+	
+	OSET_ACCELEROMETER		= 9
+};
+
+/// __OsMouseEvent__ represents an event fired by mouse.
+/// It is processed by InputManager.
+struct OsMouseEvent
+{
+	uint32_t button;
+	uint32_t x;
+	uint32_t y;
+};
+
+/// __OsKeyboardEvent__ represents an event fired by keyboard.
+/// it is processed by InputManager.
+struct OsKeyboardEvent
+{
+	uint32_t key;
+	uint32_t modifier;
+};
+
+/// __OsTouchEvent__ represents an event fired by touch screen.
+/// It is processed by InputManager.
+struct OsTouchEvent
+{
+	uint32_t pointer_id;
+	uint32_t x;
+	uint32_t y;
+};
+
+/// __OsAccelerometerEvent__ represents an event fired by accelerometer.
+/// It is processed by InputManager.
+struct OsAccelerometerEvent
+{
+	float x;
+	float y;
+	float z;	
+};
+
+} // namespace crown

+ 46 - 6
engine/os/android/AndroidDevice.cpp

@@ -26,12 +26,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include <jni.h>
 #include <jni.h>
 #include "Device.h"
 #include "Device.h"
+#include "Renderer.h"
+#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_init(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 {
 	const char* argv[] = { "crown-android" };
 	const char* argv[] = { "crown-android" };
 
 
@@ -39,27 +41,65 @@ extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_init(JNIEnv* /*env
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdown(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_stopDevice(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->stop();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 {
 	device()->shutdown();
 	device()->shutdown();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_frame(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pauseDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 {
-	device()->frame();
+	device()->pause();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_unpauseDevice(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->unpause();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isInit(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDeviceInit(JNIEnv* /*env*/, jobject /*obj*/)
 {
 {
 	return device()->is_init();
 	return device()->is_init();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isRunning(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDeviceRunning(JNIEnv* /*env*/, jobject /*obj*/)
 {
 {
 	return device()->is_running();
 	return device()->is_running();
 }
 }
 
 
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDevicePaused(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	return device()->is_paused();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_frame(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->frame();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->renderer()->init();
+	Log::i("Renderer initialized");
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->renderer()->shutdown();
+	Log::i("Renderer shutdowned");
+}
+
 } // namespace crown
 } // namespace crown

+ 38 - 18
engine/os/android/AndroidOS.cpp

@@ -39,6 +39,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <unistd.h>
 #include <unistd.h>
 
 
 #include "OS.h"
 #include "OS.h"
+#include "OsEvents.h"
 #include "Assert.h"
 #include "Assert.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 
 
@@ -47,9 +48,7 @@ namespace crown
 namespace os
 namespace os
 {
 {
 
 
-static timespec			base_time;
-static uint32_t			window_width;
-static uint32_t			window_height;
+static timespec	base_time;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void printf(const char* string, ...)
 void printf(const char* string, ...)
@@ -201,6 +200,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	closedir(dir);
 	closedir(dir);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+	char* cur = norm;
+
+	while ((*path) != '\0')
+	{
+		if ((*path) == '\\')
+		{
+			(*cur) = PATH_SEPARATOR;
+		}
+		else
+		{
+			(*cur) = (*path);
+		}
+
+		path++;
+		cur++;
+	}
+
+	return norm;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 const char* get_cwd()
 const char* get_cwd()
 {
 {
@@ -285,33 +308,30 @@ void execute_process(const char* args[])
 	}
 	}
 }
 }
 
 
-
 } // namespace os
 } // namespace os
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushIntEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jint a, jint b, jint c, jint d)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushTouchEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jint pointer_id, jint x, jint y)
 {	
 {	
-	OsEventParameter values[4];
+	OsTouchEvent event;
 
 
-	values[0].int_value = a;
-	values[1].int_value = b;
-	values[2].int_value = c;
-	values[3].int_value = d;
+	event.pointer_id = pointer_id;
+	event.x = x;
+	event.y = y;
 
 
-	push_event((OsEventType)type, values[0], values[1], values[2], values[3]);
+	os_event_buffer()->push_event((OsEventType)type, &event, sizeof(OsTouchEvent));
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushFloatEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jfloat a, jfloat b, jfloat c, jfloat d)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushAccelerometerEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jfloat x, jfloat y, jfloat z)
 {
 {
-	OsEventParameter values[4];
+	OsAccelerometerEvent event;
 
 
-	values[0].float_value = a;
-	values[1].float_value = b;
-	values[2].float_value = c;
-	values[3].float_value = d;
+	event.x = x;
+	event.y = y;
+	event.z = z;
 
 
-	push_event((OsEventType)type, values[0], values[1], values[2], values[3]);
+	os_event_buffer()->push_event((OsEventType)type, &event, sizeof(OsAccelerometerEvent));
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 2 - 2
engine/os/android/ApkFilesystem.cpp

@@ -59,13 +59,13 @@ void ApkFilesystem::close(File* file)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool ApkFilesystem::is_directory(const char* path)
 bool ApkFilesystem::is_directory(const char* path)
 {
 {
-	return false;
+	return true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool ApkFilesystem::is_file(const char* path)
 bool ApkFilesystem::is_file(const char* path)
 {
 {
-	return false;
+	return true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 2 - 2
engine/os/android/Config.h

@@ -26,9 +26,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #define CROWN_VERSION_MAJOR 0 
 #define CROWN_VERSION_MAJOR 0 
 #define CROWN_VERSION_MINOR 1 
 #define CROWN_VERSION_MINOR 1 
-#define CROWN_VERSION_MICRO 11 
+#define CROWN_VERSION_MICRO 11
 
 
-#define ANDROID
+#define CROWN_DEVELOPMENT
 
 
 #ifdef ANDROID
 #ifdef ANDROID
 	#define PRId64 "lld"
 	#define PRId64 "lld"

+ 18 - 21
engine/os/android/OsWindow.cpp

@@ -24,41 +24,31 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
-#include <android/native_window_jni.h>
-
 #include "OsWindow.h"
 #include "OsWindow.h"
 #include "GLContext.h"
 #include "GLContext.h"
 #include "Assert.h"
 #include "Assert.h"
+#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-static ANativeWindow* window = NULL;
+ANativeWindow* g_android_window = NULL;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-OsWindow::OsWindow(uint32_t /*width*/, uint32_t /*height*/, uint32_t /*parent*/) :
-	m_window(NULL),
-	m_x(0),
-	m_y(0),
-	m_width(0),
-	m_height(0)
+OsWindow::OsWindow(uint32_t /*width*/, uint32_t /*height*/, uint32_t /*parent*/)
+	: m_x(0), m_y(0), m_width(0), m_height(0)
 {
 {
-	m_window = window;
-
-	m_width = ANativeWindow_getWidth(m_window);
-	m_height = ANativeWindow_getHeight(m_window);
-
-    set_android_window(m_window);
+	m_width = ANativeWindow_getWidth(g_android_window);
+	m_height = ANativeWindow_getHeight(g_android_window);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 OsWindow::~OsWindow()
 OsWindow::~OsWindow()
 {
 {
-	if (m_window)
+	if (g_android_window)
 	{
 	{
-		ANativeWindow_release(m_window);
+		ANativeWindow_release(g_android_window);
 	}
 	}
-
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -129,15 +119,22 @@ void OsWindow::set_title(const char* /*title*/)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void OsWindow::frame()
 void OsWindow::frame()
 {
 {
-	// Implemented Java-side
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-extern "C" void Java_crown_android_CrownLib_setWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
+extern "C" void Java_crown_android_CrownLib_createWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
 {
 {
     // obtain a native window from a Java surface
     // obtain a native window from a Java surface
 	CE_ASSERT(surface != 0, "Unable to get Android window");
 	CE_ASSERT(surface != 0, "Unable to get Android window");
-    window = ANativeWindow_fromSurface(env, surface);
+    g_android_window = ANativeWindow_fromSurface(env, surface);
+    Log::i("Window created");
+}
+
+//-----------------------------------------------------------------------------
+extern "C" void Java_crown_android_CrownLib_destroyWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
+{
+    ANativeWindow_release(g_android_window);
+    Log::i("Window destroyed");
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 1 - 2
engine/os/android/OsWindow.h

@@ -28,6 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include <sys/types.h>
 #include <sys/types.h>
 #include <android/native_window.h>
 #include <android/native_window.h>
+#include <android/native_window_jni.h>
 
 
 namespace crown
 namespace crown
 {
 {
@@ -81,8 +82,6 @@ public:
 
 
 private:
 private:
 
 
-	ANativeWindow*	m_window;
-
 	uint32_t		m_x;
 	uint32_t		m_x;
 	uint32_t		m_y;
 	uint32_t		m_y;
 	uint32_t		m_width;
 	uint32_t		m_width;

+ 12 - 40
engine/os/android/CrownActivity.java → engine/os/android/java/CrownActivity.java

@@ -38,6 +38,7 @@ import android.hardware.SensorManager;
 import android.content.Context;
 import android.content.Context;
 import android.widget.Toast;
 import android.widget.Toast;
 import android.content.res.AssetManager;
 import android.content.res.AssetManager;
+import android.view.View;
 import android.view.Surface;
 import android.view.Surface;
 import android.view.SurfaceView;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
 import android.view.SurfaceHolder;
@@ -49,9 +50,8 @@ import crown.android.CrownEnum;
 */
 */
 public class CrownActivity extends Activity
 public class CrownActivity extends Activity
 {
 {
-
 	// Debug
 	// Debug
-	public static String TAG = "CrownActivity";
+	public static String TAG = "crown";
 
 
 	// Resource attributes
 	// Resource attributes
     static AssetManager 		mAssetManager;
     static AssetManager 		mAssetManager;
@@ -60,8 +60,8 @@ public class CrownActivity extends Activity
 	private CrownTouch 			mTouch;
 	private CrownTouch 			mTouch;
 	private CrownSensor			mSensor;
 	private CrownSensor			mSensor;
 
 
-	// Graphic attributes
-	static CrownSurfaceView		mWindow;
+	private CrownSurfaceView 	mView;
+
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
     public void onCreate(Bundle savedInstanceState)
     public void onCreate(Bundle savedInstanceState)
@@ -73,26 +73,15 @@ public class CrownActivity extends Activity
 		CrownLib.initAssetManager(mAssetManager);
 		CrownLib.initAssetManager(mAssetManager);
 
 
 		// init Native Window
 		// init Native Window
-        mWindow = new CrownSurfaceView(this);
-        setContentView(mWindow);
+		mView = new CrownSurfaceView(this);
+        setContentView(mView);
 
 
 		// Init Input
 		// Init Input
 		mTouch = new CrownTouch(this);
 		mTouch = new CrownTouch(this);
 		mSensor = new CrownSensor(this);
 		mSensor = new CrownSensor(this);
-    }
-
-//-----------------------------------------------------------------------------
-	public void onStart()
-	{
-		super.onStart();
 
 
-	}
-
-//-----------------------------------------------------------------------------
-	public void onRestart()
-	{
-		super.onRestart();
-	}
+		Log.i(TAG, "Crown Activity created");
+    }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 	public void onResume()
 	public void onResume()
@@ -100,31 +89,20 @@ public class CrownActivity extends Activity
 		super.onResume();
 		super.onResume();
 		
 		
 		// init accelerometer
 		// init accelerometer
-		if (!mSensor.startListening(this))
-		{
-			finish();
-		}
+		mSensor.startListening(this);
+
+		Log.i(TAG, "Crown Activity resumed");
 	}
 	}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 	public void onPause()
 	public void onPause()
 	{
 	{
 		super.onPause();
 		super.onPause();
-	}
-
-//-----------------------------------------------------------------------------
-	public void onStop()
-	{
-		super.onStop();
 
 
 		// stop accelerometer
 		// stop accelerometer
 		mSensor.stopListening();
 		mSensor.stopListening();
-	}
 
 
-//-----------------------------------------------------------------------------
-	public void onDestroy()
-	{
-		super.onDestroy();
+		Log.i(TAG, "Crown Activity paused");
 	}
 	}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -133,10 +111,4 @@ public class CrownActivity extends Activity
 		mTouch.onTouch(event);
 		mTouch.onTouch(event);
         return super.onTouchEvent(event);
         return super.onTouchEvent(event);
 	}
 	}
-
-//-----------------------------------------------------------------------------
-	public boolean hasMultiTouchSupport(Context context)
-	{
-		return context.getPackageManager().hasSystemFeature("android.hardware.touchscreen.multitouch");
-	}
 }
 }

+ 0 - 0
engine/os/android/CrownEnum.java → engine/os/android/java/CrownEnum.java


+ 19 - 10
engine/os/android/CrownLib.java → engine/os/android/java/CrownLib.java

@@ -38,20 +38,29 @@ public class CrownLib
 	}
 	}
 	
 	
 	// Device functions
 	// Device functions
-	public static native void 		init();
+	public static native void 		initDevice();
+	public static native void		pauseDevice();
+	public static native void		unpauseDevice();
+	public static native void		stopDevice();
+
+	public static native boolean 	isDeviceInit();
+	public static native boolean	isDeviceRunning();
+	public static native boolean	isDevicePaused();
+
 	public static native void 		frame();
 	public static native void 		frame();
-	public static native void 		shutdown();
-	public static native boolean 	isInit();
-	public static native boolean	isRunning();
 
 
 	// AssetManager functions
 	// AssetManager functions
 	public static native void 		initAssetManager(AssetManager assetManager);
 	public static native void 		initAssetManager(AssetManager assetManager);
 
 
-	// InputManager functions
-	public static native void 		pushIntEvent(int type, int a, int b, int c, int d);
-	public static native void 		pushFloatEvent(int type, float a, float b, float c, float d);
-
 	// Window functions
 	// Window functions
-	public static native void		setWindow(Surface window);
-	public static native void 		setDisplaySize(int width, int height);
+	public static native void		createWindow(Surface window);
+	public static native void		destroyWindow();
+
+	// Renderer functions
+	public static native void		initRenderer();
+	public static native void		shutdownRenderer();
+
+	// InputManager functions
+	public static native void 		pushTouchEvent(int type, int pointer_id, int x, int y);
+	public static native void 		pushAccelerometerEvent(int type, float x, float y, float z);	
 }
 }

+ 31 - 23
engine/os/posix/Cond.cpp → engine/os/android/java/CrownMainThread.java

@@ -24,37 +24,45 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
-#include <string.h>
+package crown.android;
 
 
-#include "Cond.h"
+import android.util.Log;
+import android.view.SurfaceHolder;
 
 
-namespace crown
+///
+public class CrownMainThread extends Thread
 {
 {
+	private SurfaceHolder mSurfaceHolder;
 
 
-//-----------------------------------------------------------------------------
-Cond::Cond()
-{
-	memset(&m_cond, 0, sizeof(pthread_cond_t));
+	private boolean mPaused;
 
 
-	pthread_cond_init(&m_cond, NULL);
-}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-Cond::~Cond()
-{
-	pthread_cond_destroy(&m_cond);
-}
+	public CrownMainThread(SurfaceHolder holder)
+	{
+		super();
+		mSurfaceHolder = holder;
+	}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void Cond::signal()
-{
-	pthread_cond_signal(&m_cond);
-}
+	@Override
+	public void run()
+	{
+		CrownLib.createWindow(mSurfaceHolder.getSurface());
 
 
-//-----------------------------------------------------------------------------
-void Cond::wait(Mutex& mutex)
-{
-	pthread_cond_wait(&m_cond, &(mutex.m_mutex));
-}
+		if (!CrownLib.isDeviceInit())
+		{
+			CrownLib.initDevice();
+		}
+		else
+		{
+			CrownLib.initRenderer();
+			CrownLib.unpauseDevice();
+		}
 
 
-} // namespace crown
+		while (CrownLib.isDeviceRunning() && !CrownLib.isDevicePaused())
+		{
+			CrownLib.frame();
+		}
+	}
+}

+ 2 - 2
engine/os/android/CrownSensor.java → engine/os/android/java/CrownSensor.java

@@ -96,7 +96,7 @@ public class CrownSensor
 
 
                     norm();
                     norm();
 
 
-                    CrownLib.pushFloatEvent(CrownEnum.OSET_ACCELEROMETER, mGravity[0], mGravity[1], mGravity[2], 0.0f);
+                    CrownLib.pushAccelerometerEvent(CrownEnum.OSET_ACCELEROMETER, mGravity[0], mGravity[1], mGravity[2]);
                 }
                 }
             };           
             };           
         }
         }
@@ -115,7 +115,7 @@ public class CrownSensor
                     mGeoMagn[1] = (mGeoMagn[1] + event.values[1]) * 0.5f;
                     mGeoMagn[1] = (mGeoMagn[1] + event.values[1]) * 0.5f;
                     mGeoMagn[2] = (mGeoMagn[2] + event.values[2]) * 0.5f; 
                     mGeoMagn[2] = (mGeoMagn[2] + event.values[2]) * 0.5f; 
 
 
-                    // CrownLib.pushFloatEvent(CrownEnum.OSET_ACCELEROMETER, mGeoMagn[0], mGeoMagn[1], mGeoMagn[2], 0.0f);
+                    // CrownLib.pushAccelerometerEvent(CrownEnum.OSET_ACCELEROMETER, mGeoMagn[0], mGeoMagn[1], mGeoMagn[2], 0.0f);
                 }                
                 }                
             };
             };
         }
         }

+ 61 - 17
engine/os/android/CrownSurfaceView.java → engine/os/android/java/CrownSurfaceView.java

@@ -30,47 +30,91 @@ import android.content.Context;
 import android.view.Surface;
 import android.view.Surface;
 import android.view.SurfaceView;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
 import android.view.SurfaceHolder;
+import android.graphics.PixelFormat;
+import android.util.Log;
 
 
 public class CrownSurfaceView extends SurfaceView implements SurfaceHolder.Callback
 public class CrownSurfaceView extends SurfaceView implements SurfaceHolder.Callback
 {
 {
-	private MainThread mMainThread;
+	private final String TAG = "crown";
 
 
-	//-----------------------------------------------------------------------------
+	private CrownMainThread mThread;
+
+	private boolean mSurfaceCreated;
+
+//-----------------------------------------------------------------------------
 	public CrownSurfaceView(Context context)
 	public CrownSurfaceView(Context context)
 	{
 	{
 		super(context);
 		super(context);
 
 
-		this.getHolder().addCallback(this);
-
-		mMainThread = new MainThread(getHolder(), this);
+		getHolder().addCallback(this);
 
 
 		setFocusable(true);
 		setFocusable(true);
+
+		mSurfaceCreated = false;
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------
-	@Override
-	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
+//-----------------------------------------------------------------------------
+	public boolean isSurfaceCreated()
 	{
 	{
+		return mSurfaceCreated;
+	}
+
+//-----------------------------------------------------------------------------
+	public void createThread(SurfaceHolder holder)
+	{
+		mThread = new CrownMainThread(holder);
+		mThread.start();
+	}
+
+//-----------------------------------------------------------------------------
+	public void destroyThread()
+	{
+        try
+        {
+        	CrownLib.pauseDevice();
+            mThread.join();
+        }
+        catch (InterruptedException e)
+        {
+            Log.e("crown", "terminateThread corrupts");
+        }     
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	@Override
 	@Override
 	public void surfaceCreated(SurfaceHolder holder) 
 	public void surfaceCreated(SurfaceHolder holder) 
 	{
 	{
-		mMainThread.start();
+		Log.d(TAG, "Crown Surface created");
+
+		if (!mSurfaceCreated)
+		{
+			mSurfaceCreated = true;
+
+			createThread(holder);
+		}
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	@Override
 	@Override
 	public void surfaceDestroyed(SurfaceHolder holder) 
 	public void surfaceDestroyed(SurfaceHolder holder) 
 	{
 	{
-		try
-		{
-			mMainThread.join();
-		}
-		catch (InterruptedException e)
-		{
-			e.printStackTrace();
-		}
+		mSurfaceCreated = false;
+
+		destroyThread();
+
+		CrownLib.pauseDevice();
+
+		CrownLib.destroyWindow();
+
+		CrownLib.shutdownRenderer();
+
+		Log.d(TAG, "Crown Surface destroyed");
+	}
+
+	//-----------------------------------------------------------------------------
+	@Override
+	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
+	{
+		Log.d(TAG, "Crown Surface changed");
 	}
 	}
 }
 }

+ 4 - 5
engine/os/android/CrownTouch.java → engine/os/android/java/CrownTouch.java

@@ -35,10 +35,9 @@ import android.view.MotionEvent;
 * CrownTouch manages touch and gesture events passing them to Crown Engine
 * CrownTouch manages touch and gesture events passing them to Crown Engine
 */
 */
 
 
-//TODO: gestures doesn't work...fix them
 public class CrownTouch
 public class CrownTouch
 {
 {
-	private boolean 				isListening;
+	private boolean isListening;
 
 
 //-----------------------------------------------------------------------------------
 //-----------------------------------------------------------------------------------
 	public CrownTouch(Context context)
 	public CrownTouch(Context context)
@@ -63,7 +62,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_DOWN:
 			case MotionEvent.ACTION_DOWN:
 			case MotionEvent.ACTION_POINTER_DOWN:
 			case MotionEvent.ACTION_POINTER_DOWN:
 			{
 			{
-				CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_DOWN, pointerId, (int)x, (int)y, 0);
+				CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_DOWN, pointerId, (int)x, (int)y);
 				break;			
 				break;			
 			}
 			}
 
 
@@ -72,7 +71,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_OUTSIDE:
 			case MotionEvent.ACTION_OUTSIDE:
 			case MotionEvent.ACTION_CANCEL:
 			case MotionEvent.ACTION_CANCEL:
 			{
 			{
-				CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_UP, pointerId, (int)x, (int)y, 0);
+				CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_UP, pointerId, (int)x, (int)y);
 				break;			
 				break;			
 			}
 			}
 			
 			
@@ -80,7 +79,7 @@ public class CrownTouch
 			{
 			{
 				for (int index = 0; index < pointerCount; index++)
 				for (int index = 0; index < pointerCount; index++)
 				{
 				{
-					CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_MOVE, event.getPointerId(index), (int)event.getX(index), (int)event.getY(index), 0);
+					CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_MOVE, event.getPointerId(index), (int)event.getX(index), (int)event.getY(index));
 				}
 				}
 
 
 				break;
 				break;

+ 24 - 0
engine/os/linux/LinuxOS.cpp

@@ -206,6 +206,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	closedir(dir);
 	closedir(dir);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+	char* cur = norm;
+
+	while ((*path) != '\0')
+	{
+		if ((*path) == '\\')
+		{
+			(*cur) = PATH_SEPARATOR;
+		}
+		else
+		{
+			(*cur) = (*path);
+		}
+
+		path++;
+		cur++;
+	}
+
+	return norm;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 const char* get_cwd()
 const char* get_cwd()
 {
 {

+ 19 - 18
engine/os/linux/OsWindow.cpp

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "OS.h"
 #include "OS.h"
 #include "GLContext.h"
 #include "GLContext.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
+#include "OsEvents.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -271,8 +272,8 @@ void OsWindow::frame()
 {
 {
 	XEvent event;
 	XEvent event;
 
 
-	OsEventParameter data_button[4] = {0, 0, 0, 0};
-	OsEventParameter data_key[4] = {0, 0, 0, 0};
+	OsMouseEvent mouse_event;
+	OsKeyboardEvent keyboard_event;
 
 
 	while (XPending(m_x11_display))
 	while (XPending(m_x11_display))
 	{
 	{
@@ -293,38 +294,38 @@ void OsWindow::frame()
 			{
 			{
 				OsEventType oset_type = event.type == ButtonPress ? OSET_BUTTON_PRESS : OSET_BUTTON_RELEASE;
 				OsEventType oset_type = event.type == ButtonPress ? OSET_BUTTON_PRESS : OSET_BUTTON_RELEASE;
 
 
-				data_button[0].int_value = event.xbutton.x;
-				data_button[1].int_value = event.xbutton.y;
+				mouse_event.x = event.xbutton.x;
+				mouse_event.y = event.xbutton.y;
 
 
 				switch (event.xbutton.button)
 				switch (event.xbutton.button)
 				{
 				{
 					case Button1:
 					case Button1:
 					{
 					{
-						data_button[2].int_value = 0;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 0;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 						break;
 					}
 					}
 					case Button2:
 					case Button2:
 					{
 					{
-						data_button[2].int_value = 1;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 1;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 						break;
 					}
 					}
 					case Button3:
 					case Button3:
 					{
 					{
-						data_button[2].int_value = 2;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 2;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 						break;
 					}
 					}
 				}
 				}
 
 
 				break;
 				break;
 			}
 			}
-			case MotionNotify:
-			{
-				push_event(OSET_MOTION_NOTIFY, data_button[0], data_button[1], data_button[2], data_button[3]);
-				break;
-			}
+			// case MotionNotify:
+			// {
+			// 	push_event(OSET_MOTION_NOTIFY, data_button[0], data_button[1], data_button[2], data_button[3]);
+			// 	break;
+			// }
 			case KeyPress:
 			case KeyPress:
 			case KeyRelease:
 			case KeyRelease:
 			{
 			{
@@ -353,10 +354,10 @@ void OsWindow::frame()
 
 
 				OsEventType oset_type = event.type == KeyPress ? OSET_KEY_PRESS : OSET_KEY_RELEASE;
 				OsEventType oset_type = event.type == KeyPress ? OSET_KEY_PRESS : OSET_KEY_RELEASE;
 
 
-				data_key[0].int_value = ((int32_t)kc);
-				data_key[1].int_value = modifier_mask;
+				keyboard_event.key = ((int32_t)kc);
+				keyboard_event.modifier = modifier_mask;
 
 
-				push_event(oset_type, data_key[0], data_key[1], data_key[2], data_key[3]);
+				os_event_buffer()->push_event(oset_type, &keyboard_event, sizeof(OsKeyboardEvent));
 
 
 //				// Text input part
 //				// Text input part
 //				if (event.type == KeyPress && len > 0)
 //				if (event.type == KeyPress && len > 0)

+ 35 - 4
engine/os/linux/main.cpp

@@ -26,18 +26,29 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include "Crown.h"
 #include "Crown.h"
 
 
-int main(int argc, char** argv)
+namespace crown
+{
+
+struct MainArgs
+{
+	int argc;
+	char** argv;
+};
+
+static Thread thread("main-thread");
+
+int32_t main_thread(void* data)
 {
 {
 	crown::os::init_os();
 	crown::os::init_os();
 
 
 	crown::Device* engine = crown::device();
 	crown::Device* engine = crown::device();
 
 
-	if (!engine->init(argc, argv))
+	MainArgs* args = (MainArgs*)data;
+	if (!engine->init(args->argc, args->argv))
 	{
 	{
-		exit(-1);
+		return -1;
 	}
 	}
 
 
-	// Main loop
 	while (engine->is_running())
 	while (engine->is_running())
 	{
 	{
 		engine->frame();
 		engine->frame();
@@ -45,6 +56,26 @@ int main(int argc, char** argv)
 
 
 	engine->shutdown();
 	engine->shutdown();
 
 
+	thread.stop();
+
 	return 0;
 	return 0;
 }
 }
 
 
+int32_t ce_main(void* args)
+{
+	thread.start(main_thread, args);
+
+	while (thread.is_running());
+	
+	return 0;
+}
+
+}
+
+int32_t main(int argc, char** argv)
+{
+	crown::MainArgs args;
+	args.argc = argc;
+	args.argv = argv;
+	return crown::ce_main(&args);
+}

+ 35 - 0
engine/os/posix/Cond.h

@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include <pthread.h>
 #include <pthread.h>
+#include <cstring>
 
 
 #include "Types.h"
 #include "Types.h"
 #include "Mutex.h"
 #include "Mutex.h"
@@ -56,4 +57,38 @@ private:
 	Cond&			operator=(const Cond&);
 	Cond&			operator=(const Cond&);
 };
 };
 
 
+//-----------------------------------------------------------------------------
+inline Cond::Cond()
+{
+	memset(&m_cond, 0, sizeof(pthread_cond_t));
+
+	int32_t result = pthread_cond_init(&m_cond, NULL);
+
+	CE_ASSERT(result == 0, "Failed to init cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline Cond::~Cond()
+{
+	int32_t result = pthread_cond_destroy(&m_cond);
+
+	CE_ASSERT(result == 0, "Failed to destroy cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Cond::signal()
+{
+	int32_t result = pthread_cond_signal(&m_cond);
+
+	CE_ASSERT(result == 0, "Failed to signal cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Cond::wait(Mutex& mutex)
+{
+	int32_t result = pthread_cond_wait(&m_cond, &(mutex.m_mutex));
+
+	CE_ASSERT(result == 0, "Failed to wait cond. errno: %d", result);
+}
+
 } // namespace crown
 } // namespace crown

+ 36 - 0
engine/os/posix/Mutex.h

@@ -27,9 +27,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include <pthread.h>
 #include <pthread.h>
+#include <cstring>
 
 
 #include "Types.h"
 #include "Types.h"
 #include "OS.h"
 #include "OS.h"
+#include "Assert.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -57,4 +59,38 @@ private:
 	friend class		Cond;
 	friend class		Cond;
 };
 };
 
 
+//-----------------------------------------------------------------------------
+inline Mutex::Mutex()
+{
+	memset(&m_mutex, 0, sizeof(pthread_mutex_t));
+
+	int32_t result = pthread_mutex_init(&m_mutex, NULL);
+
+	CE_ASSERT(result == 0, "Failed to init mutex. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline Mutex::~Mutex()
+{
+	int32_t result = pthread_mutex_destroy(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to destroy mutex. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Mutex::lock()
+{
+	int32_t result = pthread_mutex_lock(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to acquire lock. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Mutex::unlock()
+{
+	int32_t result = pthread_mutex_unlock(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to release lock. errno: %d", result);
+}
+
 } // namespace crown
 } // namespace crown

+ 56 - 12
engine/os/posix/Mutex.cpp → engine/os/posix/Semaphore.h

@@ -24,37 +24,81 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
-#include <string.h>
+#pragma once
 
 
+#include <errno.h>
+#include <semaphore.h>
+
+#include "Assert.h"
 #include "Mutex.h"
 #include "Mutex.h"
+#include "Cond.h"
+#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-//-----------------------------------------------------------------------------
-Mutex::Mutex()
+class Semaphore
 {
 {
-	memset(&m_mutex, 0, sizeof(pthread_mutex_t));
+public:
+
+			Semaphore();
+			~Semaphore();
+
+	void	post(uint32_t count = 1);
+	void	wait();
+
+private:
+
+	Mutex 	m_mutex;
+	Cond 	m_cond;
+
+	int32_t m_count;
+
+private:
+
+	Semaphore(const Semaphore& s); // no copy constructor
+	Semaphore& operator=(const Semaphore& s); // no assignment operator
+};
 
 
-	pthread_mutex_init(&m_mutex, NULL);
+//-----------------------------------------------------------------------------
+inline Semaphore::Semaphore() : m_count(0)
+{
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-Mutex::~Mutex()
+inline Semaphore::~Semaphore()
 {
 {
-	pthread_mutex_destroy(&m_mutex);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void Mutex::lock()
+inline void Semaphore::post(uint32_t count)
 {
 {
-	pthread_mutex_lock(&m_mutex);
+	m_mutex.lock();
+
+	for (uint32_t i = 0; i < count; i++)
+	{
+		m_cond.signal();
+	}
+
+	m_count += count;
+
+	m_mutex.unlock();	
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void Mutex::unlock()
+inline void Semaphore::wait()
 {
 {
-	pthread_mutex_unlock(&m_mutex);
+	m_mutex.lock();
+
+	while (m_count <= 0)
+	{
+		m_cond.wait(m_mutex);
+	}
+
+	m_count--;
+
+	m_mutex.unlock();
 }
 }
 
 
-} // namespace crown
+
+} // namespace crown

+ 0 - 125
engine/os/posix/Thread.cpp

@@ -1,125 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-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 <stdlib.h>
-#include <string.h>
-
-#include "Thread.h"
-#include "Assert.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Thread::Thread(const char* name) :
-	m_name(name),
-	m_is_running(false),
-	m_is_terminating(false),
-	m_thread(0)
-{
-	memset(&m_thread, 0, sizeof(pthread_t));
-}
-
-//-----------------------------------------------------------------------------
-Thread::~Thread()
-{
-}
-
-//-----------------------------------------------------------------------------
-const char* Thread::name() const
-{
-	return m_name;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::start()
-{
-	m_is_terminating = false;
-
-	// Make thread joinable
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-	// Create thread
-	int rc = pthread_create(&m_thread, &attr, Thread::background_proc, (void*) this);
-	CE_ASSERT(rc == 0, "Failed to create the thread '%s': errno: %d", m_name, rc);
-
-	// Free attr memory
-	pthread_attr_destroy(&attr);
-
-	m_is_running = true;
-}
-
-//-----------------------------------------------------------------------------
-bool Thread::is_running() const
-{
-	return m_is_running;
-}
-
-//-----------------------------------------------------------------------------
-bool Thread::is_terminating() const
-{
-	return m_is_terminating;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::stop()
-{
-	m_is_terminating = true;
-}
-
-//-----------------------------------------------------------------------------
-int32_t Thread::run()
-{
-	return 0;
-}
-
-//-----------------------------------------------------------------------------
-void* Thread::background_proc(void* thiz)
-{
-	Thread* thread = ((Thread*) thiz);
-
-	thread->run();
-
-	thread->m_is_running = false;
-
-	return NULL;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::join()
-{
-	pthread_join(m_thread, NULL);
-}
-
-//-----------------------------------------------------------------------------
-void Thread::detach()
-{
-	pthread_detach(m_thread);
-}
-
-} // namespace crown

+ 113 - 45
engine/os/posix/Thread.h

@@ -26,74 +26,142 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #pragma once
 #pragma once
 
 
-#include <pthread.h>
+#include <cstring>
 
 
+#include "Assert.h"
 #include "Types.h"
 #include "Types.h"
+#include "Semaphore.h"
+#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-typedef void* (*ThreadFunction)(void*);
+typedef int32_t (*ThreadFunction)(void*);
 
 
 class Thread
 class Thread
 {
 {
 public:
 public:
 
 
-	/// Constructs the thread and gives it a @a name.
-	/// @note
-	/// The actual OS thread creation and execution is
-	/// deferred to the first call to Thread::start().
-					Thread(const char* name);
+						Thread(const char* name);
+						~Thread();
 
 
-	/// Does not stop the thread. The user must call
-	/// Thread::stop() to effectively stop the thread. 
-	virtual			~Thread();
+	void				start(ThreadFunction func, void* data = NULL, size_t stack_size = 0);
+	void				stop();
 
 
-	/// Returns the name of the thread.
-	const char*		name() const;
+	bool				is_running();
 
 
-	void			join();
-	void			detach();
+private:
 
 
-	/// Returns whether the thread is currently running.
-	bool			is_running() const;
+	int32_t				run();
 
 
-	/// Returns whether the thread is being asked to stop running.
-	/// @note
-	/// The implementer tipically polls this function to
-	/// determine whether to stop the execution or not.
-	bool			is_terminating() const;
+	static void* 		thread_proc(void* arg);
 
 
-	/// Starts the execution of the thread.
-	/// The function creates the OS thread and starts
-	/// its execution.
-	void			start();
+private:
 
 
-	/// Stops the execution of the thread if it is running.
-	/// The function releases the OS thread causing its
-	/// termination.
-	void			stop();
+	const char* 		m_name;
 
 
-	/// Executes in background when the thead is running.
-	/// The thread has to be started with Thread::start()
-	virtual int32_t	run();
+	pthread_t			m_handle;
+	ThreadFunction 	m_function;
+	void*				m_data;
+	Semaphore			m_sem;
+	size_t 				m_stack_size;
 
 
-private:
+	bool				m_is_running :1;
+};
 
 
-	static void*	background_proc(void* thiz);
+//-----------------------------------------------------------------------------
+inline Thread::Thread(const char* name) :
+	m_name(name),
+	m_handle(0),
+	m_function(NULL),
+	m_data(NULL),
+	m_stack_size(0),
+	m_is_running(false)
+{
+	memset(&m_handle, 0, sizeof(pthread_t));
+}
 
 
-private:
+//-----------------------------------------------------------------------------
+inline Thread::~Thread()
+{
+}
 
 
-	const char*		m_name;
-	bool			m_is_running;
-	bool			m_is_terminating;
-	pthread_t		m_thread;
+//-----------------------------------------------------------------------------
+inline void Thread::start(ThreadFunction func, void* data, size_t stack_size)
+{
+	CE_ASSERT(!m_is_running, "Thread is already running");
+	CE_ASSERT(func != NULL, "Function must be != NULL");
 
 
-private:
+	m_function = func;
+	m_data = data;
+	m_stack_size = stack_size;
+
+	pthread_attr_t attr;
+	int32_t result = pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+
+	CE_ASSERT(result == 0, "pthread_attr_init failed. errno: %d", result);
+
+	if (m_stack_size != 0)
+	{
+		result = pthread_attr_setstacksize(&attr, m_stack_size);
+		CE_ASSERT(result == 0, "pthread_attr_setstacksize failed. errno: %d", result);
+	}
+
+	result = pthread_create(&m_handle, &attr, thread_proc, this);
+	CE_ASSERT(result == 0, "pthread_create failed. errno: %d", result);
+
+	// Free attr memory
+	result = pthread_attr_destroy(&attr);
+	CE_ASSERT(result == 0, "pthread_attr_destroy failed. errno: %d", result);
+
+	m_is_running = true;
+
+	m_sem.wait();
+}
+
+//-----------------------------------------------------------------------------
+inline void Thread::stop()
+{
+	CE_ASSERT(m_is_running, "Thread is not running");
+	
+	m_is_running = false;
+
+	int32_t result = pthread_join(m_handle, NULL);
+
+	CE_ASSERT(result == 0, "Thread join failed. errno: %d", result);
+
+	m_handle = 0;
+}
+
+//-----------------------------------------------------------------------------
+inline bool Thread::is_running()
+{
+	return m_is_running;
+}
+
+//-----------------------------------------------------------------------------
+inline int32_t Thread::run()
+{
+	m_sem.post();
+	
+	return m_function(m_data);
+}
+
+//-----------------------------------------------------------------------------
+inline void* Thread::thread_proc(void* arg)
+{
+	Thread* thread = (Thread*)arg;
+
+	int32_t result = thread->run();
+
+	CE_ASSERT(result == 0, "Function failed");
+
+	thread->m_is_running = false;
+
+	return NULL;
+}
 
 
-	// Disable copying
-					Thread(const Thread&);
-	Thread&			operator=(const Thread&);
-};
 
 
-} // namespace crown
+} // namespace crown

+ 51 - 5
engine/os/win/Thread.cpp

@@ -34,18 +34,52 @@ namespace os
 {
 {
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-Thread::Thread(os::ThreadFunction f, LPVOID params, const char* name)
+Thread::Thread(const char* name) :
+	m_name(name),
+	m_is_running(false),
+	m_is_terminating(false)
 {
 {
-	m_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) f, params, 0, NULL);
+}
 
 
-	CE_ASSERT(m_thread != NULL, "Unable to create thread");
+//-----------------------------------------------------------------------------
+Thread::~Thread()
+{
+}
 
 
-	m_name = name;
+//-----------------------------------------------------------------------------
+bool Thread::is_running() const
+{
+	return m_is_running;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-Thread::~Thread()
+bool Thread::is_terminating() const
+{
+	return m_is_terminating;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::start()
+{
+	m_is_terminating = false;
+
+	m_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Thread::background_proc, this, 0, NULL);
+
+	CE_ASSERT(m_thread != NULL, "Failed to create the thread '%s'", m_name);
+
+	m_is_running = true;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::stop()
+{
+	m_is_terminating = true;
+}
+
+//-----------------------------------------------------------------------------
+int32_t	Thread::run()
 {
 {
+	return 0;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -62,5 +96,17 @@ void Thread::detach()
 	CE_ASSERT(closed, "Unable to close thread");
 	CE_ASSERT(closed, "Unable to close thread");
 }
 }
 
 
+void* Thread::background_proc(void* thiz)
+{
+	Thread* thread  = (Thread*)thiz;
+
+	thread->run();
+
+	thread->m_is_running = false;
+
+	return NULL;
+}
+
+
 } // namespace os
 } // namespace os
 } // namespace crown
 } // namespace crown

+ 19 - 2
engine/os/win/Thread.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <windows.h>
 #include <windows.h>
 #include <process.h>
 #include <process.h>
 #include <WinBase.h>
 #include <WinBase.h>
+
 #include "Types.h"
 #include "Types.h"
 #include "OS.h"
 #include "OS.h"
 
 
@@ -43,16 +44,32 @@ class Thread
 {
 {
 public:
 public:
 
 
-					Thread(os::ThreadFunction f, LPVOID params, const char* name);
+					Thread(const char* name);
 					~Thread();
 					~Thread();
 
 
+	const char*		name() const;
+
 	void			join();
 	void			join();
 	void			detach();
 	void			detach();
 
 
+	bool			is_running() const;
+	bool			is_terminating() const;
+
+	void			start();
+	void			stop();
+
+	virtual int32_t	run();
+
 private:
 private:
 
 
-	HANDLE			m_thread;
+	static void*	background_proc(void* thiz);
+
+private:
+	
 	const char*		m_name;
 	const char*		m_name;
+	bool			m_is_running;
+	bool			m_is_terminating;
+	HANDLE			m_thread;
 };
 };
 
 
 } // namespace os
 } // namespace os

+ 90 - 9
engine/os/win/WinOS.cpp

@@ -111,9 +111,12 @@ bool is_absolute_path(const char* path)
 
 
 	if (string::strlen(path) > 0)
 	if (string::strlen(path) > 0)
 	{
 	{
-		if ((path[0] >= 65 && path[0] <= 90) || (path[0] >= 97 && path[0] <= 122))
+		if ((path[0] >= 'c' && path[0] <= 'z') || (path[0] >= 'C' && path[0] <= 'Z'))
 		{
 		{
-			return true;
+			if (path[1] == ':')
+			{
+				return true;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -129,7 +132,7 @@ bool exists(const char* path)
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-bool is_direcotry(const char* path)
+bool is_directory(const char* path)
 {
 {
 	DWORD fileAttr;
 	DWORD fileAttr;
 	fileAttr = GetFileAttributes(path);
 	fileAttr = GetFileAttributes(path);
@@ -139,7 +142,7 @@ bool is_direcotry(const char* path)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool is_file(const char* path)
 bool is_file(const char* path)
 {
 {
-	return !is_dir(path);
+	return !is_directory(path);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -207,11 +210,56 @@ const char* get_env(const char* env)
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// bool ls(const char* path, List<Str>& fileList)
-// {
-//	// TODO
-//	return false; 
-//}
+void list_files(const char* path, Vector<DynamicString>& files)
+{
+	HANDLE file = INVALID_HANDLE_VALUE;
+	WIN32_FIND_DATA ffd;
+
+	char cur_path[MAX_PATH_LENGTH];
+
+	string::strncpy(cur_path, path, string::strlen(path) + 1);
+	string::strncat(cur_path, "\\*", 2);
+
+	file = FindFirstFile(cur_path, &ffd);
+
+	do
+	{
+		CE_ASSERT(file != INVALID_HANDLE_VALUE, "Unable to list files. errono %d", GetLastError());
+
+		if ((string::strcmp(ffd.cFileName, ".") == 0) || (string::strcmp(ffd.cFileName, "..") == 0))
+		{
+			continue;
+		}
+	
+		DynamicString filename(default_allocator());
+
+		filename = ffd.cFileName;
+		files.push_back(filename);
+	}
+	while (FindNextFile(file, &ffd) != 0);
+
+	FindClose(file);
+}
+
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+
+	for (uint32_t i = 0; i < string::strlen(path)+1; i++)
+	{
+		if (path[i] == '/')
+		{
+			norm[i] = '\\';
+		}
+		else
+		{
+			norm[i] = path[i];
+		}
+	}
+
+	return norm;
+}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void init_os()
 void init_os()
@@ -271,5 +319,38 @@ void* lookup_symbol(void* library, const char* name)
 	return symbol;
 	return symbol;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+void execute_process(const char* args[])
+{
+	STARTUPINFO info;
+	memset(&info, 0, sizeof(info));
+	info.cb = sizeof(info);
+
+	PROCESS_INFORMATION process;
+	memset(&process, 0, sizeof(process));
+
+	DynamicString cmds(default_allocator());
+
+	for (uint32_t i = 0; args[i] != NULL; i++)
+	{
+		cmds += args[i];
+		cmds += ' ';
+	}
+
+	// Necessary because CreateProcess second argument must be non-const
+	char tmp[1024];
+	string::strncpy(tmp, normalize_path(cmds.c_str()), string::strlen(cmds.c_str()));
+
+	int32_t res;
+	if (res = CreateProcess(args[0], tmp, NULL, NULL, TRUE, 0, NULL, NULL, &info, &process))
+	{
+	    ::WaitForSingleObject(process.hProcess, INFINITE);
+   		CloseHandle(process.hProcess);
+    	CloseHandle(process.hThread);
+	}
+
+	CE_ASSERT(res != 0, "Unable to create process for %s, errno: %d\n", args[0], GetLastError());
+}
+
 } // namespace os
 } // namespace os
 } // namespace crown
 } // namespace crown

+ 305 - 0
engine/os/win/inttypes.h

@@ -0,0 +1,305 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+//#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+//#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]

+ 5 - 6
engine/renderers/gles/GLESRenderer.cpp

@@ -72,6 +72,8 @@ static const char* gl_error_to_string(GLenum error)
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 GLESRenderer::GLESRenderer() :
 GLESRenderer::GLESRenderer() :
+	Renderer(),
+
 	m_max_texture_size(0),
 	m_max_texture_size(0),
 	m_max_texture_units(0),
 	m_max_texture_units(0),
 	m_max_vertex_indices(0),
 	m_max_vertex_indices(0),
@@ -178,15 +180,11 @@ void GLESRenderer::init()
 	GL_CHECK(glDisable(GL_DITHER));
 	GL_CHECK(glDisable(GL_DITHER));
 
 
 	Log::i("OpenGL Renderer initialized.");
 	Log::i("OpenGL Renderer initialized.");
-
-	load_default_shaders();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void GLESRenderer::shutdown()
 void GLESRenderer::shutdown()
 {
 {
-	unload_default_shaders();
-
 	m_context.destroy_context();
 	m_context.destroy_context();
 }
 }
 
 
@@ -759,11 +757,12 @@ void GLESRenderer::frame()
 {
 {
 	// Clear frame/depth buffer
 	// Clear frame/depth buffer
 	GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
 	GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
+	GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 0.5f));
 
 
 	// Bind the default gpu program
 	// Bind the default gpu program
-	bind_gpu_program(m_default_gpu_program);
+	// bind_gpu_program(m_default_gpu_program);
 
 
-	set_gpu_program_mat4_uniform(m_default_gpu_program, "mvp_matrix", m_model_view_projection_matrix);
+	// set_gpu_program_mat4_uniform(m_default_gpu_program, "mvp_matrix", m_model_view_projection_matrix);
 
 
 	GL_CHECK(glFinish());
 	GL_CHECK(glFinish());
 
 

+ 72 - 32
engine/renderers/gles/egl/GLContext.cpp

@@ -26,76 +26,116 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2.h>
 
 
+#include "Config.h"
 #include "Assert.h"
 #include "Assert.h"
 #include "GLContext.h"
 #include "GLContext.h"
+#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-static ANativeWindow* awindow = NULL;
+extern ANativeWindow* g_android_window;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void set_android_window(ANativeWindow* window)
+static const char* egl_error_to_string(EGLint error)
 {
 {
-    CE_ASSERT_NOT_NULL(window);
-
-	awindow = window;
+	switch (error)
+	{
+		case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
+		case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
+		case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
+		case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
+		case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
+		case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
+		case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+		case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
+		case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
+		case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
+		case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
+		case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+		case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+		case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
+		default: return "UNKNOWN_EGL_ERROR";
+	}
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-GLContext::GLContext() :
-	num_configs(0)
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+	#define EGL_CHECK(function)\
+		function;\
+		do { EGLint error; CE_ASSERT((error = eglGetError()) == EGL_SUCCESS,\
+				"EGL error: %s", egl_error_to_string(error)); } while (0)
+#else
+	#define EGL_CHECK(function)\
+		function;
+#endif
+
+//-----------------------------------------------------------------------------
+GLContext::GLContext()
+	: display(EGL_NO_DISPLAY), surface(EGL_NO_SURFACE), context(EGL_NO_CONTEXT), num_configs(0)
 {
 {
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void GLContext::create_context()
 void GLContext::create_context()
 {
 {
-	EGLint format;
+    const EGLint attrib_list[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_BLUE_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_RED_SIZE, 8,
+            EGL_NONE
+    };
 
 
-	// Screen format rgbx8888 with no alpha channel,
-	// maybe it is wrong but is for testing
-	EGLint attrib_list[]= { EGL_RED_SIZE,        8,
-                            EGL_GREEN_SIZE,      8,
-                            EGL_BLUE_SIZE,       8,
-                            EGL_DEPTH_SIZE,      24,
-                            EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
-                            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                            EGL_NONE};
+	EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
 
-    EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+	display = EGL_CHECK(eglGetDisplay(EGL_DEFAULT_DISPLAY));
+	CE_ASSERT(display != EGL_NO_DISPLAY, "Failed to obtain EGL display connection");
 
 
-    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+	EGLint egl_major, egl_minor;
+	EGLBoolean init_success = EGL_CHECK(eglInitialize(display, &egl_major, &egl_minor));
+	CE_ASSERT(init_success == EGL_TRUE, "Failed to initialize EGL");
 
 
-    eglInitialize(display, NULL, NULL);
+	Log::d("EGL Initialized: major = %d, minor = %d", egl_major, egl_minor);
 
 
-    eglBindAPI(EGL_OPENGL_ES_API);
+	EGLBoolean bind_success = EGL_CHECK(eglBindAPI(EGL_OPENGL_ES_API));
+	CE_ASSERT(bind_success != EGL_FALSE, "Failed to bind OpenGL|ES API");
 
 
-    eglChooseConfig(display, attrib_list, &config, 1, &num_configs);
+	EGLBoolean cfg_success = EGL_CHECK(eglChooseConfig(display, attrib_list, &config, 1, &num_configs));
+	CE_ASSERT(cfg_success == EGL_TRUE, "Failed to choose EGL configuration");
 
 
-	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
+	EGLint format;
+	EGL_CHECK(eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format));
+
+	ANativeWindow_setBuffersGeometry(g_android_window, 0, 0, format);
 
 
-	ANativeWindow_setBuffersGeometry(awindow, 0, 0, format);
+	context = EGL_CHECK(eglCreateContext(display, config, EGL_NO_CONTEXT, attributes));
+	CE_ASSERT(context != EGL_NO_CONTEXT, "Oops, failed to create EGL context");
 
 
-    context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes);
+	surface = EGL_CHECK(eglCreateWindowSurface(display, config, (EGLNativeWindowType)g_android_window, NULL));
+	CE_ASSERT(surface != EGL_NO_SURFACE, "Oops, failed to create EGL surface");
 
 
-	surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)awindow, NULL);
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
 
 
-    eglMakeCurrent(display, surface, surface, context);
+	Log::d("EGL context created");
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void GLContext::destroy_context()
 void GLContext::destroy_context()
 {
 {
- 	eglDestroyContext(display, context);
- 	eglDestroySurface(display, surface);
- 	eglTerminate(display);
+	EGL_CHECK(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+	EGL_CHECK(eglDestroyContext(display, context));
+	EGL_CHECK(eglDestroySurface(display, surface));
+	EGL_CHECK(eglTerminate(display));
+
+	Log::i("EGL context destroyed");
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void GLContext::swap_buffers()
 void GLContext::swap_buffers()
 {
 {
-   	eglSwapBuffers(display, surface);
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
+	EGL_CHECK(eglSwapBuffers(display, surface));
 }
 }
 
 
-}
+}

+ 4 - 7
engine/renderers/gles/egl/GLContext.h

@@ -27,13 +27,10 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include <EGL/egl.h>
 #include <EGL/egl.h>
-#include <android/native_window.h>
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-void set_android_window(ANativeWindow* window);
-
 class GLContext
 class GLContext
 {
 {
 public:
 public:
@@ -47,11 +44,11 @@ public:
 private:
 private:
 
 
 	EGLDisplay 		display;
 	EGLDisplay 		display;
-    EGLSurface 		surface;
-    EGLConfig 		config;
-    EGLContext 		context;
+	EGLSurface 		surface;
+	EGLConfig 		config;
+	EGLContext 		context;
 
 
-    int32_t			num_configs;
+	int32_t			num_configs;
 };
 };
 
 
 } // namespace crown
 } // namespace crown

+ 1 - 0
engine/resource/FileBundle.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Resource.h"
 #include "Resource.h"
 #include "StringUtils.h" 
 #include "StringUtils.h" 
 #include "Types.h"
 #include "Types.h"
+#include "OS.h"
 
 
 namespace crown
 namespace crown
 {
 {

+ 0 - 1
engine/resource/LuaResource.h

@@ -31,7 +31,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "Bundle.h"
 #include "Allocator.h"
 #include "Allocator.h"
 #include "File.h"
 #include "File.h"
-#include "Log.h"
 
 
 namespace crown
 namespace crown
 {
 {

+ 122 - 0
engine/resource/PackageResource.h

@@ -0,0 +1,122 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "Resource.h"
+#include "Bundle.h"
+#include "Allocator.h"
+#include "File.h"
+
+namespace crown
+{
+
+// All offsets are absolute
+struct PackageHeader
+{
+	uint32_t num_textures;
+	uint32_t textures_offset;
+	uint32_t num_scripts;
+	uint32_t scripts_offset;
+};
+
+class PackageResource
+{
+public:
+
+	//-----------------------------------------------------------------------------
+	static void* load(Allocator& allocator, Bundle& bundle, ResourceId id)
+	{
+		File* file = bundle.open(id);
+
+		const size_t file_size = file->size() - 12;
+		PackageResource* res = (PackageResource*) allocator.allocate(sizeof(PackageResource));
+		res->m_data = (char*) allocator.allocate(file_size);
+		file->read(res->m_data, file_size);
+
+		bundle.close(file);
+
+		return res;
+	}
+
+	//-----------------------------------------------------------------------------
+	static void online(void* /*resource*/) {}
+
+	//-----------------------------------------------------------------------------
+	static void unload(Allocator& allocator, void* resource)
+	{
+		CE_ASSERT_NOT_NULL(resource);
+
+		allocator.deallocate(((PackageResource*)resource)->m_data);
+		allocator.deallocate(resource);
+	}
+
+	//-----------------------------------------------------------------------------
+	static void offline(void* /*resource*/) {}
+
+public:
+
+	//-----------------------------------------------------------------------------
+	uint32_t num_textures() const
+	{
+		CE_ASSERT_NOT_NULL(m_data);
+
+		return ((PackageHeader*)m_data)->num_textures;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint32_t num_scripts() const
+	{
+		CE_ASSERT_NOT_NULL(m_data);
+
+		return ((PackageHeader*)m_data)->num_scripts;
+	}
+
+	//-----------------------------------------------------------------------------
+	ResourceId get_texture_id(uint32_t i) const
+	{
+		CE_ASSERT(i < num_textures(), "Index out of bounds");
+
+		ResourceId* begin = (ResourceId*) (m_data + ((PackageHeader*)m_data)->textures_offset);
+		return begin[i];
+	}
+
+	//-----------------------------------------------------------------------------
+	ResourceId get_script_id(uint32_t i) const
+	{
+		CE_ASSERT(i < num_scripts(), "Index out of bounds");
+
+		ResourceId* begin = (ResourceId*) (m_data + ((PackageHeader*)m_data)->scripts_offset);
+		return begin[i];
+	}
+
+private:
+
+	char* m_data;
+};
+
+} // namespace crown

+ 2 - 0
engine/resource/Resource.h

@@ -41,6 +41,7 @@ const char* const TEXT_EXTENSION			= "text";
 const char* const MATERIAL_EXTENSION		= "material";
 const char* const MATERIAL_EXTENSION		= "material";
 const char* const SOUND_EXTENSION			= "sound";
 const char* const SOUND_EXTENSION			= "sound";
 const char* const CONFIG_EXTENSION			= "config";
 const char* const CONFIG_EXTENSION			= "config";
+const char* const PACKAGE_EXTENSION			= "package";
 
 
 const uint32_t TEXTURE_TYPE					= 0xDEED4F7;
 const uint32_t TEXTURE_TYPE					= 0xDEED4F7;
 const uint32_t MESH_TYPE					= 0xA6E48B29;
 const uint32_t MESH_TYPE					= 0xA6E48B29;
@@ -49,6 +50,7 @@ const uint32_t TEXT_TYPE					= 0x45CC650;
 const uint32_t MATERIAL_TYPE				= 0x46807A92;
 const uint32_t MATERIAL_TYPE				= 0x46807A92;
 const uint32_t SOUND_TYPE					= 0xD196AB6E;
 const uint32_t SOUND_TYPE					= 0xD196AB6E;
 const uint32_t CONFIG_TYPE					= 0x17DEA5E1;
 const uint32_t CONFIG_TYPE					= 0x17DEA5E1;
+const uint32_t PACKAGE_TYPE					= 0xC0A2212C;
 
 
 
 
 /// ResourceId uniquely identifies a resource by its name and type.
 /// ResourceId uniquely identifies a resource by its name and type.

+ 2 - 2
engine/resource/ResourceLoader.cpp

@@ -33,7 +33,7 @@ namespace crown
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
 ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
-	Thread("resource-loader"),
+	m_thread("resource-loader"),
 	m_bundle(bundle),
 	m_bundle(bundle),
 	m_resource_heap(resource_heap),
 	m_resource_heap(resource_heap),
 	m_num_requests(0),
 	m_num_requests(0),
@@ -94,7 +94,7 @@ void* ResourceLoader::load_resource_data(LoadResourceId id) const
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 int32_t ResourceLoader::run()
 {
 {
-	while (!is_terminating())
+	while (m_thread.is_running())
 	{
 	{
 		m_requests_mutex.lock();
 		m_requests_mutex.lock();
 		while (m_requests.empty())
 		while (m_requests.empty())

+ 21 - 1
engine/resource/ResourceLoader.h

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "List.h"
 #include "List.h"
 #include "Mutex.h"
 #include "Mutex.h"
 #include "Cond.h"
 #include "Cond.h"
+#include "OS.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -65,7 +66,7 @@ struct LoadResourceData
 };
 };
 
 
 /// Loads resources in a background thread.
 /// Loads resources in a background thread.
-class ResourceLoader : public Thread
+class ResourceLoader
 {
 {
 public:
 public:
 
 
@@ -85,8 +86,27 @@ public:
 	// Loads resources in the loading queue.
 	// Loads resources in the loading queue.
 	int32_t					run();
 	int32_t					run();
 
 
+	void start()
+	{
+		m_thread.start(background_run, this);
+	}
+
+	void stop()
+	{
+		m_thread.stop();
+	}
+
+private:
+
+	static int32_t background_run(void* thiz)
+	{
+		return ((ResourceLoader*)thiz)->run();
+	}
+
 private:
 private:
 
 
+	Thread					m_thread;
+
 	// Whether to look for resources
 	// Whether to look for resources
 	Bundle&					m_bundle;
 	Bundle&					m_bundle;
 
 

+ 1 - 0
engine/resource/ResourceManager.h

@@ -122,6 +122,7 @@ private:
 
 
 private:
 private:
 
 
+	friend class			ResourcePackage;
 	friend class			Device;
 	friend class			Device;
 };
 };
 
 

+ 107 - 0
engine/resource/ResourcePackage.h

@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+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.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "ResourceManager.h"
+#include "PackageResource.h"
+#include "Resource.h"
+
+namespace crown
+{
+
+/// Collection of resources to load in a batch.
+class ResourcePackage
+{
+public:
+
+	//-----------------------------------------------------------------------------
+	ResourcePackage(ResourceManager& resman, const ResourceId id, const PackageResource* package)
+		: m_resource_manager(&resman), m_package_id(id), m_package(package), m_has_loaded(false)
+	{
+		CE_ASSERT_NOT_NULL(package);
+	}
+
+	/// Loads all the resources in the package.
+	/// @note
+	/// The resources are not immediately available after the call is made,
+	/// instead, you have to poll for completion with has_loaded()
+	void load()
+	{
+		for (uint32_t i = 0; i < m_package->num_textures(); i++)
+		{
+			m_resource_manager->load(TEXTURE_TYPE, m_package->get_texture_id(i));
+		}
+
+		for (uint32_t i = 0; i < m_package->num_scripts(); i++)
+		{
+			m_resource_manager->load(LUA_TYPE, m_package->get_script_id(i));
+		}
+	}
+
+	/// Unloads all the resources in the package.
+	void unload()
+	{
+		for (uint32_t i = 0; i < m_package->num_textures(); i++)
+		{
+			m_resource_manager->unload(m_package->get_texture_id(i));
+		}
+
+		for (uint32_t i = 0; i < m_package->num_scripts(); i++)
+		{
+			m_resource_manager->unload(m_package->get_script_id(i));
+		}		
+	}
+
+	/// Waits until the package has been loaded. 
+	void flush()
+	{
+		m_resource_manager->flush();
+		m_has_loaded = true;
+	}
+
+	/// Returns whether the package has been loaded.
+	bool has_loaded() const
+	{
+		return m_has_loaded;
+	}
+
+	/// Returns the resource id of the package.
+	ResourceId resource_id() const
+	{
+		return m_package_id;
+	}
+
+private:
+
+	ResourceManager* m_resource_manager;
+	const ResourceId m_package_id;
+	const PackageResource* m_package;
+	bool m_has_loaded;
+};
+
+} // namespace crown

+ 2 - 0
engine/resource/ResourceRegistry.cpp

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "TextureResource.h"
 #include "TextureResource.h"
 #include "MeshResource.h"
 #include "MeshResource.h"
 #include "SoundResource.h"
 #include "SoundResource.h"
+#include "PackageResource.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -39,6 +40,7 @@ static const ResourceCallback RESOURCE_CALLBACK_REGISTRY[] =
 	{ TEXTURE_TYPE, TextureResource::load, TextureResource::unload, TextureResource::online, TextureResource::offline },
 	{ TEXTURE_TYPE, TextureResource::load, TextureResource::unload, TextureResource::online, TextureResource::offline },
 	{ MESH_TYPE, MeshResource::load, MeshResource::unload, MeshResource::online, MeshResource::offline },
 	{ MESH_TYPE, MeshResource::load, MeshResource::unload, MeshResource::online, MeshResource::offline },
 	{ SOUND_TYPE, SoundResource::load, SoundResource::unload, SoundResource::online, SoundResource::offline },
 	{ SOUND_TYPE, SoundResource::load, SoundResource::unload, SoundResource::online, SoundResource::offline },
+	{ PACKAGE_TYPE, PackageResource::load, PackageResource::unload, PackageResource::online, PackageResource::offline },	
 	{ 0, NULL, NULL, NULL, NULL }
 	{ 0, NULL, NULL, NULL, NULL }
 };
 };
 
 

+ 6 - 1
engine/tests/CMakeLists.txt

@@ -11,6 +11,8 @@ add_executable(strings strings.cpp)
 add_executable(paths paths.cpp)
 add_executable(paths paths.cpp)
 add_executable(dynamic-strings dynamic-strings.cpp)
 add_executable(dynamic-strings dynamic-strings.cpp)
 add_executable(json json.cpp)
 add_executable(json json.cpp)
+add_executable(events events.cpp)
+add_executable(threads threads.cpp)
 
 
 target_link_libraries(allocators crown)
 target_link_libraries(allocators crown)
 target_link_libraries(containers crown)
 target_link_libraries(containers crown)
@@ -19,6 +21,8 @@ target_link_libraries(strings crown)
 target_link_libraries(paths crown)
 target_link_libraries(paths crown)
 target_link_libraries(dynamic-strings crown)
 target_link_libraries(dynamic-strings crown)
 target_link_libraries(json crown)
 target_link_libraries(json crown)
+target_link_libraries(events crown)
+target_link_libraries(threads crown)
 
 
 add_test(allocators-test ${EXECUTABLE_OUTPUT_PATH}/allocators)
 add_test(allocators-test ${EXECUTABLE_OUTPUT_PATH}/allocators)
 add_test(containers-test ${EXECUTABLE_OUTPUT_PATH}/containers)
 add_test(containers-test ${EXECUTABLE_OUTPUT_PATH}/containers)
@@ -27,4 +31,5 @@ add_test(strings-test ${EXECUTABLE_OUTPUT_PATH}/strings)
 add_test(paths-test ${EXECUTABLE_OUTPUT_PATH}/paths)
 add_test(paths-test ${EXECUTABLE_OUTPUT_PATH}/paths)
 add_test(dynamic-string-test ${EXECUTABLE_OUTPUT_PATH}/dynamic-strings)
 add_test(dynamic-string-test ${EXECUTABLE_OUTPUT_PATH}/dynamic-strings)
 add_test(json-test ${EXECUTABLE_OUTPUT_PATH}/json)
 add_test(json-test ${EXECUTABLE_OUTPUT_PATH}/json)
-
+add_test(events-test ${EXECUTABLE_OUTPUT_PATH}/events)
+add_test(threads-test ${EXECUTABLE_OUTPUT_PATH}/threads)

+ 90 - 0
engine/tests/events.cpp

@@ -0,0 +1,90 @@
+#include "Crown.h"
+#include "EventBuffer.h"
+
+using namespace crown;
+
+//-----------------------------------------------------------------------------
+struct TestEvent
+{
+	uint32_t a;
+	uint32_t b;
+	uint32_t c;
+};
+
+//-----------------------------------------------------------------------------
+void fill_events(EventBuffer& event_buffer, uint32_t num)
+{
+	TestEvent event;
+	event.a = 1;
+	event.b = 2;
+	event.c = 3;
+
+	for (uint32_t i = 0; i < num; i++)
+	{
+		event_buffer.push_event(0, &event, sizeof(TestEvent));
+	}
+
+	uint32_t size = num * (sizeof(TestEvent) + sizeof(uint32_t) + sizeof(size_t));
+
+	CE_ASSERT(event_buffer.size() == size, "Something ha gone wrong, size is %d, should be %d", event_buffer.size(), size);
+}
+
+void get_events(EventBuffer& event_buffer, uint32_t num)
+{
+	TestEvent* result;
+	uint32_t type = 0;
+	size_t size = 0;
+
+	uint32_t count = 0;
+
+	for (uint32_t i = 0; i < num; i++)
+	{
+		result = (TestEvent*)event_buffer.get_next_event(type, size);
+
+		if (result)
+		{
+			count++;
+		}
+
+		Log::i("count: %d", count);
+	}
+
+	CE_ASSERT(count == num, "Something ha gone wrong, count: %d, num: %d", count, num);
+}
+
+void get_event_until_end(EventBuffer& event_buffer)
+{
+	TestEvent* result;
+	uint32_t type = 0;
+	size_t size = 0;
+
+	int32_t count = 0;
+
+	while ((result = (TestEvent*)event_buffer.get_next_event(type, size)) != NULL)
+	{
+		count++;
+	}
+
+	Log::i("count: %d", count);
+}
+
+//-----------------------------------------------------------------------------
+int main()
+{
+	EventBuffer event_buffer;
+
+	fill_events(event_buffer, 10);
+	get_events(event_buffer, 10);
+
+	event_buffer.clear();
+
+	fill_events(event_buffer, 5);
+	get_events(event_buffer, 5);
+
+	event_buffer.clear();
+
+	fill_events(event_buffer, 30);
+	get_event_until_end(event_buffer);
+
+	return 0;
+}

+ 31 - 0
engine/tests/threads.cpp

@@ -0,0 +1,31 @@
+#include "Thread.h"
+#include "Log.h"
+
+#include <unistd.h>
+
+using namespace crown;
+
+int32_t first_function(void* ft)
+{
+	Thread* thread = (Thread*)ft;
+
+	while(thread->is_running())
+	{
+		Log::i("I'm in the first thread");
+	}
+
+	return 0;
+}
+	
+int main()
+{
+	Thread ft("first-thread");
+
+	ft.start(first_function, &ft);
+
+	sleep(2);
+
+	ft.stop();
+
+	return 0;
+}

+ 5 - 0
samples/01.hello-world/crown.config

@@ -0,0 +1,5 @@
+{
+	"boot" : "lua/game",
+	"window_width" : 800,
+	"window_height" : 600
+}

+ 1 - 1
utils/crown-android.rb

@@ -32,7 +32,7 @@ $activity			= "CrownActivity"
 $package			= "crown.android"
 $package			= "crown.android"
 
 
 $engine_src 		= "../engine/."
 $engine_src 		= "../engine/."
-$android_src		= "../engine/os/android/*.java"
+$android_src		= "../engine/os/android/java/."
 $config_src			= "../engine/os/android/Config.h"
 $config_src			= "../engine/os/android/Config.h"
 $manifest			= "../engine/os/android/AndroidManifest.xml"
 $manifest			= "../engine/os/android/AndroidManifest.xml"