Преглед изворни кода

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

+ 102 - 20
engine/Device.cpp

@@ -54,6 +54,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Bundle.h"
 #include "TempAllocator.h"
+#include "ResourcePackage.h"
+#include "EventBuffer.h"
 
 #if defined(LINUX) || defined(WINDOWS)
 	#include "BundleCompiler.h"
@@ -81,6 +83,8 @@ Device::Device() :
 
 	m_is_init(false),
 	m_is_running(false),
+	m_is_paused(false),
+	m_is_really_paused(false),
 
 	m_frame_count(0),
 
@@ -97,7 +101,9 @@ Device::Device() :
 	m_resource_manager(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.
 	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
@@ -140,6 +146,14 @@ bool Device::init(int argc, char** argv)
 		}
 	#endif
 
+	init();
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+void Device::init()
+{
 	// Initialize
 	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)();
 	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");
 
@@ -187,6 +202,7 @@ bool Device::init(int argc, char** argv)
 	// Create renderer
 	m_renderer = Renderer::create(m_allocator);
 	m_renderer->init();
+	m_renderer_init_request = false;
 	Log::d("Renderer created.");
 
 	// Create debug renderer
@@ -203,22 +219,27 @@ bool Device::init(int argc, char** argv)
 	m_is_init = true;
 	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
 	m_window->show();
 
-	return true;
+	if (m_quit_after_init == 1)
+	{
+		stop();
+		shutdown();
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -269,7 +290,7 @@ void Device::shutdown()
 	Log::i("Releasing Window...");
 	if (m_window)
 	{
-		CE_DELETE(m_allocator, m_window);
+		CE_DELETE(default_allocator(), m_window);
 	}
 
 	Log::i("Releasing ResourceManager...");
@@ -289,6 +310,14 @@ void Device::shutdown()
 		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_is_init = false;
@@ -300,6 +329,12 @@ bool Device::is_init() const
 	return m_is_init;
 }
 
+//-----------------------------------------------------------------------------
+bool Device::is_paused() const
+{
+	return m_is_paused;
+}
+
 //-----------------------------------------------------------------------------
 Filesystem* Device::filesystem()
 {
@@ -389,6 +424,23 @@ void Device::stop()
 	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
 {
@@ -414,18 +466,48 @@ void Device::frame()
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	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++;
+
+	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 ConsoleServer;
 class BundleCompiler;
+class ResourcePackage;
 
 /// The Engine.
 /// It is the place where to look for accessing all of
@@ -76,6 +77,9 @@ public:
 	/// Returns whether the engine is correctly initialized
 	bool					is_init() const;
 
+	/// Returns wheter the engine is paused
+	bool 					is_paused() const;
+
 	/// Return the number of frames rendered from the first
 	/// call to Device::start()
 	uint64_t				frame_count() const;
@@ -91,9 +95,24 @@ public:
 	/// and normally terminates the program.
 	void					stop();
 
+	/// Pauses the engine
+	void					pause();
+
+	/// Unpauses the engine
+	void					unpause();
+
 	/// Updates all the subsystems
 	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					reload(ResourceId name);
@@ -116,6 +135,7 @@ public:
 	
 private:
 
+	void					init();
 	void					parse_command_line(int argc, char** argv);
 	void					check_preferred_settings();
 	void					read_engine_settings();
@@ -142,6 +162,9 @@ private:
 
 	bool					m_is_init		: 1;
 	bool					m_is_running	: 1;
+	bool					m_is_paused		: 1;
+
+	bool 					m_is_really_paused :1;
 
 	uint64_t				m_frame_count;
 
@@ -166,11 +189,15 @@ private:
 	// Debug subsystems
 	ConsoleServer*			m_console_server;
 
+	bool 					m_renderer_init_request;
+
 private:
 
 	// Disable copying
 	Device(const Device&);
 	Device& operator=(const Device&);
+
+	friend class MainThread;
 };
 
 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);
 	}
 
+	// Copy crown.config to bundle dir
 	DiskFilesystem src_fs(source_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
 	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);
 		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)
 		{
-			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;
 		}
 
-		char out_name[65];
-		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
-
 		Log::i("%s <= %s", out_name, filename);
 
 		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);
 		}
+		else if (resource_type_hash == PACKAGE_TYPE)
+		{
+			result = m_package.compile(source_dir, bundle_dir, filename, out_name);
+		}
 		else
 		{
 			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 "LuaCompiler.h"
 #include "SoundCompiler.h"
+#include "PackageCompiler.h"
 #include "DynamicString.h"
 #include "Vector.h"
 #include "DiskFilesystem.h"
@@ -53,6 +54,7 @@ private:
 	TextureCompiler	m_texture;
 	LuaCompiler 	m_lua;
 	SoundCompiler	m_sound;
+	PackageCompiler m_package;
 };
 
 } // 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.
 */
 
+#include "Config.h"
 #include "LuaCompiler.h"
 #include "LuaResource.h"
 #include "TempAllocator.h"
@@ -34,6 +35,20 @@ OTHER DEALINGS IN THE SOFTWARE.
 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()
 	: 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[] =
 	{
-		"./luajit",
-		"-b",
+		LUAJIT_EXECUTABLE,
+		LUAJIT_FLAGS,
 		res_abs_path.c_str(),
 		bc_abs_path.c_str(),
 		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.
 */
 
-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)
 {
 	TempAllocator1024 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");
 
@@ -234,7 +248,7 @@ JSONElement& JSONElement::key(const char* k)
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 	bool found = false;
 
@@ -262,7 +276,7 @@ bool JSONElement::has_key(const char* k) const
 {
 	TempAllocator1024 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++)
 	{
@@ -285,7 +299,7 @@ bool JSONElement::is_key_unique(const char* k) const
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 	bool found = false;
 

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

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

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

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

+ 38 - 31
engine/input/InputManager.cpp

@@ -27,6 +27,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "InputManager.h"
 #include "OS.h"
 #include "Log.h"
+#include "EventBuffer.h"
+#include "OsEvents.h"
 
 namespace crown
 {
@@ -98,7 +100,9 @@ EventDispatcher* InputManager::get_event_dispatcher()
 //-----------------------------------------------------------------------------
 void InputManager::frame(uint64_t frame_count)
 {
-	OsEvent event;
+	void* event;
+	uint32_t event_type;
+	size_t event_size;
 
 	// Update input devices
 	m_keyboard.m_current_frame = frame_count;
@@ -106,9 +110,12 @@ void InputManager::frame(uint64_t frame_count)
 
 	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:
 			{
@@ -118,12 +125,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_BUTTON_RELEASE:
 			{
 				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;
 
-				if (event.type == OSET_BUTTON_PRESS)
+				if (event_type == OSET_BUTTON_PRESS)
 				{
 					m_mouse.update(frame_count, mouse_event.button, true);
 					m_event_dispatcher.button_pressed(mouse_event);
@@ -140,12 +147,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_KEY_RELEASE:
 			{
 				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;
 
-				if (event.type == OSET_KEY_PRESS)
+				if (event_type == OSET_KEY_PRESS)
 				{
 					m_keyboard.update(frame_count, keyboard_event.key, true);
 					m_event_dispatcher.key_pressed(keyboard_event);
@@ -162,9 +169,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_UP:
 			{
 				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].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_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_event_dispatcher.touch_down(touch_event);
@@ -189,9 +196,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_MOVE:
 			{
 				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].y = touch_event.y;
@@ -204,20 +211,20 @@ void InputManager::frame(uint64_t frame_count)
 
 				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:
 			{
 				break;

+ 29 - 4
engine/lua/LuaDevice.cpp

@@ -25,6 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "Device.h"
+#include "ResourcePackage.h"
 #include "LuaEnvironment.h"
 #include "LuaStack.h"
 
@@ -71,13 +72,37 @@ CE_EXPORT int device_stop(lua_State* /*L*/)
 	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)
 {
-	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

+ 57 - 135
engine/lua/LuaEnvironment.cpp

@@ -44,20 +44,17 @@ CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
 	load_int_setting(*env);
 	load_float_setting(*env);
 	load_string_setting(*env);
-
 	load_vec2(*env);
 	load_vec3(*env);
 	load_mat4(*env);
 	load_quat(*env);
 	load_math(*env);
-
 	load_mouse(*env);
 	load_keyboard(*env);
 	load_accelerometer(*env);
-
 	load_device(*env);
-
 	load_window(*env);
+	load_resource_package(*env);
 
 	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);
 
-	// 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;
 }
 
@@ -135,37 +117,61 @@ void LuaEnvironment::init()
 void LuaEnvironment::shutdown()
 {
 	lua_close(m_state);
-
 	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);
 
@@ -174,6 +180,8 @@ void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 	va_list vl;
 	va_start(vl, argc);
 
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
 	lua_getglobal(m_state, func);
 
 	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);
 
-	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

+ 13 - 19
engine/lua/LuaEnvironment.h

@@ -53,16 +53,9 @@ public:
 	/// Close Lua state and shutdown LuaEnvironment
 	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,
 	/// @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
 	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:
 
-	void					lua_error();
 	// Disable copying
 							LuaEnvironment(const LuaEnvironment&);
 	LuaEnvironment& 		operator=(const LuaEnvironment&);
@@ -87,14 +88,6 @@ private:
 
 	/// LuaEnvironment is used right now?
 	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_device(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
+void load_resource_package(LuaEnvironment& env);
 
 } // 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
 
 Permission is hereby granted, free of charge, to any person
@@ -28,46 +29,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 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 "Vector.h"
 #include "DynamicString.h"
+#include "EventBuffer.h"
 
 namespace crown
 {
@@ -46,6 +47,8 @@ namespace crown
 
 	#define snprintf _snprintf
 
+	#define Thread os::Thread
+
 	#undef MK_SHIFT
 	#undef MK_ALT
 #elif defined(ANDROID)
@@ -105,6 +108,9 @@ bool			delete_directory(const char* path);
 /// Does not follow symbolic links.
 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
 //-----------------------------------------------------------------------------
@@ -150,47 +156,11 @@ void*			lookup_symbol(void* library, const char* name);
 /// @a args[n] is NULL.
 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
 

+ 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 "Device.h"
+#include "Renderer.h"
+#include "Log.h"
 
 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" };
 
@@ -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();
 }
 
 //-----------------------------------------------------------------------------
-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();
 }
 
 //-----------------------------------------------------------------------------
-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();
 }
 
+//-----------------------------------------------------------------------------
+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

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

@@ -39,6 +39,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <unistd.h>
 
 #include "OS.h"
+#include "OsEvents.h"
 #include "Assert.h"
 #include "StringUtils.h"
 
@@ -47,9 +48,7 @@ namespace crown
 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, ...)
@@ -201,6 +200,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	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()
 {
@@ -285,33 +308,30 @@ void execute_process(const char* args[])
 	}
 }
 
-
 } // 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

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

@@ -59,13 +59,13 @@ void ApkFilesystem::close(File* file)
 //-----------------------------------------------------------------------------
 bool ApkFilesystem::is_directory(const char* path)
 {
-	return false;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
 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_MINOR 1 
-#define CROWN_VERSION_MICRO 11 
+#define CROWN_VERSION_MICRO 11
 
-#define ANDROID
+#define CROWN_DEVELOPMENT
 
 #ifdef ANDROID
 	#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.
 */
 
-#include <android/native_window_jni.h>
-
 #include "OsWindow.h"
 #include "GLContext.h"
 #include "Assert.h"
+#include "Log.h"
 
 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()
 {
-	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()
 {
-	// 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
 	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

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

@@ -28,6 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <sys/types.h>
 #include <android/native_window.h>
+#include <android/native_window_jni.h>
 
 namespace crown
 {
@@ -81,8 +82,6 @@ public:
 
 private:
 
-	ANativeWindow*	m_window;
-
 	uint32_t		m_x;
 	uint32_t		m_y;
 	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.widget.Toast;
 import android.content.res.AssetManager;
+import android.view.View;
 import android.view.Surface;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
@@ -49,9 +50,8 @@ import crown.android.CrownEnum;
 */
 public class CrownActivity extends Activity
 {
-
 	// Debug
-	public static String TAG = "CrownActivity";
+	public static String TAG = "crown";
 
 	// Resource attributes
     static AssetManager 		mAssetManager;
@@ -60,8 +60,8 @@ public class CrownActivity extends Activity
 	private CrownTouch 			mTouch;
 	private CrownSensor			mSensor;
 
-	// Graphic attributes
-	static CrownSurfaceView		mWindow;
+	private CrownSurfaceView 	mView;
+
 
 //-----------------------------------------------------------------------------
     public void onCreate(Bundle savedInstanceState)
@@ -73,26 +73,15 @@ public class CrownActivity extends Activity
 		CrownLib.initAssetManager(mAssetManager);
 
 		// init Native Window
-        mWindow = new CrownSurfaceView(this);
-        setContentView(mWindow);
+		mView = new CrownSurfaceView(this);
+        setContentView(mView);
 
 		// Init Input
 		mTouch = new CrownTouch(this);
 		mSensor = new CrownSensor(this);
-    }
-
-//-----------------------------------------------------------------------------
-	public void onStart()
-	{
-		super.onStart();
 
-	}
-
-//-----------------------------------------------------------------------------
-	public void onRestart()
-	{
-		super.onRestart();
-	}
+		Log.i(TAG, "Crown Activity created");
+    }
 
 //-----------------------------------------------------------------------------
 	public void onResume()
@@ -100,31 +89,20 @@ public class CrownActivity extends Activity
 		super.onResume();
 		
 		// init accelerometer
-		if (!mSensor.startListening(this))
-		{
-			finish();
-		}
+		mSensor.startListening(this);
+
+		Log.i(TAG, "Crown Activity resumed");
 	}
 
 //-----------------------------------------------------------------------------
 	public void onPause()
 	{
 		super.onPause();
-	}
-
-//-----------------------------------------------------------------------------
-	public void onStop()
-	{
-		super.onStop();
 
 		// stop accelerometer
 		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);
         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
-	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 		shutdown();
-	public static native boolean 	isInit();
-	public static native boolean	isRunning();
 
 	// AssetManager functions
 	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
-	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.
 */
 
-#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();
 
-                    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[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.SurfaceView;
 import android.view.SurfaceHolder;
+import android.graphics.PixelFormat;
+import android.util.Log;
 
 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)
 	{
 		super(context);
 
-		this.getHolder().addCallback(this);
-
-		mMainThread = new MainThread(getHolder(), this);
+		getHolder().addCallback(this);
 
 		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
 	public void surfaceCreated(SurfaceHolder holder) 
 	{
-		mMainThread.start();
+		Log.d(TAG, "Crown Surface created");
+
+		if (!mSurfaceCreated)
+		{
+			mSurfaceCreated = true;
+
+			createThread(holder);
+		}
 	}
 
 	//-----------------------------------------------------------------------------
 	@Override
 	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
 */
 
-//TODO: gestures doesn't work...fix them
 public class CrownTouch
 {
-	private boolean 				isListening;
+	private boolean isListening;
 
 //-----------------------------------------------------------------------------------
 	public CrownTouch(Context context)
@@ -63,7 +62,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_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;			
 			}
 
@@ -72,7 +71,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_OUTSIDE:
 			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;			
 			}
 			
@@ -80,7 +79,7 @@ public class CrownTouch
 			{
 				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;

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

@@ -206,6 +206,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	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()
 {

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

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "OS.h"
 #include "GLContext.h"
 #include "StringUtils.h"
+#include "OsEvents.h"
 
 namespace crown
 {
@@ -271,8 +272,8 @@ void OsWindow::frame()
 {
 	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))
 	{
@@ -293,38 +294,38 @@ void OsWindow::frame()
 			{
 				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)
 				{
 					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;
 					}
 					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;
 					}
 					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;
 			}
-			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 KeyRelease:
 			{
@@ -353,10 +354,10 @@ void OsWindow::frame()
 
 				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
 //				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"
 
-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::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())
 	{
 		engine->frame();
@@ -45,6 +56,26 @@ int main(int argc, char** argv)
 
 	engine->shutdown();
 
+	thread.stop();
+
 	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
 
 #include <pthread.h>
+#include <cstring>
 
 #include "Types.h"
 #include "Mutex.h"
@@ -56,4 +57,38 @@ private:
 	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

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

@@ -27,9 +27,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <pthread.h>
+#include <cstring>
 
 #include "Types.h"
 #include "OS.h"
+#include "Assert.h"
 
 namespace crown
 {
@@ -57,4 +59,38 @@ private:
 	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

+ 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.
 */
 
-#include <string.h>
+#pragma once
 
+#include <errno.h>
+#include <semaphore.h>
+
+#include "Assert.h"
 #include "Mutex.h"
+#include "Cond.h"
+#include "Log.h"
 
 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
 
-#include <pthread.h>
+#include <cstring>
 
+#include "Assert.h"
 #include "Types.h"
+#include "Semaphore.h"
+#include "Log.h"
 
 namespace crown
 {
 
-typedef void* (*ThreadFunction)(void*);
+typedef int32_t (*ThreadFunction)(void*);
 
 class Thread
 {
 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");
 }
 
+void* Thread::background_proc(void* thiz)
+{
+	Thread* thread  = (Thread*)thiz;
+
+	thread->run();
+
+	thread->m_is_running = false;
+
+	return NULL;
+}
+
+
 } // namespace os
 } // namespace crown

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

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <windows.h>
 #include <process.h>
 #include <WinBase.h>
+
 #include "Types.h"
 #include "OS.h"
 
@@ -43,16 +44,32 @@ class Thread
 {
 public:
 
-					Thread(os::ThreadFunction f, LPVOID params, const char* name);
+					Thread(const char* name);
 					~Thread();
 
+	const char*		name() const;
+
 	void			join();
 	void			detach();
 
+	bool			is_running() const;
+	bool			is_terminating() const;
+
+	void			start();
+	void			stop();
+
+	virtual int32_t	run();
+
 private:
 
-	HANDLE			m_thread;
+	static void*	background_proc(void* thiz);
+
+private:
+	
 	const char*		m_name;
+	bool			m_is_running;
+	bool			m_is_terminating;
+	HANDLE			m_thread;
 };
 
 } // 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 ((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;
 	fileAttr = GetFileAttributes(path);
@@ -139,7 +142,7 @@ bool is_direcotry(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()
@@ -271,5 +319,38 @@ void* lookup_symbol(void* library, const char* name)
 	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 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() :
+	Renderer(),
+
 	m_max_texture_size(0),
 	m_max_texture_units(0),
 	m_max_vertex_indices(0),
@@ -178,15 +180,11 @@ void GLESRenderer::init()
 	GL_CHECK(glDisable(GL_DITHER));
 
 	Log::i("OpenGL Renderer initialized.");
-
-	load_default_shaders();
 }
 
 //-----------------------------------------------------------------------------
 void GLESRenderer::shutdown()
 {
-	unload_default_shaders();
-
 	m_context.destroy_context();
 }
 
@@ -759,11 +757,12 @@ void GLESRenderer::frame()
 {
 	// Clear frame/depth buffer
 	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_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());
 

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

@@ -26,76 +26,116 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <GLES2/gl2.h>
 
+#include "Config.h"
 #include "Assert.h"
 #include "GLContext.h"
+#include "Log.h"
 
 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()
 {
-	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()
 {
- 	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()
 {
-   	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
 
 #include <EGL/egl.h>
-#include <android/native_window.h>
 
 namespace crown
 {
 
-void set_android_window(ANativeWindow* window);
-
 class GLContext
 {
 public:
@@ -47,11 +44,11 @@ public:
 private:
 
 	EGLDisplay 		display;
-    EGLSurface 		surface;
-    EGLConfig 		config;
-    EGLContext 		context;
+	EGLSurface 		surface;
+	EGLConfig 		config;
+	EGLContext 		context;
 
-    int32_t			num_configs;
+	int32_t			num_configs;
 };
 
 } // namespace crown

+ 1 - 0
engine/resource/FileBundle.cpp

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

+ 0 - 1
engine/resource/LuaResource.h

@@ -31,7 +31,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "Allocator.h"
 #include "File.h"
-#include "Log.h"
 
 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 SOUND_EXTENSION			= "sound";
 const char* const CONFIG_EXTENSION			= "config";
+const char* const PACKAGE_EXTENSION			= "package";
 
 const uint32_t TEXTURE_TYPE					= 0xDEED4F7;
 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 SOUND_TYPE					= 0xD196AB6E;
 const uint32_t CONFIG_TYPE					= 0x17DEA5E1;
+const uint32_t PACKAGE_TYPE					= 0xC0A2212C;
 
 
 /// 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) :
-	Thread("resource-loader"),
+	m_thread("resource-loader"),
 	m_bundle(bundle),
 	m_resource_heap(resource_heap),
 	m_num_requests(0),
@@ -94,7 +94,7 @@ void* ResourceLoader::load_resource_data(LoadResourceId id) const
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 {
-	while (!is_terminating())
+	while (m_thread.is_running())
 	{
 		m_requests_mutex.lock();
 		while (m_requests.empty())

+ 21 - 1
engine/resource/ResourceLoader.h

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "List.h"
 #include "Mutex.h"
 #include "Cond.h"
+#include "OS.h"
 
 namespace crown
 {
@@ -65,7 +66,7 @@ struct LoadResourceData
 };
 
 /// Loads resources in a background thread.
-class ResourceLoader : public Thread
+class ResourceLoader
 {
 public:
 
@@ -85,8 +86,27 @@ public:
 	// Loads resources in the loading queue.
 	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:
 
+	Thread					m_thread;
+
 	// Whether to look for resources
 	Bundle&					m_bundle;
 

+ 1 - 0
engine/resource/ResourceManager.h

@@ -122,6 +122,7 @@ private:
 
 private:
 
+	friend class			ResourcePackage;
 	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 "MeshResource.h"
 #include "SoundResource.h"
+#include "PackageResource.h"
 
 namespace crown
 {
@@ -39,6 +40,7 @@ static const ResourceCallback RESOURCE_CALLBACK_REGISTRY[] =
 	{ TEXTURE_TYPE, TextureResource::load, TextureResource::unload, TextureResource::online, TextureResource::offline },
 	{ MESH_TYPE, MeshResource::load, MeshResource::unload, MeshResource::online, MeshResource::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 }
 };
 

+ 6 - 1
engine/tests/CMakeLists.txt

@@ -11,6 +11,8 @@ add_executable(strings strings.cpp)
 add_executable(paths paths.cpp)
 add_executable(dynamic-strings dynamic-strings.cpp)
 add_executable(json json.cpp)
+add_executable(events events.cpp)
+add_executable(threads threads.cpp)
 
 target_link_libraries(allocators crown)
 target_link_libraries(containers crown)
@@ -19,6 +21,8 @@ target_link_libraries(strings crown)
 target_link_libraries(paths crown)
 target_link_libraries(dynamic-strings 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(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(dynamic-string-test ${EXECUTABLE_OUTPUT_PATH}/dynamic-strings)
 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"
 
 $engine_src 		= "../engine/."
-$android_src		= "../engine/os/android/*.java"
+$android_src		= "../engine/os/android/java/."
 $config_src			= "../engine/os/android/Config.h"
 $manifest			= "../engine/os/android/AndroidManifest.xml"