Browse Source

Merge branch 'master' into world

Conflicts:
	engine/lua/LuaEnvironment.cpp
	engine/lua/LuaEnvironment.h
	engine/lua/LuaStack.cpp
	engine/lua/LuaStack.h
Daniele Bartolini 12 years ago
parent
commit
966b87c1bf
100 changed files with 6949 additions and 4084 deletions
  1. 23 7
      BUILD.txt
  2. 55 11
      CMakeLists.txt
  3. 39 45
      engine/Android.mk
  4. 138 83
      engine/CMakeLists.txt
  5. 14 0
      engine/Config.h.in
  6. 0 130
      engine/ConsoleServer.cpp
  7. 0 76
      engine/ConsoleServer.h
  8. 10 11
      engine/Crown.h
  9. 262 298
      engine/Device.cpp
  10. 62 47
      engine/Device.h
  11. 0 204
      engine/FPSSystem.cpp
  12. 4 5
      engine/SceneGraph.cpp
  13. 1 1
      engine/SceneGraph.h
  14. 249 0
      engine/audio/OggDecoder.h
  15. 158 0
      engine/audio/SoundRenderer.h
  16. 352 0
      engine/audio/al/ALRenderer.cpp
  17. 417 0
      engine/audio/al/ALRenderer.h
  18. 364 0
      engine/audio/sles/SLESRenderer.cpp
  19. 365 0
      engine/audio/sles/SLESRenderer.h
  20. 176 0
      engine/compilers/BundleCompiler.cpp
  21. 19 25
      engine/compilers/BundleCompiler.h
  22. 13 17
      engine/compilers/Compiler.cpp
  23. 5 5
      engine/compilers/Compiler.h
  24. 117 0
      engine/compilers/lua/LuaCompiler.cpp
  25. 8 8
      engine/compilers/lua/LuaCompiler.h
  26. 199 0
      engine/compilers/mesh/MeshCompiler.cpp
  27. 35 9
      engine/compilers/mesh/MeshCompiler.h
  28. 139 0
      engine/compilers/package/PackageCompiler.cpp
  29. 12 17
      engine/compilers/package/PackageCompiler.h
  30. 171 0
      engine/compilers/sound/SoundCompiler.cpp
  31. 37 39
      engine/compilers/sound/SoundCompiler.h
  32. 38 40
      engine/compilers/texture/TextureCompiler.cpp
  33. 8 8
      engine/compilers/texture/TextureCompiler.h
  34. 1 1
      engine/core/Args.h
  35. 4 2
      engine/core/Assert.h
  36. 27 25
      engine/core/Log.cpp
  37. 4 4
      engine/core/Log.h
  38. 2 0
      engine/core/Types.h
  39. 37 40
      engine/core/containers/IdTable.h
  40. 16 24
      engine/core/containers/List.h
  41. 88 109
      engine/core/containers/PriorityQueue.h
  42. 47 4
      engine/core/containers/Queue.h
  43. 426 0
      engine/core/containers/Vector.h
  44. 0 102
      engine/core/filesystem/BinaryReader.cpp
  45. 66 10
      engine/core/filesystem/BinaryReader.h
  46. 50 10
      engine/core/filesystem/BinaryWriter.h
  47. 2 2
      engine/core/filesystem/DiskFile.cpp
  48. 168 0
      engine/core/filesystem/DiskFilesystem.cpp
  49. 91 0
      engine/core/filesystem/DiskFilesystem.h
  50. 0 205
      engine/core/filesystem/Filesystem.cpp
  51. 26 67
      engine/core/filesystem/Filesystem.h
  52. 0 64
      engine/core/filesystem/TextReader.cpp
  53. 27 3
      engine/core/filesystem/TextReader.h
  54. 10 4
      engine/core/filesystem/TextWriter.h
  55. 260 28
      engine/core/json/JSONParser.cpp
  56. 44 10
      engine/core/json/JSONParser.h
  57. 0 38
      engine/core/mem/Allocator.cpp
  58. 1 1
      engine/core/mem/Allocator.h
  59. 15 5
      engine/core/mem/LinearAllocator.cpp
  60. 2 0
      engine/core/mem/LinearAllocator.h
  61. 43 16
      engine/core/mem/Memory.cpp
  62. 27 18
      engine/core/mem/Memory.h
  63. 1 1
      engine/core/mem/ProxyAllocator.h
  64. 229 0
      engine/core/strings/DynamicString.h
  65. 56 1
      engine/core/strings/Hash.h
  66. 154 0
      engine/core/strings/StringStream.h
  67. 7 12
      engine/core/strings/StringUtils.h
  68. 0 44
      engine/input/Accelerometer.cpp
  69. 11 24
      engine/input/Accelerometer.h
  70. 0 178
      engine/input/EventDispatcher.cpp
  71. 0 79
      engine/input/EventDispatcher.h
  72. 0 230
      engine/input/InputManager.cpp
  73. 0 74
      engine/input/InputManager.h
  74. 129 131
      engine/input/KeyCode.h
  75. 0 90
      engine/input/Keyboard.cpp
  76. 62 59
      engine/input/Keyboard.h
  77. 0 131
      engine/input/Mouse.cpp
  78. 93 51
      engine/input/Mouse.h
  79. 0 66
      engine/input/Touch.cpp
  80. 22 31
      engine/input/Touch.h
  81. 29 4
      engine/lua/LuaDevice.cpp
  82. 141 218
      engine/lua/LuaEnvironment.cpp
  83. 28 53
      engine/lua/LuaEnvironment.h
  84. 114 119
      engine/lua/LuaKeyboard.cpp
  85. 5 5
      engine/lua/LuaMouse.cpp
  86. 32 32
      engine/lua/LuaResourcePackage.cpp
  87. 42 160
      engine/lua/LuaStack.cpp
  88. 121 34
      engine/lua/LuaStack.h
  89. 14 28
      engine/lua/LuaWindow.cpp
  90. 12 35
      engine/os/NetAddress.h
  91. 0 73
      engine/os/OS.cpp
  92. 57 54
      engine/os/OS.h
  93. 142 0
      engine/os/OsEventQueue.h
  94. 74 30
      engine/os/OsTypes.h
  95. 88 8
      engine/os/android/AndroidDevice.cpp
  96. 93 23
      engine/os/android/AndroidOS.cpp
  97. 57 48
      engine/os/android/ApkFile.cpp
  98. 40 31
      engine/os/android/ApkFile.h
  99. 44 49
      engine/os/android/ApkFilesystem.cpp
  100. 78 0
      engine/os/android/ApkFilesystem.h

+ 23 - 7
BUILD.txt

@@ -40,27 +40,43 @@ engine on the currently supported platforms.
 
 		1. $ mkdir build
 		2. $ cd build
-		3. $ cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/your/install/dir -DCROWN_ARCH=<arch>
-		   (read below for valid architecture strings)
+		3. $ cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/your/install/dir -DCROWN_BUILD=<build>
+		   (read below for valid build strings)
 		4. $ make
 		5. $ make install
 
-		'CROWN_ARCH' valid values right now are:
+		'CROWN_BUILD' valid values right now are:
+
+ 			* linux-debug-32
+ 			* linux-development-32
+ 			* linux-release-32
+ 			* linux-debug-64
+ 			* linux-development-64
+ 			* linux-release-64
 
-	 		* Linux: "x86" or "x86_64"
 
 	- Windows
 
 		1. Create a folder named 'build'
 		2. Open a terminal and:
 		3. cd build
-		4. cmake.exe .. -DCMAKE_INSTALL_PREFIX=C:/your/install/dir -DCROWN_ARCH=win64
+		4. cmake.exe .. -DCMAKE_INSTALL_PREFIX=C:/your/install/dir -DCROWN_BUILD=<build>
 		5. Open the generated Visual Studio solution and build/install from there
 
+		'CROWN_BUILD' valid values right now are:
+
+ 			* windows-debug-32
+ 			* windows-development-32
+ 			* windows-release-32
+ 			* windows-debug-64
+ 			* windows-development-64
+ 			* windows-release-64
+
+
 	- Android
 
-		Building for Android is a bit involved process at the moment, we are working hard
-		to improve the system.
+		1. $ cd utils
+		2. $ ruby crown-android.rb --target <android-target> --name <project-name> --path <project-path>
 
 	You can also use the GUI front-end of CMake which can, less or more, simplify
 	the overall 'complexity' of building from the terminal.

+ 55 - 11
CMakeLists.txt

@@ -4,30 +4,74 @@ project(crown)
 
 set (CROWN_VERSION_MAJOR 0)
 set (CROWN_VERSION_MINOR 1)
-set (CROWN_VERSION_MICRO 9)
+set (CROWN_VERSION_MICRO 13)
 
 option (CROWN_BUILD_SAMPLES "Whether to build the samples" ON)
 option (CROWN_BUILD_TOOLS "Whether to build the tools" ON)
 option (CROWN_BUILD_TESTS "Whether to build unit tests" ON)
 
-# always debug mode for now
-set (CROWN_DEBUG 1)
-
-# detect operating system
-if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+# build configuration variables
+if (CROWN_BUILD MATCHES "linux-debug-32")
+	set (LINUX 1)
+	set (CROWN_DEBUG 1)
+	set (CROWN_ARCH "x86")
+elseif (CROWN_BUILD MATCHES "linux-development-32")
+	set (LINUX 1)
+	set (CROWN_DEVELOPMENT 1)
+	set (CROWN_ARCH "x86")
+elseif (CROWN_BUILD MATCHES "linux-release-32")
+	set (LINUX 1)
+	set (CROWN_RELEASE 1)
+	set (CROWN_ARCH "x86")
+elseif (CROWN_BUILD MATCHES "linux-debug-64")
+	set (LINUX 1)
+	set (CROWN_DEBUG 1)
+	set (CROWN_ARCH "x86_64")
+elseif (CROWN_BUILD MATCHES "linux-development-64")
+	set (LINUX 1)
+	set (CROWN_DEVELOPMENT 1)
+	set (CROWN_ARCH "x86_64")
+elseif (CROWN_BUILD MATCHES "linux-release-64")
 	set (LINUX 1)
-endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+	set (CROWN_RELEASE 1)
+	set (CROWN_ARCH "x86_64")
+elseif (CROWN_BUILD MATCHES "windows-debug-32")
+	set (WINDOWS 1)
+	set (CROWN_DEBUG 1)
+	set (CROWN_ARCH "win32")
+elseif (CROWN_BUILD MATCHES "windows-development-32")
+	set (WINDOWS 1)
+	set (CROWN_DEVELOPMENT 1)
+	set (CROWN_ARCH "win32")
+elseif (CROWN_BUILD MATCHES "windows-release-32")
+	set (WINDOWS 1)
+	set (CROWN_RELEASE 1)
+	set (CROWN_ARCH "win32")
+elseif (CROWN_BUILD MATCHES "windows-debug-64")
+	set (WINDOWS 1)
+	set (CROWN_DEBUG 1)
+	set (CROWN_ARCH "win64")
+elseif (CROWN_BUILD MATCHES "windows-development-64")
+	set (WINDOWS 1)
+	set (CROWN_DEVELOPMENT 1)
+	set (CROWN_ARCH "win64")
+elseif (CROWN_BUILD MATCHES "windows-release-64")
+	set (WINDOWS 1)
+	set (CROWN_RELEASE 1)
+	set (CROWN_ARCH "win64")
+else ()
+	message (FATAL_ERROR "Wrong build configuration")
+endif (CROWN_BUILD MATCHES "linux-debug-32")
 
-if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-	set(WINDOWS 1)
-endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+# executable name
+set (CROWN_EXECUTABLE_NAME crown-${CROWN_BUILD})
 
 # always build the engine
 add_subdirectory(engine)
 
 # select optional projects to build
 if (CROWN_BUILD_TOOLS)
-	add_subdirectory(tools)
+	#add_subdirectory(tools)
 endif (CROWN_BUILD_TOOLS)
 
 if (CROWN_BUILD_SAMPLES)

+ 39 - 45
engine/Android.mk

@@ -10,6 +10,21 @@ LOCAL_MODULE := luajit-5.1
 LOCAL_SRC_FILES := libluajit-5.1.so
 include $(PREBUILT_SHARED_LIBRARY)
 
+###############################################################################
+# libogg & libvorbis
+###############################################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ogg
+LOCAL_SRC_FILES := libogg.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := vorbis
+LOCAL_SRC_FILES := libvorbis.a
+include $(PREBUILT_STATIC_LIBRARY)
+
 ###############################################################################
 # libcrown
 ###############################################################################
@@ -24,15 +39,11 @@ LOCAL_SRC_FILES :=\
 	core/compressors/ZipCompressor.cpp\
 	core/containers/Generic.cpp\
 \
-	core/filesystem/BinaryReader.cpp\
-	core/filesystem/BinaryWriter.cpp\
-	core/filesystem/DiskFile.cpp\
 	core/filesystem/File.cpp\
-	core/filesystem/Filesystem.cpp\
-	core/filesystem/TextReader.cpp\
-	core/filesystem/TextWriter.cpp\
+	core/filesystem/DiskFile.cpp\
+	core/filesystem/DiskFilesystem.cpp\
 \
-	core/json/JSONParser.cpp
+	core/json/JSONParser.cpp\
 \
 	core/math/Color4.cpp\
 	core/math/Mat3.cpp\
@@ -43,7 +54,6 @@ LOCAL_SRC_FILES :=\
 	core/math/Vec3.cpp\
 	core/math/Vec4.cpp\
 \
-	core/mem/Allocator.cpp\
 	core/mem/HeapAllocator.cpp\
 	core/mem/LinearAllocator.cpp\
 	core/mem/ProxyAllocator.cpp\
@@ -57,48 +67,28 @@ LOCAL_SRC_FILES :=\
 	core/Args.cpp\
 	core/Log.cpp\
 \
-	input/Accelerometer.cpp\
-	input/Keyboard.cpp\
-	input/Mouse.cpp\
-	input/Touch.cpp\
-	input/EventDispatcher.cpp\
-	input/InputManager.cpp\
-\
-	network/BitMessage.cpp\
-\
-	os/OS.cpp\
 	os/android/AndroidOS.cpp\
 	os/android/AndroidDevice.cpp\
 	os/android/OsWindow.cpp\
+	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\
 \
-	renderers/gles/GLESRenderer.cpp\
-	renderers/gles/GLESUtils.cpp\
-	renderers/gles/egl/GLContext.cpp\
+	renderers/gl/GLRenderer.cpp\
+	renderers/gl/egl/GLContext.cpp\
 	renderers/DebugRenderer.cpp\
-	renderers/PixelFormat.cpp\
-	renderers/VertexFormat.cpp\
 \
-	resource/ArchiveBundle.cpp\
 	resource/FileBundle.cpp\
-	resource/FontResource.cpp\
-	resource/MaterialResource.cpp\
-	resource/PixelShaderResource.cpp\
 	resource/ResourceLoader.cpp\
 	resource/ResourceManager.cpp\
-	resource/TextResource.cpp\
-	resource/TextureResource.cpp\
-	resource/VertexShaderResource.cpp\
+	resource/ResourceRegistry.cpp\
+\
+	rpc/RPCServer.cpp\
+	rpc/RPCHandler.cpp\
 \
 	lua/LuaStack.cpp\
 	lua/LuaEnvironment.cpp\
 	lua/LuaAccelerometer.cpp\
-	lua/LuaCamera.cpp\
 	lua/LuaDevice.cpp\
 	lua/LuaKeyboard.cpp\
 	lua/LuaMat4.cpp\
@@ -112,11 +102,12 @@ LOCAL_SRC_FILES :=\
 	lua/LuaIntSetting.cpp\
 	lua/LuaFloatSetting.cpp\
 	lua/LuaStringSetting.cpp\
+	lua/LuaResourcePackage.cpp\
+\
+	audio/sles/SLESRenderer.cpp\
 \
 	Camera.cpp\
 	Device.cpp\
-	FPSSystem.cpp\
-	ConsoleServer.cpp\
 \
 
 LOCAL_C_INCLUDES	:=\
@@ -132,22 +123,25 @@ LOCAL_C_INCLUDES	:=\
 	$(LOCAL_PATH)/core/json\
 	$(LOCAL_PATH)/core/settings\
 	$(LOCAL_PATH)/core/strings\
+	$(LOCAL_PATH)/resource\
+	$(LOCAL_PATH)/rpc\
 	$(LOCAL_PATH)/input\
 	$(LOCAL_PATH)/lua\
+	$(LOCAL_PATH)/audio\
 	$(LOCAL_PATH)/network\
 	$(LOCAL_PATH)/os\
 	$(LOCAL_PATH)/os/android\
 	$(LOCAL_PATH)/os/posix\
 	$(LOCAL_PATH)/renderers\
-	$(LOCAL_PATH)/renderers/gles\
-	$(LOCAL_PATH)/renderers/gles/egl\
-	$(LOCAL_PATH)/third/luajit/include/luajit-2.0\
-
+	$(LOCAL_PATH)/renderers/gl\
+	$(LOCAL_PATH)/renderers/gl/egl\
+	$(LOCAL_PATH)/third/ARMv7/luajit/include/luajit-2.0\
+	$(LOCAL_PATH)/third/ARMv7/oggvorbis/include\
+	
 LOCAL_CPPFLAGS	:= -g -fexceptions -std=c++03 -ansi -pedantic -Wall -Wextra -Wno-long-long -Wno-variadic-macros
-LOCAL_LDLIBS	:= -llog -landroid -lEGL -lGLESv2 -lz 
+LOCAL_LDLIBS	:= -llog -landroid -lEGL -lGLESv2 -lz -lOpenSLES
 LOCAL_SHARED_LIBRARIES := luajit-5.1
-LOCAL_STATIC_LIBRARIES := android_native_app_glue
+LOCAL_STATIC_LIBRARIES := android_native_app_glue vorbis ogg
 include $(BUILD_SHARED_LIBRARY)
 
 $(call import-module,android/native_app_glue)
-

+ 138 - 83
engine/CMakeLists.txt

@@ -25,7 +25,9 @@ endif (CROWN_ARCH MATCHES "ARMv7")
 set (CROWN_THIRD_INCLUDES
 	${CROWN_THIRD}/luajit/include/luajit-2.0
 	${CROWN_THIRD}/glew-1.9.0/include
-	${CROWN_THIRD}/zlib/include	
+	${CROWN_THIRD}/zlib/include
+	${CROWN_THIRD}/oggvorbis/include
+	${CROWN_THIRD}/openAL/include
 )
 
 # architecture dependent libraries
@@ -33,6 +35,8 @@ set (CROWN_THIRD_LIBS
 	${CROWN_THIRD}/luajit/lib
 	${CROWN_THIRD}/glew-1.9.0/lib
 	${CROWN_THIRD}/zlib/lib
+	${CROWN_THIRD}/oggvorbis/lib
+	${CROWN_THIRD}/openAL/lib
 )
 
 add_subdirectory(${CROWN_THIRD})
@@ -54,15 +58,21 @@ set (CROWN_INCLUDES
 	${CMAKE_SOURCE_DIR}/engine/input
 	${CMAKE_SOURCE_DIR}/engine/renderers
 	${CMAKE_SOURCE_DIR}/engine/resource
+	${CMAKE_SOURCE_DIR}/engine/rpc
 	${CMAKE_SOURCE_DIR}/engine/network
 	${CMAKE_SOURCE_DIR}/engine/lua
+	${CMAKE_SOURCE_DIR}/engine/audio
+	${CMAKE_SOURCE_DIR}/engine/compilers
+	${CMAKE_SOURCE_DIR}/engine/compilers/lua
+	${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
-	ConsoleServer.cpp
-	FPSSystem.cpp
 )
 
 set (HEADERS
@@ -70,8 +80,6 @@ set (HEADERS
 	Config.h
 	Crown.h
 	Device.h
-	ConsoleServer.h
-	FPSSystem.h
 )
 
 set (CORE_SRC
@@ -106,9 +114,11 @@ set (CONTAINERS_SRC
 
 set (CONTAINERS_HEADERS
 	core/containers/Queue.h
+	core/containers/PriorityQueue.h
 	core/containers/Map.h
 	core/containers/Generic.h
 	core/containers/List.h
+	core/containers/Vector.h
 	core/containers/RBTree.h
 	core/containers/IdTable.h
 )
@@ -144,28 +154,21 @@ set (MATH_HEADERS
 )
 
 set (FILESYSTEM_SRC
-	core/filesystem/DiskFile.cpp
 	core/filesystem/File.cpp
-	
-	core/filesystem/BinaryReader.cpp
-	core/filesystem/BinaryWriter.cpp
-	core/filesystem/TextReader.cpp
-	core/filesystem/TextWriter.cpp
-
-	core/filesystem/Filesystem.cpp
+	core/filesystem/DiskFile.cpp
+	core/filesystem/DiskFilesystem.cpp
 )
 
 set (FILESYSTEM_HEADERS
-	core/filesystem/DiskFile.h
-	core/filesystem/NullFile.h
 	core/filesystem/File.h
-
+	core/filesystem/NullFile.h
+	core/filesystem/DiskFile.h
 	core/filesystem/BinaryReader.h
 	core/filesystem/BinaryWriter.h
 	core/filesystem/TextReader.h
 	core/filesystem/TextWriter.h
-
 	core/filesystem/Filesystem.h
+	core/filesystem/DiskFilesystem.h
 )
 
 set (JSON_SRC
@@ -181,13 +184,14 @@ set (STRINGS_SRC
 
 set (STRINGS_HEADERS
 	core/strings/Path.h
-	core/strings/String.h
+	core/strings/StringUtils.h
+	core/strings/StringStream.h
 	core/strings/Hash.h
+	core/strings/DynamicString.h
 )
 
 set (MEM_SRC
 	core/mem/Memory.cpp
-	core/mem/Allocator.cpp
 	core/mem/HeapAllocator.cpp
 	core/mem/LinearAllocator.cpp
 	core/mem/StackAllocator.cpp
@@ -226,17 +230,9 @@ set (SETTINGS_HEADERS
 )
 
 set (INPUT_SRC
-	input/EventDispatcher.cpp
-	input/InputManager.cpp
-	input/Keyboard.cpp
-	input/Mouse.cpp
-	input/Touch.cpp
-	input/Accelerometer.cpp
 )
 
 set (INPUT_HEADERS
-	input/EventDispatcher.h
-	input/InputManager.h
 	input/Keyboard.h
 	input/KeyCode.h
 	input/Mouse.h
@@ -253,59 +249,68 @@ set (NETWORK_HEADERS
 
 set (RENDERERS_SRC
 	renderers/DebugRenderer.cpp
-	renderers/PixelFormat.cpp
-	renderers/VertexFormat.cpp
 )
 
 set (RENDERERS_HEADERS
 	renderers/Renderer.h
-	renderers/IndexBuffer.h
-	renderers/VertexBuffer.h
-	renderers/Material.h
-	renderers/Texture.h
+	renderers/RenderContext.h
 	renderers/DebugRenderer.h
 	renderers/PixelFormat.h
 	renderers/VertexFormat.h
 )
 
 set (RESOURCE_SRC
-	resource/MaterialResource.cpp
 	resource/ResourceLoader.cpp
 	resource/ResourceManager.cpp
 	resource/ResourceRegistry.cpp
-	resource/TextureResource.cpp
-	resource/MeshResource.cpp
-	resource/FontResource.cpp
-	resource/SoundResource.cpp
-	resource/ArchiveBundle.cpp
-	resource/FileBundle.cpp
 )
 
+if (CROWN_DEBUG OR CROWN_DEVELOPMENT)
+	list (APPEND RESOURCE_SRC resource/FileBundle.cpp)
+elseif (CROWN_RELEASE)
+	list (APPEND RESOURCE_SRC resource/ArchiveBundle.cpp)
+else ()
+	message (FATAL_ERROR "Oops, you should not be here")
+endif (CROWN_DEBUG OR CROWN_DEVELOPMENT)
+
 set (RESOURCE_HEADERS
-	resource/MaterialResource.h
 	resource/Resource.h
+	resource/ResourceFormat.h
 	resource/ResourceLoader.h
 	resource/ResourceManager.h
 	resource/ResourceRegistry.h
 	resource/Bundle.h
+	resource/LuaResource.h
 	resource/TextureResource.h
 	resource/MeshResource.h
 	resource/FontResource.h
 	resource/SoundResource.h
-	resource/ArchiveBundle.h
-	resource/FileBundle.h
+	resource/MaterialResource.h
+	resource/PackageResource.h
+	resource/ResourcePackage.h
+)
+
+set (RPC_SRC
+	rpc/RPCHandler.cpp
+	rpc/RPCServer.cpp
+)
+
+set (RPC_HEADERS
+	rpc/RPCServer.h
+	rpc/RPCHandler.h
 )
 
 set (OS_SRC
-	os/OS.cpp
 )
 
 set (OS_HEADERS
 	os/OS.h
+	os/OsEventQueue.h
 	os/NetAddress.h
+	os/OsTypes.h
 )
 
-set(LUA_SRC
+set (LUA_SRC
 	lua/LuaStack.cpp
 	lua/LuaEnvironment.cpp
 	lua/LuaIntSetting.cpp
@@ -321,13 +326,41 @@ set(LUA_SRC
 	lua/LuaAccelerometer.cpp
 	lua/LuaDevice.cpp
 	lua/LuaWindow.cpp
+	lua/LuaResourcePackage.cpp
 )
 
-set(LUA_HEADERS
+set (LUA_HEADERS
 	lua/LuaStack.h
 	lua/LuaEnvironment.h
 )
 
+set (AUDIO_SRC)
+
+set (AUDIO_HEADERS
+	audio/SoundRenderer.h
+	audio/OggDecoder.h
+)
+
+set (COMPILER_SRC
+	compilers/Compiler.cpp
+	compilers/BundleCompiler.cpp
+	compilers/mesh/MeshCompiler.cpp
+	compilers/lua/LuaCompiler.cpp
+	compilers/texture/TextureCompiler.cpp
+	compilers/sound/SoundCompiler.cpp
+	compilers/package/PackageCompiler.cpp
+)
+
+set (COMPILER_HEADER
+	compilers/Compiler.h
+	compilers/BundleCompiler.h
+	compilers/mesh/MeshCompiler.h
+	compilers/lua/LuaCompiler.h
+	compilers/texture/TextureCompiler.h
+	compilers/sound/SoundCompiler.h
+	compilers/package/PackageCompiler.h
+)
+
 set (CROWN_LIBRARIES)
 
 # Platform specific stuff
@@ -335,41 +368,42 @@ if (LINUX)
 	list (APPEND CROWN_INCLUDES
 		${CMAKE_SOURCE_DIR}/engine/os/linux
 		${CMAKE_SOURCE_DIR}/engine/renderers/gl/glx
+		${CMAKE_SOURCE_DIR}/engine/renderers/al
 	)
 
 	list (APPEND OS_HEADERS
 		os/linux/OsWindow.h
-		os/linux/TCPSocket.h
-		os/linux/UDPSocket.h
 		os/linux/OsFile.h
-		os/linux/Thread.h
+		os/linux/OsThread.h
 		os/linux/Mutex.h
 		os/linux/Cond.h
+		os/posix/Semaphore.h
 	)
 
 	list (APPEND OS_SRC
 		os/linux/LinuxOS.cpp
 		os/linux/OsWindow.cpp
-		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
 		renderers/gl/GLRenderer.cpp
-		renderers/gl/GLUtils.cpp
 		renderers/gl/glx/GLContext.cpp
 	)
 
 	list (APPEND RENDERERS_HEADERS
 		renderers/gl/GLRenderer.h
-		renderers/gl/GLUtils.h
 		renderers/gl/glx/GLContext.h
 	)
 
+	list (APPEND AUDIO_SRC
+		audio/al/ALRenderer.cpp
+	)
+
+	list (APPEND AUDIO_HEADERS
+		audio/al/ALRenderer.h
+	)
+
 	list (APPEND CROWN_LIBRARIES
 		rt
 		z
@@ -379,6 +413,8 @@ if (LINUX)
 		dl
 		GLEW
 		GL
+		openal
+		vorbisfile
 		luajit-5.1
 	)
 
@@ -392,13 +428,27 @@ if (LINUX)
 		-Werror
 		-Wno-long-long
 		-Wno-variadic-macros
-		-g
-		-pg
 		-fPIC
 		#-fvisibility=hidden
 	)
 
-	set (CROWN_EXECUTABLE_NAME crown-linux)
+	if (CROWN_DEBUG)
+		list (APPEND COMPILER_FLAGS -g -pg)
+	elseif (CROWN_DEVELOPMENT)
+		list (APPEND COMPILER_FLAGS -O2)
+	elseif (CROWN_RELEASE)
+		list (APPEND COMPILER_FLAGS
+			-O2
+			-Wno-unused-variable
+			-Wno-unused-parameter
+			-Wno-maybe-uninitialized
+			-Wno-unused-but-set-variable
+			-Wno-unused-function
+		)
+	else ()
+		message (FATAL_ERROR "Oops, you should not be here")
+	endif (CROWN_DEBUG)
+
 	set (CROWN_MAIN_SRC os/linux/main.cpp)
 endif (LINUX)
 
@@ -409,32 +459,39 @@ if (WINDOWS)
 	)
 
 	list (APPEND OS_HEADERS
-		os/win/OsWindow.h
 		os/win/OsFile.h
-		os/win/Thread.h
+		os/win/OsThread.h
+		os/win/OsWindow.h
 		os/win/Mutex.h
 		os/win/Cond.h
+		os/win/Semaphore.h
+		os/win/AtomicInt.h
+		os/win/inttypes.h
 	)
 
 	list (APPEND OS_SRC
 		os/win/WinOS.cpp
-		os/win/OsWindow.cpp
 		os/win/OsFile.cpp
-		os/win/Thread.cpp
-		os/win/Mutex.cpp
-		os/win/Cond.cpp
+		os/win/OsWindow.cpp
 	)
 
 	list (APPEND RENDERERS_SRC
 		renderers/gl/GLRenderer.cpp
-		renderers/gl/GLUtils.cpp
 		renderers/gl/wgl/GLContext.cpp
 	)
 
 	list (APPEND RENDERERS_HEADERS
 		renderers/gl/GLRenderer.h
-		renderers/gl/GLUtils.h
 		renderers/gl/wgl/GLContext.h
+		renderers/gl/wgl/wglext.h
+	)
+
+	list (APPEND AUDIO_SRC
+		audio/al/ALRenderer.cpp
+	)
+
+	list (APPEND AUDIO_HEADERS
+		audio/al/ALRenderer.h
 	)
 
 	list (APPEND CROWN_LIBRARIES
@@ -442,11 +499,14 @@ if (WINDOWS)
 		OpenGL32
 		glew32
 		lua51
+		OpenAL32
+		libvorbis
+		libvorbisfile
+	)
+
+	set (COMPILER_FLAGS
 	)
 
-	set (COMPILER_FLAGS)
-	
-	set (CROWN_EXECUTABLE_NAME crown-win)
 	set (CROWN_MAIN_SRC os/win/main.cpp)
 endif(WINDOWS)
 
@@ -461,18 +521,15 @@ set (CROWN_SOURCES
 	${MEM_SRC}
 	${COMPRESSORS_SRC}
 	${SETTINGS_SRC}
-
 	${INPUT_SRC}
-
 	${RENDERERS_SRC}
-
 	${RESOURCE_SRC}
-
+	${RPC_SRC}
 #	${NETWORK_SRC}
-
 	${OS_SRC}
-
 	${LUA_SRC}
+	${AUDIO_SRC}
+	${COMPILER_SRC}
 )
 
 set (CROWN_HEADERS
@@ -486,20 +543,15 @@ set (CROWN_HEADERS
 	${MEM_HEADERS}
 	${COMPRESSORS_HEADERS}
 	${SETTINGS_HEADERS}
-
 	${INPUT_HEADERS}
-
 	${RENDERERS_HEADERS}
-
 	${RESOURCE_HEADERS}
-
 	${RPC_HEADERS}
-
 #	${NETWORK_HEADERS}
-
 	${OS_HEADERS}
-
 	${LUA_HEADERS}
+	${AUDIO_HEADERS}
+	${COMPILER_HEADERS}
 )
 
 configure_file (${CMAKE_CURRENT_SOURCE_DIR}/Config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/Config.h)
@@ -520,9 +572,12 @@ if (CROWN_BUILD_TESTS)
 	add_subdirectory(tests)
 endif (CROWN_BUILD_TESTS)
 
+
 install (TARGETS crown DESTINATION bin)
 install (TARGETS ${CROWN_EXECUTABLE_NAME} DESTINATION bin)
 
+install (TARGETS crown DESTINATION test)
+
 #install (FILES ${HEADERS} DESTINATION include/${CMAKE_PROJECT_NAME})
 
 #install (FILES ${CORE_HEADERS} DESTINATION include/${CMAKE_PROJECT_NAME}/core)

+ 14 - 0
engine/Config.h.in

@@ -32,3 +32,17 @@ OTHER DEALINGS IN THE SOFTWARE.
 #cmakedefine WINDOWS
 
 #cmakedefine CROWN_DEBUG
+#cmakedefine CROWN_DEVELOPMENT
+#cmakedefine CROWN_RELEASE
+
+#define CROWN_MAX_TEXTURE_UNITS		8
+#define CROWN_MAX_TEXTURES			32
+#define CROWN_MAX_RENDER_TARGETS	32
+#define CROWN_MAX_VERTEX_BUFFERS	1024
+#define CROWN_MAX_INDEX_BUFFERS		1024
+#define CROWN_MAX_SHADERS			1024
+#define CROWN_MAX_GPU_PROGRAMS		1024
+#define CROWN_MAX_UNIFORMS			128
+
+// Including NUL character
+#define CROWN_MAX_UNIFORM_NAME_LENGTH	64

+ 0 - 130
engine/ConsoleServer.cpp

@@ -1,130 +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 "ConsoleServer.h"
-#include "Log.h"
-#include "StringUtils.h"
-#include "Device.h"
-#include "LuaEnvironment.h"
-#include "StringUtils.h"
-#include "JSONParser.h"
-#include "IntSetting.h"
-
-namespace crown
-{
-
-static IntSetting g_port("read_port", "port used for reading", 10000, 9999, 65535);
-
-// //-----------------------------------------------------------------------------
-// ConsoleServer::ConsoleServer() :
-// 	m_thread("console-thread"),
-// 	m_active(false)
-// {
-// 	// string::strncpy(m_cmd_buffer, "", 1024);
-// 	// string::strncpy(m_err_buffer, "", 1024);
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::init()
-// {
-// 	// m_active = true;
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::shutdown()
-// {
-// 	// m_active = false;
-
-// 	// m_socket.close();
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::read_eval_loop()
-// {
-// 	// m_socket.open(g_port);
-	
-// 	// char cmd[1024];
-
-// 	// while (m_active)
-// 	// {
-// 	// 	string::strncpy(cmd, "", 1024);
-// 	// 	receive((char*)cmd, 1024);
-
-// 	// 	// Fill command buffer
-// 	// 	string::strncpy(m_cmd_buffer, cmd, 1024);
-// 	// }
-
-// 	// Log::i("End read-eval loop");
-// 	// m_socket.close();
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::execute()
-// {
-// 	// m_command_mutex.lock();
-
-// 	// LuaEnvironment* lua = device()->lua_environment();
-
-// 	// lua->load_buffer(m_cmd_buffer, string::strlen(m_cmd_buffer));
-// 	// lua->execute(0, 0);
-
-// 	// string::strncpy(m_cmd_buffer, "", 1024);
-
-// 	// string::strncpy(m_err_buffer, lua->error(),  1024);
-
-// 	// if (string::strcmp(m_err_buffer, "") != 0)
-// 	// {
-// 	// 	// Fill error buffer
-// 	// 	send((char*)m_err_buffer, 1024);
-// 	// }
-
-// 	// string::strncpy(m_err_buffer, "", 1024);
-
-// 	// m_command_mutex.unlock();
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::send(const void* data, size_t size)
-// {
-// 	// m_socket.send(data, size);
-// }
-
-// //-----------------------------------------------------------------------------
-// void ConsoleServer::receive(char* data, size_t size)
-// {
-// 	// m_socket.receive(data, size);
-// }
-
-// //-----------------------------------------------------------------------------
-// void* ConsoleServer::background_thread(void* thiz)
-// {
-// 	// ((ConsoleServer*)thiz)->read_eval_loop();
-
-// 	// return NULL;
-// }
-
-
-} // namespace crown

+ 0 - 76
engine/ConsoleServer.h

@@ -1,76 +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.
-*/
-
-#pragma once
-
-#include "Types.h"
-#include "TCPSocket.h"
-#include "Thread.h"
-#include "Mutex.h"
-
-namespace crown
-{
-
-class ConsoleServer
-{
-public:
-
-// 	/// Constructor
-// 							ConsoleServer();
-// 	/// Start listening on @port
-// 	void					init();
-// 	/// Stop listening
-// 	void					shutdown();
-// 	/// Read-evaluation loop, executed on a different thread
-// 	void					read_eval_loop();
-// 	/// Execute commands, executed on main thread
-// 	void					execute();
-// 	/// Send data to client
-// 	void					send(const void* data, size_t size = 1024);
-// 	/// Receive data to client
-// 	void					receive(char* data, size_t size = 1024);
-
-// private:
-
-// 	static void*			background_thread(void* thiz);
-
-// private:
-
-// 	os::TCPSocket			m_socket;
-
-// 	Thread					m_thread;
-// 	Mutex					m_command_mutex;
-
-// 	// Is console active?
-// 	bool					m_active;
-// 	// Commands buffer
-// 	char					m_cmd_buffer[1024];
-
-// 	char 					m_err_buffer[1024];
-
-};
-
-} // namespace crown

+ 10 - 11
engine/Crown.h

@@ -60,12 +60,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Map.h"
 #include "RBTree.h"
 #include "List.h"
+#include "Vector.h"
 #include "Generic.h"
 #include "Queue.h"
+#include "PriorityQueue.h"
 #include "IdTable.h"
 
 // Core/Strings
 #include "StringUtils.h"
+#include "StringStream.h"
 #include "Hash.h"
 #include "Path.h"
 
@@ -101,8 +104,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Device.h"
 
 // Engine/Input
-#include "EventDispatcher.h"
-#include "InputManager.h"
 #include "Keyboard.h"
 #include "KeyCode.h"
 #include "Mouse.h"
@@ -113,28 +114,22 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "LuaEnvironment.h"
 
 // Engine/Os
-#include "Thread.h"
+#include "OsThread.h"
 #include "Mutex.h"
 #include "Cond.h"
 #include "OsFile.h"
 #include "OsWindow.h"
-#include "TCPSocket.h"
-#include "UDPSocket.h"
+#include "OsSocket.h"
 
 // Engine/Renderers
-#include "VertexBuffer.h"
-#include "IndexBuffer.h"
 #include "Renderer.h"
-#include "Material.h"
-#include "Texture.h"
+#include "RenderContext.h"
 #include "DebugRenderer.h"
 #include "PixelFormat.h"
 #include "VertexFormat.h"
 
 // Engine/Resource
 #include "Bundle.h"
-#include "ArchiveBundle.h"
-#include "FileBundle.h"
 #include "ResourceLoader.h"
 #include "ResourceManager.h"
 #include "TextureResource.h"
@@ -142,3 +137,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "SoundResource.h"
 #include "MaterialResource.h"
 #include "FontResource.h"
+
+// Engine/Audio
+#include "SoundRenderer.h"
+#include "OggDecoder.h"

+ 262 - 298
engine/Device.cpp

@@ -22,73 +22,83 @@ 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.
+OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include <cstdlib>
 
 #include "Config.h"
 #include "Device.h"
-#include "Filesystem.h"
-#include "InputManager.h"
-#include "Log.h"
-#include "OS.h"
-#include "Renderer.h"
-#include "DebugRenderer.h"
-#include "Types.h"
-#include "StringUtils.h"
+#include "Accelerometer.h"
 #include "Args.h"
-#include "ArchiveBundle.h"
-#include "FileBundle.h"
-#include "ResourceManager.h"
-#include "TextureResource.h"
+#include "DebugRenderer.h"
+#include "DiskFile.h"
+#include "DiskFilesystem.h"
+#include "JSONParser.h"
 #include "Keyboard.h"
+#include "Log.h"
+#include "LuaEnvironment.h"
+#include "Memory.h"
 #include "Mouse.h"
-#include "Touch.h"
-#include "Accelerometer.h"
+#include "OS.h"
 #include "OsWindow.h"
-#include "JSONParser.h"
-#include "DiskFile.h"
-#include "Memory.h"
-#include "LuaEnvironment.h"
-#include "ConsoleServer.h"
+#include "Renderer.h"
+#include "ResourceManager.h"
+#include "StringSetting.h"
+#include "StringUtils.h"
 #include "TextReader.h"
+#include "Touch.h"
+#include "Types.h"
+#include "Bundle.h"
+#include "TempAllocator.h"
+#include "ResourcePackage.h"
+#include "RPCServer.h"
+#include "SoundRenderer.h"
 
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Device::Device() :
-	m_allocator(m_subsystems_heap, MAX_SUBSYSTEMS_HEAP),
+#if defined(LINUX) || defined(WINDOWS)
+	#include "BundleCompiler.h"
+#endif
 
-	m_preferred_window_width(1000),
-	m_preferred_window_height(625),
-	m_preferred_window_fullscreen(0),
-	m_preferred_mode(MODE_RELEASE),
+#if defined(ANDROID)
+	#include "ApkFilesystem.h"
+#endif
 
-	m_quit_after_init(0),
+#define MAX_SUBSYSTEMS_HEAP 16 * 1024 * 1024
 
-	m_is_init(false),
-	m_is_running(false),
+namespace crown
+{
+//-----------------------------------------------------------------------------
+Device::Device()
+	: m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP)
+	, m_is_init(false)
+	, m_is_running(false)
+	, m_is_paused(false)
+	, m_is_really_paused(false)
 
-	m_frame_count(0),
+	, m_frame_count(0)
 
-	m_last_time(0),
-	m_current_time(0),
-	m_last_delta_time(0.0f),
+	, m_last_time(0)
+	, m_current_time(0)
+	, m_last_delta_time(0.0f)
+	, m_time_since_start(0.0)
 
-	m_filesystem(NULL),
-	m_input_manager(NULL),
-	m_lua_environment(NULL),
-	m_renderer(NULL),
-	m_debug_renderer(NULL),
+	, m_filesystem(NULL)
+	, m_lua_environment(NULL)
+	, m_renderer(NULL)
+	, m_debug_renderer(NULL)
+	, m_sound_renderer(NULL)
 
-	m_resource_manager(NULL),
-	m_resource_bundle(NULL),
+	, m_bundle_compiler(NULL)
+	, m_rpc(NULL)
+	, m_resource_manager(NULL)
+	, m_resource_bundle(NULL)
 
-	m_console_server(NULL)
+	, m_renderer_init_request(false)
 {
-	// Select executable dir by default
-	string::strncpy(m_preferred_root_path, os::get_cwd(), MAX_PATH_LENGTH);
+	// Bundle dir is current dir by default.
+	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
+	string::strncpy(m_source_dir, "", MAX_PATH_LENGTH);
+	string::strncpy(m_boot_file, "lua/game", MAX_PATH_LENGTH);
 }
 
 //-----------------------------------------------------------------------------
@@ -97,75 +107,101 @@ Device::~Device()
 }
 
 //-----------------------------------------------------------------------------
-bool Device::init(int argc, char** argv)
+void Device::init()
 {
-	if (is_init())
-	{
-		Log::e("Crown Engine is already initialized.");
-		return false;
-	}
-
-	parse_command_line(argc, argv);
-	check_preferred_settings();
-
 	// Initialize
 	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);
 
-	create_filesystem();
+	// RPC only in debug or development builds
+	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+		m_rpc = CE_NEW(m_allocator, RPCServer);
+		m_rpc->add_handler(&m_command_handler);
+		m_rpc->add_handler(&m_script_handler);
+		m_rpc->add_handler(&m_stats_handler);
+		m_rpc->add_handler(&m_ping_handler);
+		m_rpc->init(false);
+	#endif
+
+	// Default bundle filesystem
+	#if defined (LINUX) || defined(WINDOWS)
+		m_filesystem = CE_NEW(m_allocator, DiskFilesystem)(m_bundle_dir);
+	#elif defined(ANDROID)
+		m_filesystem = CE_NEW(m_allocator, ApkFilesystem)();
+	#endif
+	Log::d("Filesystem created.");
 
-	create_resource_manager();
+	// Read settings from crown.config
+	read_engine_settings();
 
-	create_input_manager();
+	m_resource_bundle = Bundle::create(m_allocator, *m_filesystem);
 
-	create_window();
+	// Create resource manager
+	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle, 0);
+	Log::d("Resource manager created.");
+	Log::d("Resource seed: %d", m_resource_manager->seed());
 
-	create_renderer();
+	// Create window
+	m_window = CE_NEW(m_allocator, OsWindow);
 
-	create_debug_renderer();
+	// Create input devices
+	m_keyboard = CE_NEW(m_allocator, Keyboard);
+	m_mouse = CE_NEW(m_allocator, Mouse);
+	m_touch = CE_NEW(m_allocator, Touch);
 
-	create_lua_environment();
+	// Create renderer
+	m_renderer = CE_NEW(m_allocator, Renderer)(m_allocator);
+	m_renderer->init();
+	Log::d("Renderer created.");
 
-	create_console_server();
+	// Create debug renderer
+	m_debug_renderer = CE_NEW(m_allocator, DebugRenderer)(*m_renderer);
+	Log::d("Debug renderer created.");
 
-	read_engine_settings();
+	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)();
+	m_lua_environment->init();
+	Log::d("Lua environment created.");
 
-	Log::i("Crown Engine initialized.");
+	m_sound_renderer = CE_NEW(m_allocator, SoundRenderer)(m_allocator);
+	m_sound_renderer->init();
+	Log::d("SoundRenderer created.");
 
+	Log::i("Crown Engine initialized.");
 	Log::i("Initializing Game...");
 
-	// Initialize the game through init game function
-	m_lua_environment->game_init();
-
 	m_is_init = true;
-
 	start();
 
-	if (m_quit_after_init == 1)
+	// Execute lua boot file
+	if (m_lua_environment->load_and_execute(m_boot_file))
+	{
+		if (!m_lua_environment->call_global("init", 0))
+		{
+			pause();
+		}
+	}
+	else
 	{
-		shutdown();
+		pause();
 	}
 
-	return true;
+	Log::d("Total allocated size: %llu", m_allocator.allocated_size());
 }
 
 //-----------------------------------------------------------------------------
 void Device::shutdown()
 {
-	if (is_init() == false)
-	{
-		Log::e("Crown Engine is not initialized.");	
-		return;
-	}
+	CE_ASSERT(is_init(), "Engine is not initialized");
 
 	// Shutdowns the game
-	m_lua_environment->game_shutdown();
+	m_lua_environment->call_global("shutdown", 0);
+
 
-	Log::i("Releasing ConsoleServer...");
-	if (m_console_server)
+	Log::d("Releasing SoundRenderer...");
+	if (m_sound_renderer)
 	{
-		//m_console_server->shutdown();
+		m_sound_renderer->shutdown();
 
-		CE_DELETE(m_allocator, m_console_server);
+		CE_DELETE(m_allocator, m_sound_renderer);
 	}
 
 	Log::i("Releasing LuaEnvironment...");
@@ -176,11 +212,10 @@ void Device::shutdown()
 		CE_DELETE(m_allocator, m_lua_environment);
 	}
 
-	Log::i("Releasing InputManager...");
-	if (m_input_manager)
-	{
-		CE_DELETE(m_allocator, m_input_manager);
-	}
+	Log::i("Releasing Input Devices...");
+	CE_DELETE(m_allocator, m_touch);
+	CE_DELETE(m_allocator, m_mouse);
+	CE_DELETE(m_allocator, m_keyboard);
 
 	Log::i("Releasing DebugRenderer...");
 	if (m_debug_renderer)
@@ -192,25 +227,18 @@ void Device::shutdown()
 	if (m_renderer)
 	{
 		m_renderer->shutdown();
-
-		Renderer::destroy(m_allocator, m_renderer);
-	}
-
-	Log::i("Releasing Window...");
-	if (m_window)
-	{
-		CE_DELETE(m_allocator, m_window);
+		CE_DELETE(m_allocator, m_renderer);
 	}
 
 	Log::i("Releasing ResourceManager...");
-	if (m_resource_bundle)
+	if (m_resource_manager)
 	{
-		CE_DELETE(m_allocator, m_resource_bundle);
+		CE_DELETE(m_allocator, m_resource_manager);
 	}
 
-	if (m_resource_manager)
+	if (m_resource_bundle)
 	{
-		CE_DELETE(m_allocator, m_resource_manager);
+		Bundle::destroy(m_allocator, m_resource_bundle);
 	}
 
 	Log::i("Releasing Filesystem...");
@@ -219,8 +247,14 @@ void Device::shutdown()
 		CE_DELETE(m_allocator, m_filesystem);
 	}
 
-	m_allocator.clear();
+	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+		Log::flush();
+		m_rpc->execute_callbacks();
+		m_rpc->shutdown();
+		CE_DELETE(m_allocator, m_rpc);
+	#endif
 
+	m_allocator.clear();
 	m_is_init = false;
 }
 
@@ -231,21 +265,21 @@ bool Device::is_init() const
 }
 
 //-----------------------------------------------------------------------------
-Filesystem* Device::filesystem()
+bool Device::is_paused() const
 {
-	return m_filesystem;
+	return m_is_paused;
 }
 
 //-----------------------------------------------------------------------------
-ResourceManager* Device::resource_manager()
+Filesystem* Device::filesystem()
 {
-	return m_resource_manager;
+	return m_filesystem;
 }
 
 //-----------------------------------------------------------------------------
-InputManager* Device::input_manager()
+ResourceManager* Device::resource_manager()
 {
-	return m_input_manager;
+	return m_resource_manager;
 }
 
 //-----------------------------------------------------------------------------
@@ -272,60 +306,65 @@ DebugRenderer* Device::debug_renderer()
 	return m_debug_renderer;
 }
 
+//-----------------------------------------------------------------------------
+SoundRenderer* Device::sound_renderer()
+{
+	return m_sound_renderer;
+}
+
 //-----------------------------------------------------------------------------
 Keyboard* Device::keyboard()
 {
-	return m_input_manager->keyboard();
+	return m_keyboard;
 }
 
 //-----------------------------------------------------------------------------
 Mouse* Device::mouse()
 {
-	return m_input_manager->mouse();
+	return m_mouse;
 }
 
 //-----------------------------------------------------------------------------
 Touch* Device::touch()
 {
-	return m_input_manager->touch();
+	return m_touch;
 }
 
 //-----------------------------------------------------------------------------
 Accelerometer* Device::accelerometer()
 {
-	return m_input_manager->accelerometer();
+	return NULL;
 }
 
-ConsoleServer* Device::console_server()
-{
-	return m_console_server;
-}
 //-----------------------------------------------------------------------------
 void Device::start()
 {
-	if (is_init() == false)
-	{
-		Log::e("Cannot start uninitialized engine.");
-		return;
-	}
+	CE_ASSERT(m_is_init, "Cannot start uninitialized engine.");
 
 	m_is_running = true;
-
 	m_last_time = os::milliseconds();
 }
 
 //-----------------------------------------------------------------------------
 void Device::stop()
 {
-	if (is_init() == false)
-	{
-		Log::e("Cannot stop uninitialized engine.");
-		return;
-	}
+	CE_ASSERT(m_is_init, "Cannot stop uninitialized engine.");
 
 	m_is_running = false;
 }
 
+//-----------------------------------------------------------------------------
+void Device::pause()
+{
+	m_is_paused = true;
+}
+
+//-----------------------------------------------------------------------------
+void Device::unpause()
+{
+	m_is_paused = false;
+}
+
 //-----------------------------------------------------------------------------
 bool Device::is_running() const
 {
@@ -344,235 +383,160 @@ float Device::last_delta_time() const
 	return m_last_delta_time;
 }
 
+//-----------------------------------------------------------------------------
+double Device::time_since_start() const
+{
+	return m_time_since_start;
+}
+
 //-----------------------------------------------------------------------------
 void Device::frame()
 {
 	m_current_time = os::microseconds();
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	m_last_time = m_current_time;
+	m_time_since_start += m_last_delta_time;
 
-	m_resource_manager->poll_resource_loader();
-
-	m_window->frame();
-	m_input_manager->frame(frame_count());
+	m_rpc->update();
 
-	m_lua_environment->game_frame(last_delta_time());
+	if (!m_is_paused)
+	{
+		m_resource_manager->poll_resource_loader();
 
-	//m_console_server->execute();
+		m_renderer->set_layer_clear(0, CLEAR_COLOR | CLEAR_DEPTH, Color4::LIGHTBLUE, 1.0f);
+		m_renderer->commit(0);
 
-	m_debug_renderer->draw_all();
-	m_renderer->frame();
+		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
+		{
+			pause();
+		}
 
-	m_frame_count++;
-}
+		m_renderer->frame();
 
-//-----------------------------------------------------------------------------
-void Device::reload(ResourceId name)
-{
-	(void)name;
-}
+		// FIXME: SoundRenderer should not be updated each frame
+		m_sound_renderer->frame();
+	}
 
-//-----------------------------------------------------------------------------
-void Device::create_filesystem()
-{
-	m_filesystem = CE_NEW(m_allocator, Filesystem)(m_preferred_root_path);
+	Log::flush();
+	m_rpc->execute_callbacks();
 
-	Log::d("Filesystem created.");
-	Log::d("Filesystem root path: %s", m_filesystem->root_path());
+	m_frame_count++;
 }
 
 //-----------------------------------------------------------------------------
-void Device::create_resource_manager()
+ResourcePackage* Device::create_resource_package(const char* name)
 {
-	// Select appropriate resource archive
-	if (m_preferred_mode == MODE_DEVELOPMENT)
-	{
-		m_resource_bundle = CE_NEW(m_allocator, FileBundle)(*m_filesystem);
-	}
-	else
-	{
-		m_resource_bundle = CE_NEW(m_allocator, ArchiveBundle)(*m_filesystem);
-	}
+	CE_ASSERT_NOT_NULL(name);
 
-	// Read resource seed
-	DiskFile* seed_file = filesystem()->open("seed.ini", FOM_READ);
-	TextReader reader(*seed_file);
+	ResourceId package_id = m_resource_manager->load("package", name);
+	m_resource_manager->flush();
 
-	char tmp_buf[32];
-	reader.read_string(tmp_buf, 32);
+	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
+	ResourcePackage* package = CE_NEW(default_allocator(), ResourcePackage)(*m_resource_manager, package_id, package_res);
 
-	filesystem()->close(seed_file);
-
-	uint32_t seed = string::parse_uint(tmp_buf);
-
-	// Create resource manager
-	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle, seed);
-
-	Log::d("Resource manager created.");
-	Log::d("Resource seed: %d", m_resource_manager->seed());
+	return package;
 }
 
 //-----------------------------------------------------------------------------
-void Device::create_input_manager()
+void Device::destroy_resource_package(ResourcePackage* package)
 {
-	// Create input manager
-	m_input_manager = CE_NEW(m_allocator, InputManager)();
+	CE_ASSERT_NOT_NULL(package);
 
-	Log::d("Input manager created.");
+	m_resource_manager->unload(package->resource_id());
+	CE_DELETE(default_allocator(), package);
 }
 
 //-----------------------------------------------------------------------------
-void Device::create_window()
+void Device::compile(const char* , const char* , const char* )
 {
-	m_window = CE_NEW(m_allocator, OsWindow)(m_preferred_window_width, m_preferred_window_height);
-
-	CE_ASSERT(m_window != NULL, "Unable to create the window");
-
-	m_window->set_title("Crown Game Engine");
-	m_window->show();
-
-	Log::d("Window created.");
 }
 
 //-----------------------------------------------------------------------------
-void Device::create_renderer()
+void Device::reload(const char* type, const char* name)
 {
-	m_renderer = Renderer::create(m_allocator);
-	m_renderer->init();
+	TempAllocator4096 temp;
+	DynamicString filename(temp);
+	filename += name;
+	filename += '.';
+	filename += type;
 
-	Log::d("Renderer created.");
-}
+	if (!m_bundle_compiler->compile(m_bundle_dir, m_source_dir, filename.c_str()))
+	{
+		Log::d("Compilation failed.");
+		return;
+	}
 
-//-----------------------------------------------------------------------------
-void Device::create_debug_renderer()
-{
-	// Create debug renderer
-	m_debug_renderer = CE_NEW(m_allocator, DebugRenderer)(*m_renderer);
+	uint32_t type_hash = hash::murmur2_32(type, string::strlen(type), 0);
 
-	Log::d("Debug renderer created.");
+	switch (type_hash)
+	{
+		case LUA_TYPE:
+		{
+			m_lua_environment->load_and_execute(name);
+			break;
+		}
+		default:
+		{
+			CE_ASSERT(false, "Oops, unknown resource type: %s", type);
+			break;
+		}
+	}
 }
-
-//-----------------------------------------------------------------------------
-void Device::create_lua_environment()
+//-------------------------------------------------------------------------
+void Device::read_engine_settings()
 {
-	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)();
+	// // Check crown.config existance
+	// CE_ASSERT(m_filesystem->is_file("crown.config"), "Unable to open crown.config");
 
-	m_lua_environment->init();
+	// // Copy crown config in a buffer
+	// TempAllocator4096 allocator;
 
-	Log::d("Lua environment created.");
-}
+	// File* config_file = m_filesystem->open("crown.config", FOM_READ);
 
-void Device::create_console_server()
-{
-	m_console_server = NULL;//CE_NEW(m_allocator, ConsoleServer)();
+	// char* json_string = (char*)allocator.allocate(config_file->size());
 
-	//m_console_server->init();
+	// config_file->read(json_string, config_file->size());
 
-	Log::d("Console server created.");
-}
+	// m_filesystem->close(config_file);
 
-//-----------------------------------------------------------------------------
-void Device::parse_command_line(int argc, char** argv)
-{
-	static ArgsOption options[] = 
-	{
-		{ "help",             AOA_NO_ARGUMENT,       NULL,        'i' },
-		{ "root-path",        AOA_REQUIRED_ARGUMENT, NULL,        'r' },
-		{ "width",            AOA_REQUIRED_ARGUMENT, NULL,        'w' },
-		{ "height",           AOA_REQUIRED_ARGUMENT, NULL,        'h' },
-		{ "fullscreen",       AOA_NO_ARGUMENT,       &m_preferred_window_fullscreen, 1 },
-		{ "dev",              AOA_NO_ARGUMENT,       &m_preferred_mode, MODE_DEVELOPMENT },
-		{ "quit-after-init",  AOA_NO_ARGUMENT,       &m_quit_after_init, 1 },
-		{ NULL, 0, NULL, 0 }
-	};
+	// // Parse crown.config
+	// JSONParser parser(json_string);
 
-	Args args(argc, argv, "", options);
+	// JSONElement root = parser.root();
 
-	int32_t opt;
+	// // Boot
+	// if (root.has_key("boot"))
+	// {
+	// 	const char* boot = root.key("boot").string_value();
+	// 	const size_t boot_length = string::strlen(boot) + 1;
 
-	while ((opt = args.getopt()) != -1)
-	{
-		switch (opt)
-		{
-			case 0:
-			{
-				break;
-			}
-			// Root path
-			case 'r':
-			{
-				string::strncpy(m_preferred_root_path, args.optarg(), MAX_PATH_LENGTH);
-				break;
-			}
-			// Window width
-			case 'w':
-			{
-				m_preferred_window_width = atoi(args.optarg());
-				break;
-			}
-			// Window height
-			case 'h':
-			{
-				m_preferred_window_height = atoi(args.optarg());
-				break;
-			}
-			case 'i':
-			case '?':
-			default:
-			{
-				print_help_message();
-				exit(EXIT_FAILURE);
-			}
-		}
-	}
-}
+	// 	string::strncpy(m_boot_file, boot, boot_length);
+	// }
+	// // Window width
+	// if (root.has_key("window_width"))
+	// {
+	// 	m_preferred_window_width = root.key("window_width").int_value();
+	// }
+	// // Window height
+	// if (root.has_key("window_height"))
+	// {
+	// 	m_preferred_window_height = root.key("window_height").int_value();
+	// }
 
-//-----------------------------------------------------------------------------
-void Device::check_preferred_settings()
-{
-	if (!os::is_absolute_path(m_preferred_root_path))
-	{
-		Log::e("The root path must be absolute.");
-		exit(EXIT_FAILURE);
-	}
+	// allocator.deallocate(json_string);
 
-	if (m_preferred_window_width == 0 || m_preferred_window_height == 0)
-	{
-		Log::e("Window width and height must be greater than zero.");
-		exit(EXIT_FAILURE);
-	}
+	// Log::i("Configuration set");
 }
 
-//-----------------------------------------------------------------------------
-void Device::read_engine_settings()
+static Device* g_device;
+void set_device(Device* device)
 {
+	g_device = device;
 }
 
-//-----------------------------------------------------------------------------
-void Device::print_help_message()
-{
-	os::printf(
-	"Usage: crown [options]\n"
-	"Options:\n\n"
-
-	"All of the following options take precedence over\n"
-	"environment variables and configuration files.\n\n"
-
-	"  --help                Show this help.\n"
-	"  --root-path <path>    Use <path> as the filesystem root path.\n"
-	"  --width <width>       Set the <width> of the render window.\n"
-	"  --height <width>      Set the <height> of the render window.\n"
-	"  --fullscreen          Start in fullscreen.\n"
-	"  --dev                 Run the engine in development mode\n"
-	"  --quit-after-init     Quit the engine immediately after the\n"
-	"                        initialization. Used only for debugging.\n");
-}
-
-Device g_device;
 Device* device()
 {
-	return &g_device;
+	return g_device;
 }
 
 } // namespace crown
-

+ 62 - 47
engine/Device.h

@@ -31,8 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "OS.h"
 #include "LinearAllocator.h"
 #include "Resource.h"
-
-#define MAX_SUBSYSTEMS_HEAP 1024 * 1024
+#include "RPCHandler.h"
 
 namespace crown
 {
@@ -43,13 +42,15 @@ class OsWindow;
 class Bundle;
 class Renderer;
 class DebugRenderer;
-class InputManager;
 class Keyboard;
 class Mouse;
 class Touch;
 class Accelerometer;
 class LuaEnvironment;
-class ConsoleServer;
+class SoundRenderer;
+class BundleCompiler;
+class ResourcePackage;
+class RPCServer;
 
 /// The Engine.
 /// It is the place where to look for accessing all of
@@ -61,9 +62,7 @@ public:
 							Device();
 							~Device();
 
-	/// Initializes the engine allowing to pass command line
-	/// parameters to configure some parameters.
-	bool					init(int argc, char** argv);
+	void					init();
 
 	/// Shutdowns the engine freeing all the allocated resources
 	void					shutdown();
@@ -75,14 +74,19 @@ 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;
 
-	/// Returns the time in milliseconds needed to render
-	/// the last frame
+	/// Returns the time in seconds needed to render the last frame
 	float					last_delta_time() const;
 
+	/// Returns the time in seconds since the first call to start().
+	double					time_since_start() const;
+
 	/// Forces the engine to actually start doing work.
 	void					start();
 
@@ -90,92 +94,102 @@ public:
 	/// and normally terminates the program.
 	void					stop();
 
+	/// Pauses the engine
+	void					pause();
+
+	/// Unpauses the engine
+	void					unpause();
+
+	virtual int32_t			run(int argc, char** argv) = 0;
+
 	/// Updates all the subsystems
 	void					frame();
 
-	void					reload(ResourceId name);
+	/// 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(const char* type, const char* name);
 
 	Filesystem*				filesystem();
 	ResourceManager*		resource_manager();
-	InputManager*			input_manager();
 	LuaEnvironment*			lua_environment();
 
 	OsWindow*				window();
 	Renderer*				renderer();
 	DebugRenderer*			debug_renderer();
 
+	SoundRenderer*			sound_renderer();
+
 	Keyboard*				keyboard();
 	Mouse*					mouse();
 	Touch*					touch();
 	Accelerometer*			accelerometer();
-
-	ConsoleServer*			console_server();
+	RPCServer*				rpc() { return m_rpc; }
 
 private:
 
-	void					create_filesystem();
-	void					create_resource_manager();
-	void					create_input_manager();
-	void 					create_lua_environment();
-
-	void					create_window();
-	void					create_renderer();
-	void					create_debug_renderer();
-
-	void					create_console_server();
-
-	void					parse_command_line(int argc, char** argv);
-	void					check_preferred_settings();
 	void					read_engine_settings();
-	void					print_help_message();
 
-private:
+protected:
 
 	// Used to allocate all subsystems
-	uint8_t					m_subsystems_heap[MAX_SUBSYSTEMS_HEAP];
 	LinearAllocator			m_allocator;
 
-	// Preferred settings from command line
-	int32_t					m_preferred_window_width;
-	int32_t					m_preferred_window_height;
-	int32_t					m_preferred_window_fullscreen;
-	int32_t					m_preferred_mode;
-	char					m_preferred_root_path[MAX_PATH_LENGTH];
-
-	int32_t					m_quit_after_init;
+	// Preferred settings
+	char					m_source_dir[MAX_PATH_LENGTH];
+	char 					m_bundle_dir[MAX_PATH_LENGTH];
+	char 					m_boot_file[MAX_PATH_LENGTH];
 
 	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;
 
 	uint64_t				m_last_time;
 	uint64_t				m_current_time;
 	float					m_last_delta_time;
+	double					m_time_since_start;
 
 	// Public subsystems
 	Filesystem*				m_filesystem;
 
 	OsWindow*				m_window;
-	InputManager*			m_input_manager;
+
+	Keyboard*				m_keyboard;
+	Mouse*					m_mouse;
+	Touch*					m_touch;
+
 	LuaEnvironment*			m_lua_environment;
 	Renderer*				m_renderer;
 	DebugRenderer*			m_debug_renderer;
 
+	SoundRenderer*			m_sound_renderer;
+
 	// Private subsystems
+	BundleCompiler*			m_bundle_compiler;
+	RPCServer*				m_rpc;
 	ResourceManager*		m_resource_manager;
 	Bundle*					m_resource_bundle;
 
-	// Debug subsystems
-	ConsoleServer*			m_console_server;
+	RPCCommandHandler		m_command_handler;
+	RPCScriptHandler		m_script_handler;
+	RPCStatsHandler			m_stats_handler;
+	RPCPingHandler			m_ping_handler;
 
-private:
+	bool 					m_renderer_init_request;
 
-	enum
-	{
-		MODE_RELEASE,
-		MODE_DEVELOPMENT
-	};
+private:
 
 	// Disable copying
 	Device(const Device&);
@@ -184,5 +198,6 @@ private:
 
 CE_EXPORT Device* device();
 
-} // namespace crown
+CE_EXPORT void set_device(Device* device);
 
+} // namespace crown

+ 0 - 204
engine/FPSSystem.cpp

@@ -1,204 +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 "InputManager.h"
-#include "Camera.h"
-#include "FPSSystem.h"
-#include "Vec2.h"
-#include "Vec3.h"
-#include "Mat3.h"
-#include "OS.h"
-#include "Device.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------
-FPSSystem::FPSSystem(Camera* camera, float speed, float sensibility) :
-	m_camera(camera),
-	m_camera_speed(speed),
-	m_camera_sensibility(sensibility),
-
-	m_angle_x(0),
-	m_angle_y(0),
-
-	m_up_pressed(false),
-	m_right_pressed(false),
-	m_down_pressed(false),
-	m_left_pressed(false)
-{
-	device()->input_manager()->register_keyboard_listener(this);
-	device()->input_manager()->register_accelerometer_listener(this);
-	//device()->input_manager()->register_mouse_listener(this);
-	device()->mouse()->set_cursor_relative_xy(Vec2(0.5f, 0.5f));
-	
-}
-
-//-----------------------------------------------------------------------
-void FPSSystem::key_pressed(const KeyboardEvent& event)
-{
-	switch (event.key)
-	{
-		case 'w':
-		case 'W':
-		{
-			m_up_pressed = true;
-			break;
-		}
-		case 'a':
-		case 'A':
-		{
-			m_left_pressed = true;
-			break;
-		}
-		case 's':
-		case 'S':
-		{
-			m_down_pressed = true;
-			break;
-		}
-		case 'd':
-		case 'D':
-		{
-			m_right_pressed = true;
-			break;
-		}
-		default:
-		{
-			break;
-		}
-	}
-}
-
-//-----------------------------------------------------------------------
-void FPSSystem::key_released(const KeyboardEvent& event)
-{
-	switch (event.key)
-	{
-		case 'w':
-		case 'W':
-		{
-			m_up_pressed = false;
-			break;
-		}
-		case 'a':
-		case 'A':
-		{
-			m_left_pressed = false;
-			break;
-		}
-		case 's':
-		case 'S':
-		{
-			m_down_pressed = false;
-			break;
-		}
-		case 'd':
-		case 'D':
-		{
-			m_right_pressed = false;
-			break;
-		}
-		default:
-		{
-			break;
-		}
-	}
-}
-
-//-----------------------------------------------------------------------
-void FPSSystem::accelerometer_changed(const AccelerometerEvent& event)
-{
-	(void)event;
-	set_view_by_cursor();
-}
-//-----------------------------------------------------------------------
-void FPSSystem::set_camera(Camera* camera)
-{
-	m_camera = camera;
-}
-
-//-----------------------------------------------------------------------
-Camera* FPSSystem::camera()
-{
-	return m_camera;
-}
-
-//-----------------------------------------------------------------------
-void FPSSystem::update(float dt)
-{
-	if (m_up_pressed)
-	{
-		m_camera->move_forward(m_camera_speed * dt);
-	}
-
-	if (m_left_pressed)
-	{
-		m_camera->strafe_left(m_camera_speed * dt);
-	}		
-
-	if (m_down_pressed)
-	{
-		m_camera->move_backward(m_camera_speed * dt);
-	}
-
-	if (m_right_pressed)
-	{
-		m_camera->strafe_right(m_camera_speed * dt);
-	}
-
-	device()->renderer()->set_matrix(MT_VIEW, m_camera->view_matrix());
-	device()->renderer()->set_matrix(MT_PROJECTION, m_camera->projection_matrix());
-}
-
-//-----------------------------------------------------------------------	
-void FPSSystem::set_view_by_cursor()
-{
-	static Vec2 lastPos = device()->mouse()->cursor_relative_xy();
-	Vec2 currentPos = device()->mouse()->cursor_relative_xy();
-	device()->mouse()->set_cursor_relative_xy(Vec2(0.5f, 0.5f));
-
-	if (lastPos == currentPos)
-	{
-		return;
-	}
-
-	Vec2 delta = lastPos - currentPos;
-
-	device()->mouse()->set_cursor_relative_xy(Vec2(0.5f, 0.5f));
-	lastPos = device()->mouse()->cursor_relative_xy();
-
-	m_angle_x += delta.y * m_camera_sensibility;
-	m_angle_y += delta.x * m_camera_sensibility;
-
-	m_angle_x = math::clamp_to_range(-89.999f * math::DEG_TO_RAD, 89.999f * math::DEG_TO_RAD, m_angle_x);
-	m_angle_y = math::fmod(m_angle_y, math::TWO_PI);
-
-	m_camera->set_rotation(m_angle_x, m_angle_y);
-}
-
-} // namespace crown
-

+ 4 - 5
engine/SceneGraph.cpp

@@ -33,11 +33,10 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-SceneGraph::SceneGraph() :
-	m_nodes(m_allocator, MAX_NODES),
-	m_world_poses(m_allocator),
-	m_local_poses(m_allocator),
-	m_parents(m_allocator)
+SceneGraph::SceneGraph()
+	: m_world_poses(m_allocator)
+	, m_local_poses(m_allocator)
+	, m_parents(m_allocator)
 {
 }
 

+ 1 - 1
engine/SceneGraph.h

@@ -69,7 +69,7 @@ private:
 	HeapAllocator	m_allocator;
 
 	// Sparse table of nodes
-	IdTable			m_nodes;
+	IdTable<MAX_NODES> m_nodes;
 
 	// Conversion from sparse table to packed array
 	uint32_t		m_sparse_to_packed[MAX_NODES];

+ 249 - 0
engine/audio/OggDecoder.h

@@ -0,0 +1,249 @@
+/*
+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 <vorbis/vorbisfile.h>
+#include <cstring>
+
+#include "Types.h"
+#include "Assert.h"
+
+#define SOUND_STREAM_BUFFER_SIZE (4096 * 2) // 8K... should be tested
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+struct OggBuffer
+{
+	char*	cur_ptr;
+	char*	buffer_ptr;
+	size_t	length;
+
+	OggBuffer(char* data, const size_t len) : 
+		cur_ptr(data), 
+		buffer_ptr(data), 
+		length(len)
+	{
+	}
+};
+
+//-----------------------------------------------------------------------------
+size_t ogg_buffer_read(void* dst, size_t size1, size_t size2, void* src)
+{
+    OggBuffer* ob = reinterpret_cast<OggBuffer*>(src);
+
+    size_t len = size1 * size2;
+
+    if ((ob->cur_ptr + len) > (ob->buffer_ptr + ob->length))
+    {
+    	len = ob->buffer_ptr + ob->length - ob->cur_ptr;
+    }
+
+    memcpy(dst, ob->cur_ptr, len);
+
+    ob->cur_ptr += len;
+
+    return len;
+}
+
+//-----------------------------------------------------------------------------
+int32_t	ogg_buffer_seek(void* src, ogg_int64_t offset, int32_t whence)
+{
+    OggBuffer* ob = reinterpret_cast<OggBuffer*>(src);
+
+    switch(whence)
+    {
+    	case SEEK_CUR:
+    	{
+    		ob->cur_ptr += offset;
+    		break;
+    	}
+    	case SEEK_END:
+    	{
+    		ob->cur_ptr = ob->buffer_ptr + ob->length - offset;
+    		break;
+    	}
+    	case SEEK_SET:
+    	{
+    		ob->cur_ptr = ob->buffer_ptr + offset;
+    		break;
+    	}
+    	default:
+    	{
+    		return -1;
+    	}
+    }
+
+    // Checks inferior limit
+    if (ob->cur_ptr < ob->buffer_ptr)
+    {
+    	ob->cur_ptr = ob->buffer_ptr;
+    	return -1;
+    }
+
+    // Checks superior limit
+    if (ob->cur_ptr > ob->buffer_ptr + ob->length)
+    {
+    	ob->cur_ptr = ob->buffer_ptr + ob->length;
+    	return -1;
+    }
+
+    // Success
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+int32_t ogg_buffer_close(void* src)
+{
+	(void)src;
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+long int ogg_buffer_tell(void* src)
+{
+    OggBuffer* ob = reinterpret_cast<OggBuffer*>(src);
+
+    return ob->cur_ptr - ob->buffer_ptr;
+}
+
+//-----------------------------------------------------------------------------
+static const char* ov_error_to_string(int32_t error)
+{
+	Log::i("error: %d", error);
+	switch (error)
+	{
+	case OV_FALSE: return "OV_FALSE";
+	case OV_HOLE: return "OV_HOLE";
+	case OV_EREAD: return "OV_EREAD";
+	case OV_EFAULT: return "OV_EFAULT";
+	case OV_EIMPL: return "OV_EIMPL";
+	case OV_EINVAL: return "OV_EINVAL";
+	case OV_ENOTVORBIS: return "OV_ENOTVORBIS";
+	case OV_EBADHEADER: return "OV_EBADHEADER";
+	case OV_EVERSION: return "OV_EVERSION";
+	case OV_EBADLINK: return "OV_EBADLINK";
+	case OV_ENOSEEK: return "OV_ENOSEEK";
+	default: return "OV_UNKNOWN"; // this case is never reached
+	}
+}
+
+//-----------------------------------------------------------------------------
+void check_ov_error(int32_t result)
+{
+	CE_ASSERT(result >= 0, "OV Error: %s", ov_error_to_string(result));
+}
+
+
+//-----------------------------------------------------------------------------
+class OggDecoder
+{
+public:
+
+	//-----------------------------------------------------------------------------
+	void init(char* data, const size_t size)
+	{
+		CE_ASSERT_NOT_NULL(data);
+
+		ov_callbacks callbacks;
+		callbacks.read_func = ogg_buffer_read;
+		callbacks.seek_func = ogg_buffer_seek;
+		callbacks.close_func = ogg_buffer_close;
+		callbacks.tell_func = ogg_buffer_tell;
+
+		m_buffer = CE_NEW(default_allocator(), OggBuffer)(data, size);
+
+		int32_t result = ov_open_callbacks((void*)m_buffer, &m_stream, NULL, 0, callbacks);
+		check_ov_error(result);
+		m_info = ov_info(&m_stream, -1);
+	}
+
+	//-----------------------------------------------------------------------------
+	void shutdown()
+	{
+		ov_clear(&m_stream);
+	}
+
+	//-----------------------------------------------------------------------------
+	bool stream()
+	{
+		int32_t  section;
+		int32_t  result;
+		int32_t  size = 0;
+
+		while (size < SOUND_STREAM_BUFFER_SIZE)
+		{
+			result = ov_read(&m_stream, (char*)m_data + size, SOUND_STREAM_BUFFER_SIZE - size, 0, 2, 1, &section);
+			check_ov_error(result);
+
+			if (result > 0)
+			{
+				size += result;
+			}
+			else if (result == 0)
+			{
+				return false;
+			}
+		}
+
+		m_size = size;
+
+		return true;
+	}
+
+	//-----------------------------------------------------------------------------
+	void rewind()
+	{
+		int32_t result = ov_raw_seek(&m_stream, 0);
+		check_ov_error(result);
+	}
+
+	//-----------------------------------------------------------------------------
+	const char* data()
+	{
+		return m_data;
+	}
+
+	//-----------------------------------------------------------------------------
+	size_t size()
+	{
+		return m_size;
+	}
+
+private:
+
+	OggBuffer* 				m_buffer;
+
+	OggVorbis_File  		m_stream;
+	vorbis_info*			m_info;
+
+	char					m_data[SOUND_STREAM_BUFFER_SIZE];
+	size_t					m_size;
+};
+
+} // namespace crown

+ 158 - 0
engine/audio/SoundRenderer.h

@@ -0,0 +1,158 @@
+/*
+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 "IdTable.h"
+#include "Allocator.h"
+#include "Types.h"
+
+#define	MAX_SOUNDS 64
+
+namespace crown
+{
+//-----------------------------------------------------------------------------
+typedef 	Id 		SoundId;
+
+//-----------------------------------------------------------------------------
+class SoundRendererImpl;
+	class SoundResource;
+class Vec3;
+
+//-----------------------------------------------------------------------------
+class SoundRenderer
+{
+public:
+							SoundRenderer(Allocator& allocator);
+
+							~SoundRenderer();
+
+	void					init();
+
+	void					shutdown();
+
+	void					pause();
+
+	void					unpause();
+
+	void					frame();
+
+	/// Returns number of sounds actually in use
+	uint32_t				num_sounds();
+
+	/// Sets listener parameters. @a position affects audibility of sounds, 
+	/// @a velocity affects doppler shift and @a orientation affects how a sound could be heard
+	void					set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const;
+
+	/// Creates a sound of sound 
+	SoundId					create_sound(SoundResource* resource);
+
+	/// Destroys a sound, specified by @a id, previously created
+	void					destroy_sound(SoundId id);
+
+	/// Plays a sound, specified by sound @a sid and a buffer @a bid
+	void					play_sound(SoundId id);
+
+	/// Pauses a sound, specified by @a id
+	void					pause_sound(SoundId id);
+
+	/// 
+	void					set_sound_loop(SoundId id, bool loop);
+
+	///	Sets sound's @a min_distance. From @a min_distance to @a max_distance, sound
+	/// scales from full volume to silence
+	void					set_sound_min_distance(SoundId id, const float min_distance);
+
+	///	Sets sound's @a max_distance. From @a min_distance to @a max_distance, sound
+	/// scales from full volume to silence
+	void					set_sound_max_distance(SoundId id, const float max_distance);
+
+	/// Sets sound's @a position. It affects sound audibility
+	void					set_sound_position(SoundId id, const Vec3& pos);
+
+	/// Sets sound's @a velocity. It affects doppler shift
+	void					set_sound_velocity(SoundId id, const Vec3& vel);
+
+	/// Sets sound's @a direction. It affects how a sound could be heard
+	void					set_sound_direction(SoundId id, const Vec3& dir);
+
+	/// Sets sound's @a pitch.
+	void					set_sound_pitch(SoundId id, const float pitch);
+
+	/// Sets sound's @a gain, that is measure sound's amplification
+	void					set_sound_gain(SoundId id, const float gain);
+
+	/// Sets sound's @a rolloff factor. Greater it is, greater sound's attenuation is
+	void					set_sound_rolloff(SoundId id, const float rolloff);
+
+	/// Returns minimum distance of @a id
+	float					sound_min_distance(SoundId id) const;
+
+	/// Returns maximum distance of @a id
+	float					sound_max_distance(SoundId id) const;
+	
+	/// Returns position of @a id
+	Vec3					sound_position(SoundId id) const;
+
+	/// Returns velocity of @a id
+	Vec3					sound_velocity(SoundId id) const;
+
+	/// Returns direction of @a id
+	Vec3					sound_direction(SoundId id) const;
+
+	/// Returns pitch of @a id
+	float					sound_pitch(SoundId id) const;
+
+	/// Returns gain of @a id
+	float					sound_gain(SoundId id) const;
+
+	/// Returns rolloff factor of @a id
+	/// Rolloff: perceived volume decreases at a fixed rate as a sound sound moves away from the listener
+	float					sound_rolloff(SoundId id) const;
+
+	/// Returns number of queued buffers of @a id
+	int32_t					sound_queued_buffers(SoundId id) const;
+
+	/// Returns number of processed buffers of @a id
+	int32_t					sound_processed_buffers(SoundId id) const;
+
+	/// Is sound @a id playing?
+	bool					sound_playing(SoundId id);
+
+private:
+
+	Allocator& 				m_allocator;
+
+	SoundRendererImpl*		m_impl;
+
+	bool 					m_is_paused;
+
+	IdTable<MAX_SOUNDS>		m_sounds_id_table;
+
+	uint32_t				m_num_sounds;
+};
+
+} // namespace crown

+ 352 - 0
engine/audio/al/ALRenderer.cpp

@@ -0,0 +1,352 @@
+/*
+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 "SoundRenderer.h"
+#include "ALRenderer.h"
+#include "SoundResource.h"
+#include "StringUtils.h"
+#include "Log.h"
+
+namespace crown
+{
+
+// ALRenderer
+class SoundRendererImpl
+{
+public:
+	
+	//-----------------------------------------------------------------------------
+	SoundRendererImpl() :
+		m_device(NULL),
+		m_context(NULL)
+	{
+	}
+
+	//-----------------------------------------------------------------------------
+	void init()
+	{
+		m_device = alcOpenDevice(NULL);
+		
+		if (!m_device)
+		{
+			CE_ASSERT(false, "Cannot open audio device");
+		}
+
+		m_context = alcCreateContext(m_device, NULL);
+
+		if (!m_context)
+		{
+			CE_ASSERT(false, "Cannot create context");		
+		}
+
+		AL_CHECK(alcMakeContextCurrent(m_context));
+
+		AL_CHECK(alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED));
+
+		AL_CHECK(alDopplerFactor(1.0f));
+		AL_CHECK(alDopplerVelocity(343.0f));
+
+		// Default listener
+		Vec3 pos(0.0f, 0.0f, 0.0f);
+		Vec3 vel(0.0f, 0.0f, 0.0f);
+		Vec3 at(0.0f, 0.0f, -1.0f);
+		Vec3 up(0.0f, 1.0f, 0.0f);
+
+		set_listener(pos, vel, at, up);		
+	}
+
+	//-----------------------------------------------------------------------------
+	void shutdown()
+	{
+		alcDestroyContext(m_context);
+	    alcCloseDevice(m_device);
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at)
+	{
+		AL_CHECK(alListener3f(AL_POSITION, pos.x, pos.y, pos.z));
+		AL_CHECK(alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z));
+
+		ALfloat orientation[] = { or_up.x, or_up.y, or_up.z,
+									or_at.x, or_at.y, or_at.z };
+
+		AL_CHECK(alListenerfv(AL_ORIENTATION, orientation));
+	}
+
+private:
+
+	ALCdevice*				m_device;
+	ALCcontext*				m_context;
+
+	Sound 		 			m_sounds[MAX_SOUNDS];
+
+private:
+
+	friend class 			SoundRenderer;
+};
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+SoundRenderer::SoundRenderer(Allocator& allocator) : 
+	m_allocator(allocator),
+	m_num_sounds(0)
+{
+	m_impl = CE_NEW(m_allocator, SoundRendererImpl);
+}
+
+//-----------------------------------------------------------------------------
+SoundRenderer::~SoundRenderer()
+{
+	if (m_impl)
+	{
+		CE_DELETE(m_allocator, m_impl);
+	}
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::init()
+{
+	m_impl->init();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::shutdown()
+{
+	m_impl->shutdown();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::frame()
+{
+	// TODO: needs additional works, but it's ok right now
+	for (uint32_t i = 0; i < m_num_sounds; i++)
+	{
+		if (m_impl->m_sounds[i].is_playing())
+		{
+			m_impl->m_sounds[i].update();
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+uint32_t SoundRenderer::num_sounds()
+{
+	return m_num_sounds;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const
+{
+	m_impl->set_listener(pos, vel, or_up, or_at);
+}
+
+//-----------------------------------------------------------------------------
+SoundId SoundRenderer::create_sound(SoundResource* resource)
+{
+	SoundId id = m_sounds_id_table.create();
+
+	m_impl->m_sounds[id.index].create(resource);
+
+	m_num_sounds++;
+
+	return id;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::destroy_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].destroy();
+
+	m_sounds_id_table.destroy(id);
+
+	m_num_sounds--;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::play_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].play();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::pause_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].pause();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_loop(SoundId id, bool loop)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].loop(loop);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_min_distance(SoundId id, const float min_distance)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_min_distance(min_distance);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_max_distance(SoundId id, const float max_distance)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_max_distance(max_distance);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_position(SoundId id, const Vec3& pos)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_position(pos);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_velocity(SoundId id, const Vec3& vel)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_velocity(vel);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_direction(SoundId id, const Vec3& dir)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_direction(dir);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_pitch(SoundId id, const float pitch)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_pitch(pitch);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_gain(SoundId id, const float gain)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_gain(gain);
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_rolloff(SoundId id, const float rolloff)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].set_rolloff(rolloff);
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_min_distance(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].min_distance();
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_max_distance(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].max_distance();
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_position(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].position();
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_velocity(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].velocity();
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_direction(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].direction();
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_pitch(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].pitch();
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_gain(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].gain();
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_rolloff(SoundId id) const
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].rolloff();
+}
+
+//-----------------------------------------------------------------------------
+bool SoundRenderer::sound_playing(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	return m_impl->m_sounds[id.index].is_playing();
+}
+
+} // namespace crown

+ 417 - 0
engine/audio/al/ALRenderer.h

@@ -0,0 +1,417 @@
+/*
+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 <AL/al.h>
+#include <AL/alc.h>
+
+#include "SoundResource.h"
+#include "OggDecoder.h"
+#include "Vec3.h"
+#include "Log.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+static const char* al_error_to_string(ALenum error)
+{
+	switch (error)
+	{
+		case AL_INVALID_ENUM: return "AL_INVALID_ENUM";
+		case AL_INVALID_VALUE: return "AL_INVALID_VALUE";
+		case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION";
+		case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY";
+		default: return "UNKNOWN_AL_ERROR";
+	}
+}
+
+//-----------------------------------------------------------------------------
+#ifdef CROWN_DEBUG
+	#define AL_CHECK(function)\
+		function;\
+		do { ALenum error; CE_ASSERT((error = alGetError()) == AL_NO_ERROR,\
+				"OpenAL error: %s", al_error_to_string(error)); } while (0)
+#else
+	#define AL_CHECK(function)\
+		function;
+#endif
+
+//-----------------------------------------------------------------------------
+struct Sound
+{
+public:
+	//-----------------------------------------------------------------------------
+	Sound()
+		: m_res(NULL)
+		, m_id(-1)
+		, m_created(false)
+		, m_playing(false)
+		, m_looping(false)
+		, m_streaming(false)
+		, m_positional(false)
+	{}
+
+	//-----------------------------------------------------------------------------
+	void create(SoundResource* resource)
+	{
+		CE_ASSERT_NOT_NULL(resource);
+
+		// Stores resource pointer
+		m_res = resource;
+
+		// Generates AL source
+		AL_CHECK(alGenSources(1, &m_id));
+
+		AL_CHECK(alSourcef(m_id, AL_PITCH, 1.0f));
+		AL_CHECK(alSourcef(m_id, AL_REFERENCE_DISTANCE, 0.1f));
+		AL_CHECK(alSourcef(m_id, AL_MAX_DISTANCE, 1000.0f));
+
+		// Generates AL buffers
+		AL_CHECK(alGenBuffers(3, m_buffer));
+		
+		bool stereo = (m_res->channels() > 1);
+
+		switch(m_res->bits_ps())
+		{
+			case 8:
+			{
+				if (stereo)	
+					m_format = AL_FORMAT_STEREO8;
+				else
+					m_format = AL_FORMAT_MONO8;
+				break;
+			}
+			case 16:
+			{
+				if (stereo)
+					m_format = AL_FORMAT_STEREO16;
+				else
+					m_format = AL_FORMAT_MONO16;
+				break;
+			}
+			default:
+			{
+				CE_ASSERT(false, "Wrong number of bits per sample.");
+			}
+		}
+
+		m_streaming = m_res->sound_type() == SoundType::OGG;
+		// Streams resource if is ogg 
+		if (m_streaming)
+		{
+			create_stream();
+		}
+		else
+		{
+			m_positional = true;
+
+			AL_CHECK(alBufferData(m_buffer[0], m_format, m_res->data(), m_res->size(), m_res->sample_rate()));
+
+			AL_CHECK(alSourceQueueBuffers(m_id, 1, &m_buffer[0]));
+		}
+	}
+
+	//-----------------------------------------------------------------------------
+	void update()
+	{
+		if (m_playing)
+		{
+			if (m_streaming)
+			{
+				update_stream();
+			}
+			else if (m_positional)
+			{
+				// nothing right now
+			}
+		}
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		AL_CHECK(alDeleteSources(1, &m_id));
+
+		AL_CHECK(alDeleteBuffers(3, m_buffer));
+	}
+
+	//-----------------------------------------------------------------------------
+	void play()
+	{
+		AL_CHECK(alSourcePlay(m_id));
+
+		m_playing = true;
+	}
+
+	//-----------------------------------------------------------------------------
+	void pause()
+	{
+		AL_CHECK(alSourcePause(m_id));
+
+		m_playing = false;
+	}
+
+	//-----------------------------------------------------------------------------
+	void loop(bool loop)
+	{
+		if (loop && !m_streaming)
+		{
+			AL_CHECK(alSourcei(m_id, AL_LOOPING, AL_TRUE));
+		}
+		else if (!loop && !m_streaming)
+		{
+			AL_CHECK(alSourcei(m_id, AL_LOOPING, AL_FALSE));
+		}
+
+		m_looping = loop;
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_min_distance(const float min_distance)
+	{
+		AL_CHECK(alSourcef(m_id, AL_REFERENCE_DISTANCE, min_distance));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_max_distance( const float max_distance)
+	{
+		AL_CHECK(alSourcef(m_id, AL_MAX_DISTANCE, max_distance));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_position(const Vec3& pos)
+	{
+		AL_CHECK(alSource3f(m_id, AL_POSITION, pos.x, pos.y, pos.z));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_velocity(const Vec3& vel)
+	{
+		AL_CHECK(alSource3f(m_id, AL_VELOCITY, vel.x, vel.y, vel.z));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_direction(const Vec3& dir)
+	{
+		AL_CHECK(alSource3f(m_id, AL_DIRECTION, dir.x, dir.y, dir.z));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_pitch(const float pitch)
+	{
+		AL_CHECK(alSourcef(m_id, AL_PITCH, pitch));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_gain(const float gain)
+	{
+		AL_CHECK(alSourcef(m_id, AL_GAIN, gain));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_rolloff(const float rolloff)
+	{
+		AL_CHECK(alSourcef(m_id, AL_ROLLOFF_FACTOR, rolloff));
+	}
+
+	//-----------------------------------------------------------------------------
+	float min_distance() const
+	{
+		ALfloat min_distance;
+
+		alGetSourcef(m_id, AL_REFERENCE_DISTANCE, &min_distance);
+
+		return min_distance;
+	}
+
+	//-----------------------------------------------------------------------------
+	float max_distance() const
+	{
+		ALfloat max_distance;
+
+		alGetSourcef(m_id, AL_MAX_DISTANCE, &max_distance);
+
+		return max_distance;
+	}
+
+	//-----------------------------------------------------------------------------
+	Vec3 position() const
+	{
+		ALfloat tmp[3];
+		alGetSourcefv(m_id, AL_POSITION, tmp);
+
+		Vec3 pos;
+		pos.x = tmp[0];
+		pos.y = tmp[1];
+		pos.z = tmp[2];
+
+		return pos;
+	}
+
+	//-----------------------------------------------------------------------------
+	Vec3 velocity() const
+	{
+		ALfloat tmp[3];
+		alGetSourcefv(m_id, AL_VELOCITY, tmp);
+
+		Vec3 vel;
+		vel.x = tmp[0];
+		vel.y = tmp[1];
+		vel.z = tmp[2];
+
+		return vel;
+	}
+
+	//-----------------------------------------------------------------------------
+	Vec3 direction() const
+	{
+		ALfloat tmp[3];
+		alGetSourcefv(m_id, AL_DIRECTION, tmp);
+
+		Vec3 dir;
+		dir.x = tmp[0];
+		dir.y = tmp[1];
+		dir.z = tmp[2];
+
+		return dir;	
+	}
+
+	//-----------------------------------------------------------------------------
+	float pitch() const
+	{
+		ALfloat pitch;
+		alGetSourcef(m_id, AL_PITCH, &pitch);
+
+		return pitch;
+	}
+
+	//-----------------------------------------------------------------------------
+	float gain() const
+	{
+		ALfloat gain;
+		alGetSourcef(m_id, AL_GAIN, &gain);
+
+		return gain;
+	}
+
+	//-----------------------------------------------------------------------------
+	float rolloff() const
+	{
+		ALfloat rolloff;
+		alGetSourcef(m_id, AL_ROLLOFF_FACTOR, &rolloff);
+
+		return rolloff;
+	}
+
+	//-----------------------------------------------------------------------------
+	bool is_playing() const
+	{
+		ALint source_state;
+		alGetSourcei(m_id, AL_SOURCE_STATE, &source_state);
+
+		return source_state == AL_PLAYING;
+	}
+
+	//-----------------------------------------------------------------------------
+	int32_t queued_buffers()
+	{
+		int32_t queued;
+		alGetSourcei(m_id, AL_BUFFERS_QUEUED, &queued);
+
+		return queued;
+	}
+
+	//-----------------------------------------------------------------------------
+	int32_t processed_buffers()
+	{
+		int32_t processed;
+		alGetSourcei(m_id, AL_BUFFERS_PROCESSED, &processed);
+
+		return processed;
+	}
+
+private:
+
+	//-----------------------------------------------------------------------------
+	void create_stream()
+	{
+		m_decoder.init((char*)m_res->data(), m_res->size());
+		m_decoder.stream();
+		AL_CHECK(alBufferData(m_buffer[0], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+		m_decoder.stream();
+		AL_CHECK(alBufferData(m_buffer[1], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));			
+		m_decoder.stream();
+		AL_CHECK(alBufferData(m_buffer[2], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+
+		AL_CHECK(alSourceQueueBuffers(m_id, 3, m_buffer));
+	}
+
+	//-----------------------------------------------------------------------------
+	void update_stream()
+	{
+		uint32_t processed = processed_buffers();
+
+		while (processed--)
+		{
+			ALuint buffer;
+
+			AL_CHECK(alSourceUnqueueBuffers(m_id, 1, &buffer));
+
+			if (m_decoder.stream())
+			{
+				AL_CHECK(alBufferData(buffer, m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+			}
+			else if (m_looping)
+			{
+				m_decoder.rewind();
+				m_decoder.stream();
+				AL_CHECK(alBufferData(buffer, m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+			}
+
+			AL_CHECK(alSourceQueueBuffers(m_id, 1, &buffer));
+		}
+	}
+
+public:
+
+	SoundResource*	m_res;
+
+	ALuint			m_id;
+	ALuint			m_buffer[3];
+	ALuint 			m_format;
+
+	bool			m_created :1;
+	bool			m_playing :1;
+	bool			m_looping :1;
+	bool			m_streaming :1;
+	bool			m_positional :1;
+
+	OggDecoder		m_decoder;
+};
+
+} // namespace crown

+ 364 - 0
engine/audio/sles/SLESRenderer.cpp

@@ -0,0 +1,364 @@
+/*
+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 <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+#include <cstring>
+
+#include "Types.h"
+#include "Assert.h"
+#include "SoundRenderer.h"
+#include "SLESRenderer.h"
+#include "Vec3.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+class SoundRendererImpl
+{
+public:
+	//-----------------------------------------------------------------------------
+	void init()
+	{
+		SLresult result;
+
+		const SLInterfaceID ids[] = {SL_IID_ENGINE};
+		const SLboolean reqs[] = {SL_BOOLEAN_TRUE};
+
+		result = slCreateEngine(&m_engine_obj, 0, NULL, 1, ids, reqs);
+		result = (*m_engine_obj)->Realize(m_engine_obj, SL_BOOLEAN_FALSE);
+
+		result = (*m_engine_obj)->GetInterface(m_engine_obj, SL_IID_ENGINE, &m_engine);
+
+		const SLInterfaceID ids1[] = {SL_IID_VOLUME};
+		const SLboolean reqs1[] = {SL_BOOLEAN_FALSE};
+
+		result = (*m_engine)->CreateOutputMix(m_engine, &m_out_mix_obj, 1, ids1, reqs1); 
+		result = (*m_out_mix_obj)->Realize(m_out_mix_obj, SL_BOOLEAN_FALSE);
+	}
+
+	//-----------------------------------------------------------------------------
+	void shutdown()
+	{
+		for (uint32_t i = 0; i < MAX_SOUNDS; i++)
+		{
+			m_sounds[i].destroy();
+		}
+
+		if (m_out_mix_obj)
+		{
+			(*m_out_mix_obj)->Destroy(m_out_mix_obj);
+			m_out_mix_obj = NULL;
+		}
+
+		if (m_engine_obj)
+		{
+			(*m_engine_obj)->Destroy(m_engine_obj);
+			m_engine_obj = NULL;
+			m_engine = NULL;
+		}
+	}
+
+public:
+
+	SLObjectItf						m_engine_obj;
+	SLEngineItf						m_engine;
+
+	SLObjectItf 					m_out_mix_obj;
+
+	Sound 							m_sounds[MAX_SOUNDS];
+
+private:
+
+	friend class SoundRenderer;
+};
+
+//-----------------------------------------------------------------------------
+SoundRenderer::SoundRenderer(Allocator& allocator) :
+	m_allocator(allocator),
+	m_impl(NULL),
+	m_is_paused(false),
+	m_num_sounds(0)
+{
+	m_impl = CE_NEW(m_allocator, SoundRendererImpl);
+}
+
+//-----------------------------------------------------------------------------
+SoundRenderer::~SoundRenderer()
+{
+	if (m_impl)
+	{
+		CE_DELETE(m_allocator, m_impl);
+	}
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::init()
+{
+	m_impl->init();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::shutdown()
+{
+	m_impl->shutdown();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::pause()
+{
+	for (uint32_t i = 0; i < MAX_SOUNDS; i++)
+	{
+		if (m_impl->m_sounds[i].is_playing())
+		{
+			m_impl->m_sounds[i].pause();
+		}
+	}
+
+	m_is_paused = true;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::unpause()
+{
+	for (uint32_t i = 0; i < MAX_SOUNDS; i++)
+	{
+		if (m_impl->m_sounds[i].is_created() && !m_impl->m_sounds[i].is_playing())
+		{
+			m_impl->m_sounds[i].unpause();
+		}
+	}
+
+	m_is_paused = false;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::frame()
+{
+	// Not needed because openSL|ES works through a callback mechanism making
+	// streamed-sound's update tricky with frame function. 
+	// When we will manage phisical aspect of sound then we will implement this.
+}
+
+//-----------------------------------------------------------------------------
+uint32_t SoundRenderer::num_sounds()
+{
+	return m_num_sounds;
+}
+
+//-----------------------------------------------------------------------------
+SoundId SoundRenderer::create_sound(SoundResource* resource)
+{
+	SoundId id = m_sounds_id_table.create();
+
+	m_impl->m_sounds[id.index].create(m_impl->m_engine, m_impl->m_out_mix_obj, resource);
+
+	m_num_sounds++;
+
+	return id;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::destroy_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].destroy();
+
+	m_sounds_id_table.destroy(id);
+
+	m_num_sounds--;
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::play_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].play();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::pause_sound(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].pause();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_loop(SoundId id, bool loop)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
+
+	m_impl->m_sounds[id.index].loop(loop);
+}
+
+//-----------------------------------------------------------------------------
+bool SoundRenderer::sound_playing(SoundId id)
+{
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exist");
+
+	return m_impl->m_sounds[id.index].is_playing();
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_listener(const Vec3& /*pos*/, const Vec3& /*vel*/, const Vec3& /*or_up*/, const Vec3& /*or_at*/) const
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_min_distance(SoundId /*id*/,  const float /*min_distance*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_max_distance(SoundId /*id*/,  const float /*max_distance*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_position(SoundId /*id*/, const Vec3& /*pos*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_velocity(SoundId /*id*/, const Vec3& /*vel*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_direction(SoundId /*id*/, const Vec3& /*dir*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_pitch(SoundId /*id*/, const float /*pitch*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_gain(SoundId /*id*/, const float /*gain*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+void SoundRenderer::set_sound_rolloff(SoundId /*id*/, const float /*rolloff*/)
+{
+	Log::w("Stub");
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_min_distance(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_max_distance(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_position(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return Vec3::ZERO;
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_velocity(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return Vec3::ZERO;
+}
+
+//-----------------------------------------------------------------------------
+Vec3 SoundRenderer::sound_direction(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return Vec3::ZERO;
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_pitch(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_gain(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+float SoundRenderer::sound_rolloff(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+int32_t SoundRenderer::sound_queued_buffers(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+int32_t SoundRenderer::sound_processed_buffers(SoundId /*id*/) const
+{
+	Log::w("Stub");
+
+	return 0;
+}
+
+
+} // namespace crown

+ 365 - 0
engine/audio/sles/SLESRenderer.h

@@ -0,0 +1,365 @@
+/*
+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 "SoundResource.h"
+#include "OggDecoder.h"
+#include "Vec3.h"
+#include "Log.h"
+
+namespace crown
+{
+
+static const char* sles_error_to_string(SLresult result)
+{
+	switch (result)
+	{
+	case SL_RESULT_SUCCESS: return "SL_RESULT_SUCCESS";
+	case SL_RESULT_PARAMETER_INVALID: return "SL_RESULT_PARAMETER_INVALID";
+	case SL_RESULT_MEMORY_FAILURE: return "SL_RESULT_MEMORY_FAILURE";
+	case SL_RESULT_FEATURE_UNSUPPORTED: return "SL_RESULT_FEATURE_UNSUPPORTED";
+	case SL_RESULT_RESOURCE_ERROR: return "SL_RESULT_RESOURCE_ERROR";
+	case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+	case SL_RESULT_PRECONDITIONS_VIOLATED: return "SL_RESULT_PRECONDITIONS_VIOLATED";
+	case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+	case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+	case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+	case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+	case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+	default: return "SL_RESULT_UNKNOWN";
+	}
+}
+
+//-----------------------------------------------------------------------------
+void check_sles_errors(SLresult result)
+{
+	CE_ASSERT(result == SL_RESULT_SUCCESS, "SL_ERROR_CODE: %s", sles_error_to_string(result));
+}
+
+//-----------------------------------------------------------------------------
+struct Sound
+{
+					Sound();
+
+	void 			create(SLEngineItf engine, SLObjectItf out_mix_obj, SoundResource* resource);
+	void 			update();
+	void 			destroy();
+	void 			play();
+	void 			pause();
+	void			unpause();
+	void 			loop(bool loop);
+
+	bool 			is_created() const;
+	bool 			is_playing() const;
+
+	static void 	buffer_callback(SLAndroidSimpleBufferQueueItf caller, void* sound);
+
+public:
+
+	SoundResource*					m_res;
+
+	SLEngineItf						m_engine;
+	SLObjectItf 					m_out_mix_obj;
+	SLObjectItf 					m_player_obj;
+	SLPlayItf 						m_player_play;
+	SLAndroidSimpleBufferQueueItf 	m_player_bufferqueue;
+	SLVolumeItf						m_player_volume;
+
+	uint32_t						m_processed_buffers;
+	
+	uint16_t* 						m_data;
+	size_t	  						m_size;
+	uint32_t  						m_sample_rate;
+	uint32_t  						m_channels;
+	uint32_t  						m_bits;
+
+	bool 							m_created :1;
+	bool							m_playing :1;
+	bool							m_looping :1;
+	bool							m_streaming :1;
+	bool 							m_positional :1;
+
+	OggDecoder						m_decoder;
+};
+
+//-----------------------------------------------------------------------------
+inline void Sound::buffer_callback(SLAndroidSimpleBufferQueueItf caller, void* sound)
+{
+	Sound* s = (Sound*)sound;
+
+	if (s->is_playing())
+	{
+		s->m_processed_buffers++;
+
+		if (s->m_decoder.stream())
+		{
+			(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());
+		}
+		else if (s->m_looping)
+		{
+			s->m_decoder.rewind();
+			s->m_decoder.stream();
+			(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());	
+		}
+		else
+		{
+			s->pause();
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+inline Sound::Sound()
+	: m_res(NULL)
+	, m_player_obj(NULL)
+	, m_player_play(NULL)
+	, m_player_bufferqueue(NULL)
+	, m_player_volume(NULL)
+	, m_processed_buffers(0)
+	, m_data(NULL)
+	, m_size(0)
+	, m_sample_rate(0)
+	, m_channels(0)
+	, m_bits(0)
+	, m_created(false)
+	, m_playing(false)
+	, m_looping(false)
+	, m_streaming(false)
+	, m_positional(false)
+{
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::create(SLEngineItf engine, SLObjectItf out_mix_obj, SoundResource* resource)
+{
+	CE_ASSERT_NOT_NULL(resource);
+
+	m_engine = engine;
+	m_out_mix_obj = out_mix_obj;
+
+	m_res = resource;
+
+	// Configures buffer queue
+	SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
+
+	// Configures audio format
+	SLDataFormat_PCM format_pcm;
+	format_pcm.formatType = SL_DATAFORMAT_PCM;
+
+	// Sets channels
+	switch (m_res->channels())
+	{
+	case 1:
+		format_pcm.numChannels = 1;
+		format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
+		break;
+	case 2:
+	default:
+		format_pcm.numChannels = 2;
+		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
+		break;
+	}
+
+	// Sets sample rate
+	switch (m_res->sample_rate())
+	{
+	case 8000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_8;
+		break;
+	case 11025:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_11_025;
+		break;
+	case 16000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_16;
+		break;
+	case 22050:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_22_05;
+		break;
+	case 24000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_24;
+		break;
+	case 32000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_32;
+		break;
+	case 44100:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
+		break;
+	case 48000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_48;
+		break;
+	case 64000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_64;
+		break;
+	case 88200:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_88_2;
+		break;
+	case 96000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_96;
+		break;
+	case 192000:
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_192;
+		break;
+	}	
+	
+	format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
+	format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
+	format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
+	format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
+
+	// Configures audio source
+	SLDataSource audio_source;
+	audio_source.pLocator = &buffer_queue;
+	audio_source.pFormat = &format_pcm;
+
+	// Configures audio output mix
+	SLDataLocator_OutputMix out_mix;
+	out_mix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
+	out_mix.outputMix = m_out_mix_obj;
+
+	// Configures audio sink
+	SLDataSink audio_sink;
+	audio_sink.pLocator = &out_mix;
+	audio_sink.pFormat = NULL;
+
+	// Creates sound player
+	const SLInterfaceID ids[] = {SL_IID_PLAY, SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
+	const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+
+	SLresult result = (*m_engine)->CreateAudioPlayer(m_engine, &m_player_obj, &audio_source, &audio_sink, 3, ids, reqs);
+	check_sles_errors(result);
+
+	result = (*m_player_obj)->Realize(m_player_obj, SL_BOOLEAN_FALSE);
+	check_sles_errors(result);
+
+	// Gets interfaces
+	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_PLAY, &m_player_play);
+	check_sles_errors(result);
+
+	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_BUFFERQUEUE, &m_player_bufferqueue);
+	check_sles_errors(result);
+
+	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_VOLUME, &m_player_volume);
+	check_sles_errors(result);
+
+	(*m_player_bufferqueue)->RegisterCallback(m_player_bufferqueue, Sound::buffer_callback, this);
+
+	// Manage simple sound or stream
+	m_streaming = m_res->sound_type() == SoundType::OGG;
+
+	if (m_streaming)
+	{
+		m_decoder.init((char*)m_res->data(), m_res->size());
+
+		m_decoder.stream();
+		(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_decoder.data(), m_decoder.size());
+	}
+	else
+	{
+		(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_res->data(), m_res->size());
+	}
+
+	m_created = true;
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::update()
+{
+	// See SLESRenderer.cpp, row 160
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::destroy()
+{
+	if (m_player_obj)
+	{
+		SLuint32 state;
+		(*m_player_obj)->GetState(m_player_obj, &state);
+
+		if (state == SL_OBJECT_STATE_REALIZED)
+		{
+			(*m_player_bufferqueue)->Clear(m_player_bufferqueue);
+			(*m_player_obj)->AbortAsyncOperation(m_player_obj);
+			(*m_player_obj)->Destroy(m_player_obj);
+
+			m_player_obj = NULL;
+			m_player_play = NULL;
+			m_player_bufferqueue = NULL;
+			m_player_volume = NULL;
+		}
+
+		m_created = false;
+		m_playing = false;
+		m_looping = false;
+		m_streaming = false;
+	}
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::play()
+{
+	SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PLAYING);
+	check_sles_errors(result);
+
+	m_playing = true;
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::pause()
+{
+	SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PAUSED);
+	check_sles_errors(result);
+
+	m_playing = false;
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::unpause()
+{
+	m_decoder.stream();
+	(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_decoder.data(), m_decoder.size());
+	play();
+}
+
+//-----------------------------------------------------------------------------
+inline void Sound::loop(bool loop)
+{
+	m_looping = loop;
+}
+
+//-----------------------------------------------------------------------------
+bool Sound::is_created() const
+{
+	return m_created;
+}
+
+//-----------------------------------------------------------------------------
+inline bool Sound::is_playing() const
+{
+	return m_playing;
+}
+
+} // namespace crown

+ 176 - 0
engine/compilers/BundleCompiler.cpp

@@ -0,0 +1,176 @@
+/*
+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 <inttypes.h>
+#include "BundleCompiler.h"
+#include "Vector.h"
+#include "DynamicString.h"
+#include "Allocator.h"
+#include "OS.h"
+#include "Log.h"
+#include "Resource.h"
+#include "Path.h"
+#include "DiskFilesystem.h"
+#include "TempAllocator.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+BundleCompiler::BundleCompiler()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir, const char* resource)
+{
+	Vector<DynamicString> files(default_allocator());
+
+	if (resource == NULL)
+	{
+		BundleCompiler::scan(source_dir, "", files);
+
+		// Create bundle dir if does not exist
+		DiskFilesystem temp;
+		if (!temp.is_directory(bundle_dir) || !temp.is_file(bundle_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;
+		}
+	}
+	else
+	{
+		DynamicString filename(default_allocator());
+		filename = resource;
+		files.push_back(filename);
+	}
+
+	// Compile all resources
+	for (uint32_t i = 0; i < files.size(); i++)
+	{
+		const char* filename = files[i].c_str();
+
+		uint64_t filename_hash = hash::murmur2_64(filename, string::strlen(filename), 0);
+
+		char filename_extension[32];
+		path::extension(filename, filename_extension, 32);
+		uint32_t resource_type_hash = hash::murmur2_32(filename_extension, string::strlen(filename_extension), 0);
+
+		char out_name[65];
+		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
+
+		// Skip crown.config file
+		if (resource_type_hash == CONFIG_TYPE)
+		{
+			continue;
+		}
+
+		Log::i("%s <= %s", out_name, filename);
+		Log::flush();
+
+		bool result = false;
+		if (resource_type_hash == MESH_TYPE)
+		{
+			result = m_mesh.compile(source_dir, bundle_dir, filename, out_name);
+		}
+		else if (resource_type_hash == TEXTURE_TYPE)
+		{
+			result = m_texture.compile(source_dir, bundle_dir, filename, out_name);
+		}
+		else if (resource_type_hash == LUA_TYPE)
+		{
+			result = m_lua.compile(source_dir, bundle_dir, filename, out_name);
+		}
+		else if(resource_type_hash == SOUND_TYPE)
+		{
+			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!");
+			return false;
+		}
+
+		if (!result)
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+void BundleCompiler::scan(const char* source_dir, const char* cur_dir, Vector<DynamicString>& files)
+{
+	Vector<DynamicString> my_files(default_allocator());
+
+	DiskFilesystem fs(source_dir);
+	fs.list_files(cur_dir, my_files);
+
+	for (uint32_t i = 0; i < my_files.size(); i++)
+	{
+		DynamicString file_i(default_allocator());
+
+		if (string::strcmp(cur_dir, "") != 0)
+		{
+			file_i += cur_dir;
+			file_i += '/';
+		}
+		file_i += my_files[i];
+
+		if (fs.is_directory(file_i.c_str()))
+		{
+			BundleCompiler::scan(source_dir, file_i.c_str(), files);
+		}
+		else // Assume a regular file
+		{
+			files.push_back(file_i);
+		}
+	}
+}
+
+} // namespace crown

+ 19 - 25
engine/os/posix/UDPSocket.h → engine/compilers/BundleCompiler.h

@@ -26,43 +26,37 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
+#include "MeshCompiler.h"
+#include "TextureCompiler.h"
+#include "LuaCompiler.h"
+#include "SoundCompiler.h"
+#include "PackageCompiler.h"
+#include "DynamicString.h"
+#include "Vector.h"
+#include "DiskFilesystem.h"
 
 namespace crown
 {
-namespace os
-{
-
-class NetAddress;
 
-/// OS level UDP socket.
-class UDPSocket
+class CE_EXPORT BundleCompiler
 {
 public:
 
-				UDPSocket();
-				~UDPSocket();
-
-	// Open connection
-	bool 		open(uint16_t port);
+	BundleCompiler();
 
-	// Send data through socket
-	bool 		send(const NetAddress& receiver, const void* data, size_t size);
+	bool compile(const char* bundle_dir, const char* source_dir, const char* resource = NULL);
 
-	// Receive data through socket
-	size_t	 	receive(NetAddress& sender, void* data, size_t size);
-
-	// Close connection
-	void 		close();
+private:
 
-	// Is connection open?
-	bool 		is_open();
+	static void scan(const char* source_dir, const char* cur_dir, Vector<DynamicString>& files);
 
 private:
-	
-	// Socket descriptor
-	int 	m_socket;
+
+	MeshCompiler	m_mesh;
+	TextureCompiler	m_texture;
+	LuaCompiler 	m_lua;
+	SoundCompiler	m_sound;
+	PackageCompiler m_package;
 };
 
-} // namespace os
 } // namespace crown

+ 13 - 17
tools/compilers/Compiler.cpp → engine/compilers/Compiler.cpp

@@ -24,15 +24,11 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <cstring>
-#include <cstdlib>
-#include <iostream>
-
 #include "Compiler.h"
+#include "Filesystem.h"
+#include "DiskFilesystem.h"
 #include "ResourceFormat.h"
-
-using std::cout;
-using std::endl;
+#include "File.h"
 
 namespace crown
 {
@@ -40,14 +36,14 @@ namespace crown
 //-----------------------------------------------------------------------------
 bool Compiler::compile(const char* root_path, const char* dest_path, const char* name_in, const char* name_out)
 {
-	std::string path_in = std::string(root_path) + "/" + std::string(name_in);
-	std::string path_out = std::string(dest_path) + "/" + std::string(name_out);
+	DiskFilesystem root_fs(root_path);
+	DiskFilesystem dest_fs(dest_path);
 
 	// The compilation fails when returned size is zero
 	size_t resource_size = 0;
-	if ((resource_size = compile_impl(path_in.c_str())) == 0)
+	if ((resource_size = compile_impl(root_fs, name_in)) == 0)
 	{
-		cout << "Compilation failed." << endl;
+		Log::e("Compilation failed");
 		return false;
 	}
 
@@ -58,23 +54,23 @@ bool Compiler::compile(const char* root_path, const char* dest_path, const char*
 	resource_header.size = resource_size;
 
 	// Open destination file and write the header
-	std::fstream out_file;
-	out_file.open(path_out.c_str(), std::fstream::out | std::fstream::binary);
+	File* out_file = dest_fs.open(name_out, FOM_WRITE);
 
-	if (out_file.is_open())
+	if (out_file)
 	{
 		// Write header
-		out_file.write((char*)&resource_header, sizeof(ResourceHeader));
+		out_file->write((char*)&resource_header, sizeof(ResourceHeader));
 
 		// Write resource-specific data
 		write_impl(out_file);
-		out_file.close();
+
+		dest_fs.close(out_file);
 
 		cleanup();
 		return true;
 	}
 
-	cout << "Unable to write compiled file." << endl;
+	Log::e("Unable to write compiled file.");
 	return false;
 }
 

+ 5 - 5
tools/compilers/Compiler.h → engine/compilers/Compiler.h

@@ -26,14 +26,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include <string>
-#include <fstream>
-
 #include "Types.h"
 
 namespace crown
 {
 
+class Filesystem;
+class File;
+
 /// Resource compiler interface.
 /// Every specific resource compiler must inherith from this
 /// interface and implement its methods accordingly.
@@ -48,8 +48,8 @@ public:
 
 protected:
 
-	virtual size_t			compile_impl(const char* resource_path) = 0;
-	virtual void			write_impl(std::fstream& out_file) = 0;
+	virtual size_t			compile_impl(Filesystem& fs, const char* resource_path) = 0;
+	virtual void			write_impl(File* out_file) = 0;
 };
 
 } // namespace crown

+ 117 - 0
engine/compilers/lua/LuaCompiler.cpp

@@ -0,0 +1,117 @@
+/*
+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 "Config.h"
+#include "LuaCompiler.h"
+#include "LuaResource.h"
+#include "TempAllocator.h"
+#include "DynamicString.h"
+#include "Filesystem.h"
+#include "OS.h"
+
+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)
+{
+}
+
+//-----------------------------------------------------------------------------
+LuaCompiler::~LuaCompiler()
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t LuaCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	TempAllocator1024 alloc;
+	DynamicString res_abs_path(alloc);
+	TempAllocator1024 alloc2;
+	DynamicString bc_abs_path(alloc2);
+	fs.get_absolute_path(resource_path, res_abs_path);
+	fs.get_absolute_path("bc.tmp", bc_abs_path);
+
+	const char* luajit[] =
+	{
+		LUAJIT_EXECUTABLE,
+		LUAJIT_FLAGS,
+		res_abs_path.c_str(),
+		bc_abs_path.c_str(),
+		NULL
+	};
+
+	os::execute_process(luajit);
+
+	File* bc = fs.open(bc_abs_path.c_str(), FOM_READ);
+	if (bc != NULL)
+	{
+		m_luajit_blob_size = bc->size();
+		m_luajit_blob = (char*) default_allocator().allocate(m_luajit_blob_size);
+		bc->read(m_luajit_blob, m_luajit_blob_size);
+		fs.close(bc);
+		fs.delete_file(bc_abs_path.c_str());
+	}
+	else
+	{
+		Log::e("Error while reading luajit bytecode");
+		return 0;
+	}
+
+	return sizeof(LuaHeader) + m_luajit_blob_size;
+}
+
+//-----------------------------------------------------------------------------
+void LuaCompiler::write_impl(File* out_file)
+{
+	LuaHeader header;
+	header.version = LUA_RESOURCE_VERSION;
+	header.size = m_luajit_blob_size;
+
+	out_file->write((char*)&header, sizeof(LuaHeader));
+	out_file->write((char*)m_luajit_blob, m_luajit_blob_size);
+
+	default_allocator().deallocate(m_luajit_blob);
+	m_luajit_blob_size = 0;
+	m_luajit_blob = NULL;
+}
+
+} // namespace crown

+ 8 - 8
tools/compilers/mat/MATCompiler.h → engine/compilers/lua/LuaCompiler.h

@@ -27,24 +27,24 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Compiler.h"
-#include "FileStream.h"
-#include "Resource.h"
 
 namespace crown
 {
 
-class MATCompiler : public Compiler
+class CE_EXPORT LuaCompiler : public Compiler
 {
 public:
 
-					MATCompiler(const char* root_path, const char* dest_path, const char* resource, uint32_t seed);
-					~MATCompiler();
+					LuaCompiler();
+					~LuaCompiler();
 
-	bool			compile();
-	void			write();
+	size_t			compile_impl(Filesystem& fs, const char* resource_path);
+	void			write_impl(File* out_file);
 
 private:
+
+	size_t			m_luajit_blob_size;
+	char*			m_luajit_blob;
 };
 
 } // namespace crown
-

+ 199 - 0
engine/compilers/mesh/MeshCompiler.cpp

@@ -0,0 +1,199 @@
+/*
+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 "MeshCompiler.h"
+#include "DynamicString.h"
+#include "TempAllocator.h"
+#include "Filesystem.h"
+#include "JSONParser.h"
+#include "Log.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+MeshCompiler::MeshCompiler()
+	: m_vertices(default_allocator()), m_indices(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+MeshCompiler::~MeshCompiler()
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t MeshCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+	char* buf = (char*)default_allocator().allocate(file->size());
+	file->read(buf, file->size());
+
+	JSONParser json(buf);
+	JSONElement root = json.root();
+
+	// Read data arrays
+	JSONElement position = root.key_or_nil("position");
+	JSONElement normal = root.key_or_nil("normal");
+	JSONElement texcoord = root.key_or_nil("texcoord");
+
+	m_has_normal = false;
+	m_has_texcoord = false;
+
+	if (position.is_nil())
+	{
+		Log::e("Bad mesh: array 'position' not found.");
+		return 0;
+	}
+	List<float> position_array(default_allocator());
+	position.array_value(position_array);
+
+
+	List<float> normal_array(default_allocator());
+	if (!normal.is_nil())
+	{
+		m_has_normal = true;
+		normal.array_value(normal_array);
+	}
+
+	List<float> texcoord_array(default_allocator());
+	if (!texcoord.is_nil())
+	{
+		m_has_texcoord = true;
+		texcoord.array_value(texcoord_array);
+	}
+
+	// Read index arrays
+	JSONElement index = root.key_or_nil("index");
+	if (index.is_nil())
+	{
+		Log::e("Bad mesh: array 'index' not found.");
+		return 0;
+	}
+
+	List<uint16_t> position_index(default_allocator());
+	List<uint16_t> normal_index(default_allocator());
+	List<uint16_t> texcoord_index(default_allocator());
+
+	index[0].array_value(position_index);
+
+	if (m_has_normal)
+	{
+		index[1].array_value(normal_index);
+	}
+
+	if (m_has_texcoord)
+	{
+		index[2].array_value(texcoord_index);
+	}
+
+	// Generate vb/ib
+	uint32_t idx = 0;
+	for (uint32_t i = 0; i < position_index.size(); i++)
+	{
+		MeshVertex v;
+
+		uint16_t p_idx = position_index[i] * 3;
+		v.position = Vec3(position_array[p_idx], position_array[p_idx + 1], position_array[p_idx + 2]);
+
+		if (m_has_normal)
+		{
+			uint16_t n_idx = normal_index[i] * 3;
+			v.normal = Vec3(normal_array[n_idx], normal_array[n_idx + 1], normal_array[n_idx + 2]);
+		}
+
+		if (m_has_texcoord)
+		{
+			uint16_t t_idx = texcoord_index[i] * 2;
+			v.texcoord = Vec2(texcoord_array[t_idx], texcoord_array[t_idx + 1]);
+		}
+
+
+		uint32_t f_idx = 0;
+		bool found = false;
+		for (; f_idx < m_vertices.size(); f_idx++)
+		{
+			if (m_vertices[f_idx] == v)
+			{
+				found = true;
+				break;
+			}
+		}
+
+		if (found)
+		{
+			m_indices.push_back(f_idx);
+		}
+		else
+		{
+			m_vertices.push_back(v);
+			m_indices.push_back(idx);
+			idx++;
+		}
+	}
+
+	m_mesh_header.version = MESH_VERSION;
+	m_mesh_header.num_meshes = 1;
+	m_mesh_header.num_joints = 0;
+	//m_mesh_header.padding[0] = 0xCECECECE;
+
+	default_allocator().deallocate(buf);
+	fs.close(file);
+
+	return sizeof(MeshHeader) + sizeof(MeshData) +
+	 		m_vertices.size() * sizeof(MeshVertex) +
+	 		m_indices.size() * sizeof(uint16_t);
+}
+
+//-----------------------------------------------------------------------------
+void MeshCompiler::write_impl(File* out_file)
+{
+	MeshData data;
+	data.vertices.num_vertices = m_vertices.size();
+	data.vertices.format = VERTEX_P3_N3_T2;
+	data.vertices.offset = sizeof(MeshHeader) + sizeof(MeshData);
+
+	data.indices.num_indices = m_indices.size();
+	data.indices.offset = sizeof(MeshHeader) + sizeof(MeshData) + m_vertices.size() * sizeof(MeshVertex);
+
+	// Write header
+	out_file->write((char*)&m_mesh_header, sizeof(MeshHeader));
+
+	// Write mesh metadata
+	out_file->write((char*)&data, sizeof(MeshData));
+
+	// Write vertices
+	out_file->write((char*) m_vertices.begin(), m_vertices.size() * sizeof(MeshVertex));
+
+	// Write indices
+	out_file->write((char*) m_indices.begin(), m_indices.size() * sizeof(uint16_t));
+
+	// Cleanup
+	m_vertices.clear();
+	m_indices.clear();
+}
+
+} // namespace crown

+ 35 - 9
engine/renderers/VertexBuffer.h → engine/compilers/mesh/MeshCompiler.h

@@ -26,21 +26,47 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
+#include "Compiler.h"
+#include "MeshResource.h"
+#include "Vec3.h"
+#include "Vec2.h"
+#include "List.h"
 
 namespace crown
 {
 
-// Max number of vertex buffers a renderer can hold.
-const uint32_t MAX_VERTEX_BUFFERS = 4096;
+struct MeshVertex
+{
+	Vec3 position;
+	Vec3 normal;
+	Vec2 texcoord;
+
+	bool operator==(const MeshVertex& other)
+	{
+		return position == other.position &&
+				normal == other.normal &&
+				texcoord == other.texcoord;
+	}
+};
 
-enum VertexBufferMode
+class CE_EXPORT MeshCompiler : public Compiler
 {
-	VBM_VERTEX_ONLY		= 0,
-	VBM_TEXTURE_COORDS	= 1,
-	VBM_NORMAL_COORDS	= 2,
-	VBM_COLOR_COORDS	= 4
+public:
+
+						MeshCompiler();
+						~MeshCompiler();
+
+	size_t				compile_impl(Filesystem& fs, const char* resource_path);
+	void				write_impl(File* out_file);
+
+private:
+
+	MeshHeader			m_mesh_header;
+	bool				m_has_normal;
+	bool				m_has_texcoord;
+
+	List<MeshVertex>	m_vertices;
+	List<uint16_t>		m_indices;
 };
 
 } // namespace crown
-

+ 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

+ 12 - 17
engine/os/win/Thread.h → engine/compilers/package/PackageCompiler.h

@@ -26,34 +26,29 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include <windows.h>
-#include <process.h>
-#include <WinBase.h>
-#include "Types.h"
-#include "OS.h"
+#include "Compiler.h"
+#include "Resource.h"
+#include "List.h"
 
 namespace crown
 {
-namespace os
-{
-
-typedef void* (*ThreadFunction)(void*);
 
-class Thread
+class CE_EXPORT PackageCompiler : public Compiler
 {
 public:
 
-					Thread(os::ThreadFunction f, LPVOID params, const char* name);
-					~Thread();
+	PackageCompiler();
 
-	void			join();
-	void			detach();
+	size_t compile_impl(Filesystem& fs, const char* resource_path);
+	void write_impl(File* out_file);
 
 private:
 
-	HANDLE			m_thread;
-	const char*		m_name;
+	bool m_has_texture;
+	bool m_has_lua;
+
+	List<ResourceId> m_textures;
+	List<ResourceId> m_scripts;
 };
 
-} // namespace os
 } // namespace crown

+ 171 - 0
engine/compilers/sound/SoundCompiler.cpp

@@ -0,0 +1,171 @@
+/*
+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 <stdio.h>
+#include <limits.h>
+#include <errno.h>
+#include <vorbis/vorbisfile.h>
+
+#include "Config.h"
+#include "SoundCompiler.h"
+#include "Allocator.h"
+#include "Filesystem.h"
+#include "StringUtils.h"
+#include "DynamicString.h"
+#include "OS.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+SoundCompiler::SoundCompiler() 
+	: m_sound_data_size(0)
+	, m_sound_data(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+SoundCompiler::~SoundCompiler()
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t SoundCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	size_t size = 0;
+	
+	size = compile_if_wav(fs, resource_path);
+
+	if (size == 0)
+	{
+		size = compile_if_ogg(fs, resource_path);
+	}
+	
+	return size;
+}
+
+//-----------------------------------------------------------------------------
+void SoundCompiler::write_impl(File* out_file)
+{
+	out_file->write((char*)&m_sound_header, sizeof(SoundHeader));
+	out_file->write((char*)m_sound_data, m_sound_data_size);
+
+	if (m_sound_data)
+	{
+
+		default_allocator().deallocate(m_sound_data);
+		m_sound_data_size = 0;
+		m_sound_data = NULL;
+	}
+}
+
+//-----------------------------------------------------------------------------
+size_t SoundCompiler::compile_if_wav(Filesystem& fs, const char* resource_path)
+{
+	File* in_file = fs.open(resource_path, FOM_READ);
+
+	WAVHeader header;
+
+	in_file->read((char*)&header, sizeof(WAVHeader));
+
+	if (header.riff[0] != 'R' && header.riff[1] != 'I' && header.riff[2] != 'F' && header.riff[3] != 'F')
+	{
+		if (header.wave[0] != 'W' && header.wave[1] != 'A' && header.wave[2] != 'V' && header.wave[3] != 'E')
+		{
+			if (header.fmt[0] != 'f' && header.fmt[1] != 'm' && header.fmt[2] != 't' && header.fmt[3] != ' ')
+			{
+				fs.close(in_file);
+				return 0;
+			}
+		}
+	}
+
+	m_sound_header.version = SOUND_VERSION;
+	m_sound_header.size = header.data_size;
+	m_sound_header.sample_rate = header.fmt_sample_rate;
+	m_sound_header.avg_bytes_ps = header.fmt_avarage;
+	m_sound_header.channels = header.fmt_channels;
+	m_sound_header.block_size = header.fmt_block_align;
+	m_sound_header.bits_ps = header.fmt_bits_ps;
+	m_sound_header.sound_type = SoundType::WAV;
+
+	m_sound_data_size = header.data_size;
+	m_sound_data = (uint8_t*)default_allocator().allocate(m_sound_data_size);
+
+	in_file->read((char*)m_sound_data, m_sound_data_size);
+
+	fs.close(in_file);
+
+	return sizeof(SoundHeader) + m_sound_data_size;
+}
+
+//-----------------------------------------------------------------------------
+size_t SoundCompiler::compile_if_ogg(Filesystem& fs, const char* resource_path)
+{
+	// Retrieves resource absolute path
+	DynamicString s(default_allocator());
+	fs.get_absolute_path(resource_path, s);
+	const char* abs_path = s.c_str();
+
+	OggVorbis_File ogg_stream;
+
+	bool result = ov_fopen(os::normalize_path(abs_path), &ogg_stream) == 0;
+
+	if (result == false)
+	{
+		return 0;
+	}
+
+	vorbis_info* info = ov_info(&ogg_stream, -1);
+
+	int64_t size = ov_raw_total(&ogg_stream, -1);
+	int32_t rate = info->rate;
+	int32_t channels = info->channels;
+
+	ov_clear(&ogg_stream);
+
+	File* in_file = fs.open(resource_path, FOM_READ);
+
+	m_sound_header.version = SOUND_VERSION;
+	m_sound_header.size = size;
+	m_sound_header.sample_rate = rate;
+	m_sound_header.block_size = (channels * 16) / 8;
+	m_sound_header.avg_bytes_ps = rate * ((channels * 16) / 8);
+	m_sound_header.channels = channels;
+	m_sound_header.bits_ps = 16;
+	m_sound_header.sound_type = SoundType::OGG;
+
+	m_sound_data_size = size;
+	m_sound_data = (uint8_t*)default_allocator().allocate(m_sound_data_size);
+
+	in_file->read((char*)m_sound_data, m_sound_data_size);
+
+	fs.close(in_file);
+
+	return sizeof(SoundHeader) + m_sound_data_size;
+}
+
+} // namespace crown

+ 37 - 39
engine/resource/SoundResource.cpp → engine/compilers/sound/SoundCompiler.h

@@ -24,58 +24,56 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#pragma once
+
+#include <cstdio>
+
+#include "Compiler.h"
 #include "SoundResource.h"
-#include "Bundle.h"
-#include "Log.h"
-#include "DiskFile.h"
-#include "Assert.h"
-#include "Allocator.h"
-#include "Device.h"
+#include "Types.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-void* SoundResource::load(Allocator& allocator, Bundle& bundle, ResourceId id)
+struct WAVHeader
 {
-	DiskFile* file = bundle.open(id);
-
-	CE_ASSERT(file != NULL, "Resource does not exist: %.8X%.8X", id.name, id.type);
-
-	SoundResource* resource = (SoundResource*)allocator.allocate(sizeof(SoundResource));
-
-	file->read(&resource->m_header, sizeof(SoundHeader));
-
-	size_t size = resource->size();
-
-	resource->m_data = (uint8_t*)allocator.allocate(sizeof(uint8_t) * size);
-
-	file->read(resource->m_data, size);
-
-	bundle.close(file);
-
-	return resource;
-}
+	char 			riff[4];				// Should contains 'RIFF'
+	int32_t			chunk_size;				// Not Needed
+	char 			wave[4];				// Should contains 'WAVE'
+	char 			fmt[4];					// Should contains 'fmt '
+	int32_t			fmt_size;				// Size of format chunk
+	int16_t			fmt_tag;				// Identifies way data is stored, 1 means no compression
+	int16_t			fmt_channels;			// Channel, 1 means mono, 2 means stereo
+	int32_t			fmt_sample_rate;		// Sample per second
+	int32_t			fmt_avarage;			// Avarage bytes per sample
+	int16_t			fmt_block_align;		// Block alignment
+	int16_t			fmt_bits_ps;			// Number of bits per sample
+	char 			data[4];				// Should contains 'data'
+	int32_t			data_size;				// Data dimension
+};
 
 //-----------------------------------------------------------------------------
-void SoundResource::online(void* resource)
+class CE_EXPORT SoundCompiler : public Compiler
 {
-	CE_ASSERT(resource != NULL, "Resource not loaded");
-}
+public:
 
-//-----------------------------------------------------------------------------
-void SoundResource::unload(Allocator& allocator, void* resource)
-{
-	CE_ASSERT(resource != NULL, "Resource not loaded");
+						SoundCompiler();
+						~SoundCompiler();
 
-	allocator.deallocate(((SoundResource*)resource)->m_data);
-	allocator.deallocate(resource);
-}
+	size_t				compile_impl(Filesystem& fs, const char* resource_path);
+	void				write_impl(File* out_file);
 
-//-----------------------------------------------------------------------------
-void SoundResource::offline(void* /*resource*/)
-{
+private:
+
+	size_t				compile_if_wav(Filesystem& fs, const char* resource_path);
+	size_t				compile_if_ogg(Filesystem& fs, const char* resource_path);
+
+private:
 
-}
+	SoundHeader			m_sound_header;
+	size_t				m_sound_data_size;
+	uint8_t*			m_sound_data;
+};
 
 } // namespace crown

+ 38 - 40
tools/compilers/tga/TGACompiler.cpp → engine/compilers/texture/TextureCompiler.cpp

@@ -24,53 +24,42 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <fstream>
-#include <iostream>
-
-#include "TGACompiler.h"
+#include "TextureCompiler.h"
 #include "PixelFormat.h"
-#include "TextureFormat.h"
+#include "Allocator.h"
+#include "Filesystem.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-TGACompiler::TGACompiler() :
+TextureCompiler::TextureCompiler() :
 	m_texture_data_size(0),
 	m_texture_data(NULL)
 {
 }
 
 //-----------------------------------------------------------------------------
-TGACompiler::~TGACompiler()
+TextureCompiler::~TextureCompiler()
 {
-	if (m_texture_data)
-	{
-		delete[] m_texture_data;
-	}
 }
 
 //-----------------------------------------------------------------------------
-size_t TGACompiler::compile_impl(const char* resource_path)
+size_t TextureCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 {
-	std::fstream in_file;
-	in_file.open(resource_path, std::fstream::in | std::fstream::binary);
+	File* in_file = fs.open(resource_path, FOM_READ);
 
-	if (!in_file.is_open())
+	if (!in_file)
 	{
-		std::cout << "Unable to open file: " << resource_path << std::endl;
+		Log::e("Unable to open file: %s", resource_path);
 		return 0;
 	}
 
 	// Read the header
-	if (!in_file.read((char*)(char*)&m_tga_header, sizeof(TGAHeader)))
-	{
-		std::cout << "Unable to read the TGA header." << std::endl;
-		return 0;
-	}
+	in_file->read((char*)(char*)&m_tga_header, sizeof(TGAHeader));
 
 	// Skip TGA ID
-	in_file.seekg(m_tga_header.id_length);
+	in_file->skip(m_tga_header.id_length);
 
 	// Compute color channels
 	m_tga_channels = m_tga_header.pixel_depth / 8;
@@ -87,25 +76,25 @@ size_t TGACompiler::compile_impl(const char* resource_path)
 		case 2:
 		case 3:
 		{
-			m_texture_header.format = PF_RGB_8;
+			m_texture_header.format = PIXEL_RGB_8;
 
 			m_texture_data_size = m_tga_size * 3;
-			m_texture_data = new uint8_t[m_texture_data_size];
+			m_texture_data = (uint8_t*)default_allocator().allocate(m_texture_data_size);
 
 			break;
 		}
 		case 4:
 		{
-			m_texture_header.format = PF_RGBA_8;
+			m_texture_header.format = PIXEL_RGBA_8;
 
 			m_texture_data_size = m_tga_size * m_tga_channels;
-			m_texture_data = new uint8_t[m_texture_data_size];
+			m_texture_data = (uint8_t*)default_allocator().allocate(m_texture_data_size);
 			
 			break;
 		}
 		default:
 		{
-			std::cout << "Unable to determine TGA channels." << std::endl;
+			Log::e("Unable to determine TGA channels.");
 			return 0;
 		}
 	}
@@ -115,7 +104,7 @@ size_t TGACompiler::compile_impl(const char* resource_path)
 	{
 		case 0:
 		{
-			std::cout << "The file does not contain image data: " << resource_path << std::endl;
+			Log::e("The file does not contain image data: %s", resource_path);
 			return 0;
 		}
 		case 2:
@@ -132,24 +121,33 @@ size_t TGACompiler::compile_impl(const char* resource_path)
 
 		default:
 		{
-			std::cout << "Image type not supported." << std::endl;
+			Log::e("Image type not supported.");
 			return 0;
 		}
 	}
 
+	fs.close(in_file);
+
 	// Return the total resource size
 	return sizeof(TextureHeader) + m_texture_data_size;
 }
 
 //-----------------------------------------------------------------------------
-void TGACompiler::write_impl(std::fstream& out_file)
+void TextureCompiler::write_impl(File* out_file)
 {
-	out_file.write((char*)&m_texture_header, sizeof(TextureHeader));
-	out_file.write((char*)m_texture_data, m_texture_data_size);
+	out_file->write((char*)&m_texture_header, sizeof(TextureHeader));
+	out_file->write((char*)m_texture_data, m_texture_data_size);
+
+	if (m_texture_data)
+	{
+		default_allocator().deallocate(m_texture_data);
+		m_texture_data_size = 0;
+		m_texture_data = NULL;
+	}
 }
 
 //-----------------------------------------------------------------------------
-void TGACompiler::load_uncompressed(std::fstream& in_file)
+void TextureCompiler::load_uncompressed(File* in_file)
 {
 	uint64_t size = m_tga_header.width * m_tga_header.height;
 
@@ -161,7 +159,7 @@ void TGACompiler::load_uncompressed(std::fstream& in_file)
 		{
 			uint16_t pixel_data;
 			
-			in_file.read((char*)&pixel_data, sizeof(pixel_data));
+			in_file->read((char*)&pixel_data, sizeof(pixel_data));
 			
 			m_texture_data[j + 0] = (pixel_data & 0x7c) >> 10;
 			m_texture_data[j + 1] = (pixel_data & 0x3e) >> 5;
@@ -172,14 +170,14 @@ void TGACompiler::load_uncompressed(std::fstream& in_file)
 	}
 	else
 	{
-		in_file.read((char*)m_texture_data, (size_t)(size * m_tga_channels));
+		in_file->read((char*)m_texture_data, (size_t)(size * m_tga_channels));
 
 		swap_red_blue();
 	}
 }
 
 //-----------------------------------------------------------------------------
-void TGACompiler::load_compressed(std::fstream& in_file)
+void TextureCompiler::load_compressed(File* in_file)
 {
 	uint8_t rle_id = 0;
 	uint32_t i = 0;
@@ -191,14 +189,14 @@ void TGACompiler::load_compressed(std::fstream& in_file)
 
 	while (i < size)
 	{
-		in_file.read((char*)&rle_id, sizeof(uint8_t));
+		in_file->read((char*)&rle_id, sizeof(uint8_t));
 
 		// If MSB == 1
 		if (rle_id & 0x80)
 		{
 			rle_id -= 127;
 			
-			in_file.read((char*)&colors, m_tga_channels);
+			in_file->read((char*)&colors, m_tga_channels);
 
 			while (rle_id)
 			{
@@ -222,7 +220,7 @@ void TGACompiler::load_compressed(std::fstream& in_file)
 
 			while (rle_id)
 			{
-				in_file.read((char*)colors, m_tga_channels);
+				in_file->read((char*)colors, m_tga_channels);
 				
 				m_texture_data[colors_read + 0] = colors[2];
 				m_texture_data[colors_read + 1] = colors[1];
@@ -242,7 +240,7 @@ void TGACompiler::load_compressed(std::fstream& in_file)
 }
 
 //-----------------------------------------------------------------------------
-void TGACompiler::swap_red_blue()
+void TextureCompiler::swap_red_blue()
 {
 	for (uint64_t i = 0; i < m_tga_size * m_tga_channels; i += m_tga_channels)
 	{

+ 8 - 8
tools/compilers/tga/TGACompiler.h → engine/compilers/texture/TextureCompiler.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Compiler.h"
-#include "TextureFormat.h"
+#include "TextureResource.h"
 
 namespace crown
 {
@@ -47,20 +47,20 @@ struct TGAHeader
 	char		image_descriptor;	// 11h  Image descriptor byte
 };
 
-class TGACompiler : public Compiler
+class CE_EXPORT TextureCompiler : public Compiler
 {
 public:
 
-					TGACompiler();
-					~TGACompiler();
+					TextureCompiler();
+					~TextureCompiler();
 
-	size_t			compile_impl(const char* resource_path);
-	void			write_impl(std::fstream& out_file);
+	size_t			compile_impl(Filesystem& fs, const char* resource_path);
+	void			write_impl(File* out_file);
 
 private:
 
-	void			load_uncompressed(std::fstream& in_file);
-	void			load_compressed(std::fstream& in_file);
+	void			load_uncompressed(File* in_file);
+	void			load_compressed(File* in_file);
 	void			swap_red_blue();
 
 private:

+ 1 - 1
engine/core/Args.h

@@ -55,7 +55,7 @@ struct ArgsOption
 };
 
 /// Parses the command line arguments in a way very similar to GNU getopt.
-class Args
+class CE_EXPORT Args
 {
 public:
 

+ 4 - 2
engine/core/Assert.h

@@ -31,13 +31,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Config.h"
 #include "Log.h"
 
-#ifdef CROWN_DEBUG
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
 	#define CE_ASSERT(condition, ...) do { if (!(condition)) {\
 		crown::Log::e("Assertion failed: %s", #condition);\
 		crown::Log::e("\t" __VA_ARGS__);\
-		crown::Log::e("\n\tIn %s:%d\n\n", __FILE__, __LINE__); abort();} } while (0)
+		crown::Log::e("\n\tIn %s:%d\n\n", __FILE__, __LINE__);\
+		crown::Log::flush(); abort();} } while (0)
 #else
 	#define CE_ASSERT(...) ((void)0)
 #endif
 
 #define CE_ASSERT_NOT_NULL(x) CE_ASSERT(x != NULL, "Parameter must be not null")
+#define CE_FATAL(msg) CE_ASSERT(false, msg)

+ 27 - 25
engine/core/Log.cpp

@@ -25,13 +25,19 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "Log.h"
-#include "OS.h"
+#include "LinearAllocator.h"
+#include "StringStream.h"
+#include "Device.h"
+#include "RPCServer.h"
 
 namespace crown
 {
 
+static char g_buffer[16 * 1024];
+static LinearAllocator g_allocator(g_buffer, 16 * 1024);
+static StringStream g_stream(g_allocator);
+
 LogLevel Log::m_threshold = LL_DEBUG;
-int32_t Log::m_indent_count = 0;
 
 //-----------------------------------------------------------------------------
 LogLevel Log::threshold()
@@ -55,21 +61,18 @@ void Log::log_message(LogLevel level, const char* message, ::va_list arg)
 
 	switch (level)
 	{
-		case LL_DEBUG:
-			os::log_info(message, arg);
-			break;
-		case LL_ERROR:
-			os::log_error(message, arg);
-			break;
-		case LL_WARN:
-			os::log_warning(message, arg);
-			break;
-		case LL_INFO:
-			os::log_info(message, arg);
-			break;
-		default:
-			break;
+		case LL_DEBUG: g_stream << "D: "; break;
+		case LL_ERROR: g_stream << "E: "; break;
+		case LL_WARN: g_stream << "W: "; break;
+		case LL_INFO: g_stream << "I: "; break;
+		default: break;
 	}
+
+	char buf[1024];
+	int len = vsnprintf(buf, 1024 - 2, message, arg);
+	buf[len] = '\n';
+	buf[len + 1] = '\0';
+	g_stream << buf;
 }
 
 //-----------------------------------------------------------------------------
@@ -109,19 +112,18 @@ void Log::i(const char* message, ...)
 }
 
 //-----------------------------------------------------------------------------
-void Log::indent_in()
+void Log::flush()
 {
-	m_indent_count += 1;
-}
+	os::printf(g_stream.c_str());
+	::fflush(stdout);
 
-//-----------------------------------------------------------------------------
-void Log::indent_out()
-{
-	if (m_indent_count > 0)
+	if (device()->rpc() != NULL)
 	{
-		m_indent_count -= 1;
+		device()->rpc()->send_message_to_all(g_stream.c_str());
 	}
+
+	g_stream.clear();
+	g_allocator.clear();
 }
 
 } // namespace crown
-

+ 4 - 4
engine/core/Log.h

@@ -42,8 +42,10 @@ enum LogLevel
 	LL_DEBUG	= 3
 };
 
+class RPCServer;
+
 /// Used to log messages.
-class Log
+class CE_EXPORT Log
 {
 
 public:
@@ -61,13 +63,11 @@ public:
 	static void			w(const char* message, ...);
 	static void			i(const char* message, ...);
 
-	static void			indent_in();
-	static void			indent_out();
+	static void			flush();
 
 private:
 
 	static LogLevel		m_threshold;
-	static int32_t		m_indent_count;
 };
 
 } // namespace crown

+ 2 - 0
engine/core/Types.h

@@ -33,8 +33,10 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #ifdef WINDOWS
 	#define CE_EXPORT __declspec(dllexport)
+	#define CE_INLINE __inline
 #else
 	#define CE_EXPORT __attribute__ ((visibility("default")))
+	#define CE_INLINE inline
 #endif
 
 #ifndef NULL

+ 37 - 40
engine/core/containers/IdTable.h

@@ -33,25 +33,22 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+#define INVALID_ID 65535
+
 struct Id
 {
-	union
-	{
-		uint16_t id;
-		uint16_t next;
-	};
-
+	uint16_t id;
 	uint16_t index;
 };
 
 /// Table of Ids.
+template <uint32_t MAX_NUM_ID>
 class IdTable
 {
 public:
 
-	/// Creates the table for tracking exactly @a max_ids - 1 unique Ids.
-					IdTable(Allocator& allocator, uint16_t max_ids);
-					~IdTable();
+	/// Creates the table for tracking exactly @a MAX_NUM_ID - 1 unique Ids.
+					IdTable();
 
 	/// Returns a new Id.
 	Id				create();
@@ -62,6 +59,8 @@ public:
 	/// Returns whether the table has the specified @a id
 	bool			has(Id id) const;
 
+	const Id*		begin() const;
+
 private:
 
 	// Returns the next available unique id.
@@ -69,13 +68,6 @@ private:
 
 private:
 
-	Allocator&		m_allocator;
-
-	// The maximum number of Ids the table can track.
-	// The last valid id is reserved and cannot be used to
-	// refer to Ids from the outside.
-	const uint16_t	m_max_ids;
-
 	// The index of the first unused id.
 	uint16_t		m_freelist;
 
@@ -86,41 +78,35 @@ private:
 	uint16_t		m_next_id;
 
 	// Table of ids.
-	Id*				m_ids;
+	// The last valid id is reserved and cannot be used to
+	// refer to Ids from the outside.
+	Id				m_ids[MAX_NUM_ID];
 };
 
 //-----------------------------------------------------------------------------
-inline IdTable::IdTable(Allocator& allocator, uint16_t max_ids) :
-	m_allocator(allocator),
-	m_max_ids(max_ids),
-	m_freelist(max_ids),
-	m_last_index(0),
-	m_next_id(0)
-{
-	m_ids = (Id*)m_allocator.allocate(m_max_ids * sizeof(Id));
-}
-
-//-----------------------------------------------------------------------------
-inline IdTable::~IdTable()
+template <uint32_t MAX_NUM_ID>
+inline IdTable<MAX_NUM_ID>::IdTable()
+	: m_freelist(MAX_NUM_ID), m_last_index(0), m_next_id(0)
 {
-	if (m_ids)
+	for (uint32_t i = 0; i < MAX_NUM_ID; i++)
 	{
-		m_allocator.deallocate(m_ids);
+		m_ids[i].id = INVALID_ID;
 	}
 }
 
 //-----------------------------------------------------------------------------
-inline Id IdTable::create()
+template <uint32_t MAX_NUM_ID>
+inline Id IdTable<MAX_NUM_ID>::create()
 {
 	// Obtain a new id
 	Id id;
 	id.id = next_id();
 
 	// Recycle slot if there are any
-	if (m_freelist != m_max_ids)
+	if (m_freelist != MAX_NUM_ID)
 	{
 		id.index = m_freelist;
-		m_freelist = m_ids[m_freelist].next;
+		m_freelist = m_ids[m_freelist].id;
 	}
 	else
 	{
@@ -133,24 +119,35 @@ inline Id IdTable::create()
 }
 
 //-----------------------------------------------------------------------------
-inline void IdTable::destroy(Id id)
+template <uint32_t MAX_NUM_ID>
+inline void IdTable<MAX_NUM_ID>::destroy(Id id)
 {
 	CE_ASSERT(has(id), "IdTable does not have ID: %d,%d", id.id, id.index);
 
-	m_ids[id.index].next = m_freelist;
+	m_ids[id.index].id = INVALID_ID;
+	m_ids[id.index].index = m_freelist;
 	m_freelist = id.index;
 }
 
 //-----------------------------------------------------------------------------
-inline bool IdTable::has(Id id) const
+template <uint32_t MAX_NUM_ID>
+inline bool IdTable<MAX_NUM_ID>::has(Id id) const
+{
+	return id.index < MAX_NUM_ID && m_ids[id.index].id == id.id;
+}
+
+//-----------------------------------------------------------------------------
+template <uint32_t MAX_NUM_ID>
+inline const Id* IdTable<MAX_NUM_ID>::begin() const
 {
-	return id.index < m_max_ids && m_ids[id.index].id == id.id;
+	return m_ids;
 }
 
 //-----------------------------------------------------------------------------
-inline uint16_t IdTable::next_id()
+template <uint32_t MAX_NUM_ID>
+inline uint16_t IdTable<MAX_NUM_ID>::next_id()
 {
-	CE_ASSERT(m_next_id < m_max_ids, "Maximum number of IDs reached");
+	CE_ASSERT(m_next_id < MAX_NUM_ID, "Maximum number of IDs reached");
 
 	return m_next_id++;
 }

+ 16 - 24
engine/core/containers/List.h

@@ -47,7 +47,7 @@ public:
 
 	/// Allocates capacity * sizeof(T) bytes.
 						List(Allocator& allocator, uint32_t capacity);
-						List(const List<T>& list);
+						List(const List<T>& other);
 						~List();
 
 	/// Random access by index
@@ -116,7 +116,7 @@ public:
 
 private:
 
-	Allocator&			m_allocator;
+	Allocator*			m_allocator;
 	uint32_t			m_capacity;
 	uint32_t			m_size;
 	T*					m_array;
@@ -124,33 +124,25 @@ private:
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline List<T>::List(Allocator& allocator) :
-	m_allocator(allocator),
-	m_capacity(0),
-	m_size(0),
-	m_array(NULL)
+inline List<T>::List(Allocator& allocator)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
 {
 }
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline List<T>::List(Allocator& allocator, uint32_t capacity) :
-	m_allocator(allocator),
-	m_capacity(0),
-	m_size(0),
-	m_array(NULL)
+inline List<T>::List(Allocator& allocator, uint32_t capacity)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
 {
 	resize(capacity);
 }
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline List<T>::List(const List<T>& list) :
-	m_capacity(0),
-	m_size(0),
-	m_array(NULL)
+inline List<T>::List(const List<T>& other)
+	: m_allocator(other.m_allocator), m_capacity(0), m_size(0), m_array(NULL)
 {
-	*this = list;
+	*this = other;
 }
 
 //-----------------------------------------------------------------------------
@@ -159,7 +151,7 @@ inline List<T>::~List()
 {
 	if (m_array)
 	{
-		m_allocator.deallocate(m_array);
+		m_allocator->deallocate(m_array);
 	}
 }
 
@@ -167,7 +159,7 @@ inline List<T>::~List()
 template <typename T>
 inline T& List<T>::operator[](uint32_t index)
 {
-	//CE_ASSERT(index < m_size);
+	CE_ASSERT(index < m_size, "Index out of bounds");
 
 	return m_array[index];
 }
@@ -176,7 +168,7 @@ inline T& List<T>::operator[](uint32_t index)
 template <typename T>
 inline const T& List<T>::operator[](uint32_t index) const
 {
-	//CE_ASSERT(index < m_size);
+	CE_ASSERT(index < m_size, "Index out of bounds");
 
 	return m_array[index];
 }
@@ -243,13 +235,13 @@ inline void List<T>::set_capacity(uint32_t capacity)
 		T* tmp = m_array;
 		m_capacity = capacity;
 
-		m_array = (T*)m_allocator.allocate(capacity * sizeof(T));
+		m_array = (T*)m_allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
 
 		memcpy(m_array, tmp, m_size * sizeof(T));
 
 		if (tmp)
 		{
-			m_allocator.deallocate(tmp);
+			m_allocator->deallocate(tmp);
 		}
 	}
 }
@@ -326,7 +318,7 @@ inline const List<T>& List<T>::operator=(const List<T>& other)
 {
 	if (m_array)
 	{
-		m_allocator.deallocate(m_array);
+		m_allocator->deallocate(m_array);
 	}
 
 	m_size = other.m_size;
@@ -334,7 +326,7 @@ inline const List<T>& List<T>::operator=(const List<T>& other)
 
 	if (m_capacity)
 	{
-		m_array = (T*)m_allocator.allocate(m_capacity * sizeof(T));
+		m_array = (T*)m_allocator->allocate(m_capacity * sizeof(T), CE_ALIGNOF(T));
 
 		memcpy(m_array, other.m_array, m_size * sizeof(T));
 	}

+ 88 - 109
tools/core/strings/StringUtils.h → engine/core/containers/PriorityQueue.h

@@ -26,178 +26,157 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include <cstdio>
-#include <cstring>
-
-#include "Assert.h"
-#include "Types.h"
+#include <algorithm>
+#include "List.h"
 
 namespace crown
 {
-namespace string
+
+template <typename T>
+class PriorityQueue
 {
+public:
+
+	/// Does not allocate memory.
+					PriorityQueue(Allocator& a);
+					~PriorityQueue();
+
+	/// Returns whether the queue is empty.
+	bool			empty() const;
+
+	/// Returns the number of items in the queue.
+	uint32_t		size() const;
+
+	/// Returns the first item in the queue.
+	const T&		top() const;
+
+	/// Inserts @a item into the queue.
+	void			push(const T& item);
+
+	/// Removes the first item from the queue.
+	void			pop();
+
+	T*				begin();
+	const T*		begin() const;
+	T*				end();
+	const T*		end() const;
+
+	T&				front();
+	const T&		front() const;
+	T&				back();
+	const T&		back() const;
 
-const char* const	EMPTY = "";
+private:
+
+	List<T>			m_queue;
+};
 
 //-----------------------------------------------------------------------------
-inline bool is_alpha(char c)
+template <typename T>
+PriorityQueue<T>::PriorityQueue(Allocator& a) :
+	m_queue(a)
 {
-	return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
 }
 
 //-----------------------------------------------------------------------------
-inline bool is_digit(char c)
+template <typename T>
+PriorityQueue<T>::~PriorityQueue()
 {
-	return !(c < '0' || c > '9');
 }
 
 //-----------------------------------------------------------------------------
-inline bool is_upper(char c)
+template <typename T>
+bool PriorityQueue<T>::empty() const
 {
-	return (c >= 'A' && c <= 'Z');
+	return m_queue.empty();
 }
 
 //-----------------------------------------------------------------------------
-inline bool is_lower(char c)
+template <typename T>
+uint32_t PriorityQueue<T>::size() const
 {
-	return (c >= 'a' && c <= 'z');
+	return m_queue.size();
 }
 
 //-----------------------------------------------------------------------------
-inline bool is_whitespace(char c)
+template <typename T>
+const T& PriorityQueue<T>::top() const
 {
-	return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+	return m_queue.front();
 }
 
 //-----------------------------------------------------------------------------
-inline size_t strlen(const char* str)
+template <typename T>
+void PriorityQueue<T>::push(const T& item)
 {
-	size_t chars = 0;
-
-	while(*str)
-	{
-		if ((*str & 0xC0) != 0x80)
-		{
-			chars++;
-		}
-		str++;
-	}
+	m_queue.push_back(item);
 
-	return chars;
+	std::push_heap(begin(), end());
 }
 
 //-----------------------------------------------------------------------------
-inline const char* strstr(const char* str1, const char* str2)
+template <typename T>
+void PriorityQueue<T>::pop()
 {
-	return ::strstr(str1, str2);
-}
+	std::pop_heap(begin(), end());
 
-//-----------------------------------------------------------------------------
-inline int32_t strcmp(const char* str1, const char* str2)
-{
-	return ::strcmp(str1, str2);
+	m_queue.pop_back();
 }
 
 //-----------------------------------------------------------------------------
-inline char* strncpy(char* dest, const char* src, size_t len)
+template <typename T>
+const T* PriorityQueue<T>::begin() const
 {
-	char* ret = ::strncpy(dest, src, len);
-	dest[len - 1] = '\0';
-
-	return ret;
+	return m_queue.begin();
 }
 
 //-----------------------------------------------------------------------------
-inline char* strcat(char* dest, const char* src)
+template <typename T>
+T* PriorityQueue<T>::begin()
 {
-	return ::strcat(dest, src);
+	return m_queue.begin();
 }
 
 //-----------------------------------------------------------------------------
-inline char* strncat(char* dest, const char* src, size_t len)
+template <typename T>
+const T* PriorityQueue<T>::end() const
 {
-	return ::strncat(dest, src, len);
+	return m_queue.end();
 }
 
 //-----------------------------------------------------------------------------
-inline const char* begin(const char* str)
+template <typename T>
+T* PriorityQueue<T>::end()
 {
-	CE_ASSERT(str != NULL, "Str must be != NULL");
-	
-	return str;
+	return m_queue.end();
 }
 
 //-----------------------------------------------------------------------------
-inline const char* end(const char* str)
+template <typename T>
+const T& PriorityQueue<T>::front() const
 {
-	CE_ASSERT(str != NULL, "Str must be != NULL");
-	
-	return str + string::strlen(str) + 1;
+	return m_queue.front();
 }
 
 //-----------------------------------------------------------------------------
-inline const char* find_first(const char* str, char c)
-{
-	CE_ASSERT(str != NULL, "Str must be != NULL");
-
-	const char* str_begin = string::begin(str);
-	
-	while (str_begin != string::end(str))
-	{
-		if ((*str_begin) == c)
-		{
-			return str_begin;
-		}
-		
-		str_begin++;
-	}
-	
-	return string::end(str);
+template <typename T>
+T& PriorityQueue<T>::front()
+{
+	return m_queue.front();
 }
 
 //-----------------------------------------------------------------------------
-inline const char* find_last(const char* str, char c)
-{
-	CE_ASSERT(str != NULL, "Str must be != NULL");
-	
-	const char* str_end = string::end(str) - 1;
-	
-	while (str_end != string::begin(str) - 1)
-	{
-		if ((*str_end) == c)
-		{
-			return str_end;
-		}
-		
-		str_end--;
-	}
-	
-	return string::end(str);
+template <typename T>
+const T& PriorityQueue<T>::back() const
+{
+	return m_queue.back();
 }
 
 //-----------------------------------------------------------------------------
-inline void substring(const char* begin, const char* end, char* out, size_t len)
-{
-	CE_ASSERT(begin != NULL, "Begin must be != NULL");
-	CE_ASSERT(end != NULL, "End must be != NULL");
-	CE_ASSERT(out != NULL, "Out must be != NULL");
-	
-	size_t i = 0;
-	
-	char* out_iterator = out;
-
-	while (begin != end && i < len)
-	{
-		(*out_iterator) = (*begin);
-		
-		begin++;
-		out_iterator++;
-		i++;
-	}
-
-	out[i] = '\0';
+template <typename T>
+T& PriorityQueue<T>::back()
+{
+	return m_queue.back();
 }
 
-} // namespace string
 } // namespace crown
-

+ 47 - 4
engine/core/containers/Queue.h

@@ -75,18 +75,24 @@ public:
 	/// time of call.
 	void			grow(uint32_t min_capacity);
 
-	/// Adds an @a item to the back of the queue
+	/// Appends an @a item to the back of the queue
 	void			push_back(const T& item);
 
 	/// Removes the last item from the queue
 	void			pop_back();
 
-	/// Adds an @a item to the front of the queue
+	/// Appends an @a item to the front of the queue
 	void			push_front(const T& item);
 
 	/// Removes the first item from the queue
 	void			pop_front();
-	
+
+	/// Appends @a n @a items to the back of the queue
+	void			push(const T *items, uint32_t n);
+
+	/// Removes @a n items from the front of the queue
+	void			pop(uint32_t n);
+
 	/// Clears the content of the queue.
 	/// @note
 	/// Does not free memory nor call destructors, it only zeroes
@@ -236,10 +242,47 @@ inline void Queue<T>::pop_front()
 	CE_ASSERT(m_size > 0, "The queue is empty");
 
 	m_read = (m_read + 1) % m_queue.size();
-
 	m_size--;
 }
 
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Queue<T>::push(const T *items, uint32_t n)
+{
+	if (space() < n)
+	{
+		grow(size() + n);		
+	}
+
+	const uint32_t size = m_queue.size();
+	const uint32_t insert = (m_read + m_size) % size;
+
+	uint32_t to_insert = n;
+	if (insert + to_insert > size)
+	{
+		to_insert = size - insert;
+	}
+
+	memcpy(m_queue.begin() + insert, items, to_insert * sizeof(T));
+
+	m_size += to_insert;
+	items += to_insert;
+	n -= to_insert;
+	memcpy(m_queue.begin(), items, n * sizeof(T));
+
+	m_size += n;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Queue<T>::pop(uint32_t n)
+{
+	CE_ASSERT(m_size > 0, "The queue is empty");
+
+	m_read = (m_read + n) % m_queue.size();
+	m_size -= n;
+}
+
 //-----------------------------------------------------------------------------
 template <typename T>
 inline void Queue<T>::clear()

+ 426 - 0
engine/core/containers/Vector.h

@@ -0,0 +1,426 @@
+/*
+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 "Allocator.h"
+#include "Types.h"
+#include "Assert.h"
+
+namespace crown
+{
+
+/// Dynamic array of objects.
+/// @note
+/// Calls constructors and destructors, not suitable for performance-critical stuff.
+/// If your data is POD, use List<T> instead.
+template <typename T>
+class Vector
+{
+public:
+
+	/// Does not allocate memory.
+						Vector(Allocator& allocator);
+
+	/// Allocates capacity * sizeof(T) bytes.
+						Vector(Allocator& allocator, uint32_t capacity);
+						Vector(const Vector<T>& other);
+						~Vector();
+
+	/// Random access by index
+	T&					operator[](uint32_t index);
+
+	/// Random access by index
+	const T&			operator[](uint32_t index) const;
+
+	/// Returns whether the vector is empty
+	bool				empty() const;
+
+	/// Returns the number of items in the vector
+	uint32_t			size() const;
+
+	/// Returns the maximum number of items the array can hold
+	uint32_t			capacity() const;
+
+	/// Resizes the vector to the given @a size.
+	/// @note
+	/// Old items will be copied to the newly created vector.
+	/// If the new capacity is smaller than the previous one, the
+	/// vector will be truncated.
+	void				resize(uint32_t size);
+
+	/// Reserves space in the vector for at least @a capacity items.
+	void				reserve(uint32_t capacity);
+
+	/// Sets the vector capacity
+	void				set_capacity(uint32_t capacity);
+
+	/// Grows the vector to contain at least @a min_capacity items
+	void				grow(uint32_t min_capacity);
+
+	/// Condenses the array so that the capacity matches the actual number
+	/// of items in the vector.
+	void				condense();
+
+	/// Appends an item to the vector and returns its index.
+	uint32_t			push_back(const T& item);
+
+	/// Removes the last item from the vector.
+	void				pop_back();
+
+	/// Appends @a count @a items to the vector and returns the number
+	/// of items in the vector after the append operation.
+	uint32_t			push(const T* items, uint32_t count);
+
+	/// Clears the content of the vector.
+	/// @note
+	/// Does not free memory nor call destructors, it only zeroes
+	/// the number of items in the vector for efficiency.
+	void				clear();
+
+	/// Copies the content of the @a other vector into this one.
+	const Vector<T>&		operator=(const Vector<T>& other);
+
+	T*					begin();
+	const T*			begin() const;
+	T*					end();
+	const T*			end() const;
+
+	T&					front();
+	const T&			front() const;
+	T&					back();
+	const T&			back() const;
+
+private:
+
+	Allocator*			m_allocator;
+	uint32_t			m_capacity;
+	uint32_t			m_size;
+	T*					m_array;
+};
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline Vector<T>::Vector(Allocator& allocator)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline Vector<T>::Vector(Allocator& allocator, uint32_t capacity)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+	resize(capacity);
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline Vector<T>::Vector(const Vector<T>& other)
+	: m_allocator(other.m_allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+	*this = other;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline Vector<T>::~Vector()
+{
+	if (m_array)
+	{
+		for (uint32_t i = 0; i < m_size; i++)
+		{
+			m_array[i].~T();
+		}
+		m_allocator->deallocate(m_array);
+	}
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline T& Vector<T>::operator[](uint32_t index)
+{
+	CE_ASSERT(index < m_size, "Index out of bounds");
+
+	return m_array[index];
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const T& Vector<T>::operator[](uint32_t index) const
+{
+	CE_ASSERT(index < m_size, "Index out of bounds");
+
+	return m_array[index];
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline bool Vector<T>::empty() const
+{
+	return m_size == 0;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline uint32_t Vector<T>::size() const
+{
+	return m_size;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline uint32_t Vector<T>::capacity() const
+{
+	return m_capacity;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::resize(uint32_t size)
+{
+	if (size > m_capacity)
+	{
+		set_capacity(size);
+	}
+
+	m_size = size;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::reserve(uint32_t capacity)
+{
+	if (capacity > m_capacity)
+	{
+		grow(capacity);
+	}
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::set_capacity(uint32_t capacity)
+{
+	if (capacity == m_capacity)
+	{
+		return;
+	}
+
+	if (capacity < m_size)
+	{
+		resize(capacity);
+	}
+
+	if (capacity > 0)
+	{
+		T* tmp = m_array;
+		m_capacity = capacity;
+
+		m_array = (T*)m_allocator->allocate(capacity * sizeof(T));
+
+		for (uint32_t i = 0; i < m_size; i++)
+		{
+			new (m_array + i) T(tmp[i]);
+		}
+
+		if (tmp)
+		{
+			for (uint32_t i = 0; i < m_size; i++)
+			{
+				tmp[i].~T();
+			}
+			m_allocator->deallocate(tmp);
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::grow(uint32_t min_capacity)
+{
+	uint32_t new_capacity = m_capacity * 2 + 1;
+
+	if (new_capacity < min_capacity)
+	{
+		new_capacity = min_capacity;
+	}
+
+	set_capacity(new_capacity);
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::condense()
+{
+	resize(m_size);
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline uint32_t Vector<T>::push_back(const T& item)
+{
+	if (m_capacity == m_size)
+	{
+		grow(0);
+	}
+
+	new (m_array + m_size) T(item);
+
+	return m_size++;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::pop_back()
+{
+	CE_ASSERT(m_size > 0, "The vector is empty");
+
+	m_size--;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline uint32_t Vector<T>::push(const T* items, uint32_t count)
+{
+	if (m_capacity <= m_size + count)
+	{
+		grow(m_size + count);
+	}
+
+	T* arr = &m_array[m_size];
+	for (uint32_t i = 0; i < count; i++)
+	{
+		arr[i] = items[i];
+	}
+
+	m_size += count;
+
+	return m_size;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline void Vector<T>::clear()
+{
+	for (uint32_t i = 0; i < m_size; i++)
+	{
+		m_array[i].~T();
+	}
+
+	m_size = 0;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const Vector<T>& Vector<T>::operator=(const Vector<T>& other)
+{
+	if (m_array)
+	{
+		m_allocator->deallocate(m_array);
+	}
+
+	m_size = other.m_size;
+	m_capacity = other.m_capacity;
+
+	if (m_capacity)
+	{
+		m_array = (T*)m_allocator->allocate(m_capacity * sizeof(T));
+
+		for (uint32_t i = 0; i < m_size; i++)
+		{
+			m_array[i] = other.m_array[i];
+		}
+	}
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const T* Vector<T>::begin() const
+{
+	return m_array;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline T* Vector<T>::begin()
+{
+	return m_array;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const T* Vector<T>::end() const
+{
+	return m_array + m_size;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline T* Vector<T>::end()
+{
+	return m_array + m_size;
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline T& Vector<T>::front()
+{
+	CE_ASSERT(m_size > 0, "The vector is empty");
+
+	return m_array[0];
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const T& Vector<T>::front() const
+{
+	CE_ASSERT(m_size > 0, "The vector is empty");
+
+	return m_array[0];
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline T& Vector<T>::back()
+{
+	CE_ASSERT(m_size > 0, "The vector is empty");
+
+	return m_array[m_size - 1];
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline const T& Vector<T>::back() const
+{
+	CE_ASSERT(m_size > 0, "The vector is empty");
+
+	return m_array[m_size - 1];
+}
+
+} // namespace crown
+

+ 0 - 102
engine/core/filesystem/BinaryReader.cpp

@@ -1,102 +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 "BinaryReader.h"
-#include "File.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-BinaryReader::BinaryReader(File& file) : m_file(file)
-{
-}
-
-//-----------------------------------------------------------------------------
-int8_t BinaryReader::read_byte()
-{
-	int8_t buffer;
-	m_file.read(&buffer, sizeof(int8_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-int16_t BinaryReader::read_int16()
-{
-	int16_t buffer;
-	m_file.read(&buffer, sizeof(int16_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-uint16_t BinaryReader::read_uint16()
-{
-	uint16_t buffer;
-	m_file.read(&buffer, sizeof(uint16_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-int32_t BinaryReader::read_int32()
-{
-	int32_t buffer;
-	m_file.read(&buffer, sizeof(int32_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-uint32_t BinaryReader::read_uint32()
-{
-	uint32_t buffer;
-	m_file.read(&buffer, sizeof(uint32_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-int64_t BinaryReader::read_int64()
-{
-	int64_t buffer;
-	m_file.read(&buffer, sizeof(int64_t));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-double BinaryReader::read_double()
-{
-	double buffer;
-	m_file.read(&buffer, sizeof(double));
-	return buffer;
-}
-
-//-----------------------------------------------------------------------------
-float BinaryReader::read_float()
-{
-	float buffer;
-	m_file.read(&buffer, sizeof(float));
-	return buffer;
-}
-
-} // namespace crown

+ 66 - 10
engine/core/filesystem/BinaryReader.h

@@ -36,20 +36,76 @@ class BinaryReader
 {
 public:
 
-						BinaryReader(File& file);
+	//-----------------------------------------------------------------------------
+	BinaryReader(File& file) : m_file(file) {}
 
-	int8_t				read_byte();
-	int16_t				read_int16();
-	uint16_t			read_uint16();
-	int32_t				read_int32();
-	uint32_t			read_uint32();
-	int64_t				read_int64();
-	float				read_float();
-	double				read_double();
+	//-----------------------------------------------------------------------------
+	int8_t read_byte()
+	{
+		int8_t buffer;
+		m_file.read(&buffer, sizeof(int8_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	int16_t read_int16()
+	{
+		int16_t buffer;
+		m_file.read(&buffer, sizeof(int16_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint16_t read_uint16()
+	{
+		uint16_t buffer;
+		m_file.read(&buffer, sizeof(uint16_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	int32_t read_int32()
+	{
+		int32_t buffer;
+		m_file.read(&buffer, sizeof(int32_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint32_t read_uint32()
+	{
+		uint32_t buffer;
+		m_file.read(&buffer, sizeof(uint32_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	int64_t read_int64()
+	{
+		int64_t buffer;
+		m_file.read(&buffer, sizeof(int64_t));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	double read_double()
+	{
+		double buffer;
+		m_file.read(&buffer, sizeof(double));
+		return buffer;
+	}
+
+	//-----------------------------------------------------------------------------
+	float read_float()
+	{
+		float buffer;
+		m_file.read(&buffer, sizeof(float));
+		return buffer;
+	}
 
 private:
 
-	File&				m_file;
+	File& m_file;
 };
 
 } // namespace crown

+ 50 - 10
engine/core/filesystem/BinaryWriter.h

@@ -36,20 +36,60 @@ class BinaryWriter
 {
 public:
 
-						BinaryWriter(File& file);
+	//-----------------------------------------------------------------------------
+	BinaryWriter(File& file) : m_file(file) {}
 
-	void				write_byte(int8_t);
-	void				write_int16(int16_t);
-	void				write_uint16(uint16_t);
-	void				write_int32(int32_t);
-	void				write_uint32(uint32_t);
-	void				write_int64(int64_t);
-	void				write_double(double);
-	void				write_float(float);
+	//-----------------------------------------------------------------------------
+	void write_byte(int8_t buffer)
+	{
+		m_file.write(&buffer, sizeof(int8_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_int16(int16_t buffer)
+	{
+		m_file.write(&buffer, sizeof(int16_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_uint16(uint16_t buffer)
+	{
+		m_file.write(&buffer, sizeof(uint16_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_int32(int32_t buffer)
+	{
+		m_file.write(&buffer, sizeof(int32_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_uint32(uint32_t buffer)
+	{
+		m_file.write(&buffer, sizeof(uint32_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_int64(int64_t buffer)
+	{
+		m_file.write(&buffer, sizeof(int64_t));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_double(double buffer)
+	{
+		m_file.write(&buffer, sizeof(double));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write_float(float buffer)
+	{
+		m_file.write(&buffer, sizeof(float));
+	}
 
 private:
 
-	File&				m_file;
+	File& m_file;
 };
 
 } // namespace crown

+ 2 - 2
engine/core/filesystem/DiskFile.cpp

@@ -83,7 +83,7 @@ void DiskFile::read(void* buffer, size_t size)
 	}
 
 	size_t bytes_read = m_file.read(buffer, size);
-	CE_ASSERT(bytes_read == size, "Failed to read from file");
+	CE_ASSERT(bytes_read == size, "Failed to read from file: requested: %lu, read: %lu", size, bytes_read);
 }
 
 //-----------------------------------------------------------------------------
@@ -98,7 +98,7 @@ void DiskFile::write(const void* buffer, size_t size)
 	}
 
 	size_t bytes_written = m_file.write(buffer, size);
-	CE_ASSERT(bytes_written == size, "Failed to write to file");
+	CE_ASSERT(bytes_written == size, "Failed to write to file: requested: %lu, written: %lu", size, bytes_written);
 }
 
 //-----------------------------------------------------------------------------

+ 168 - 0
engine/core/filesystem/DiskFilesystem.cpp

@@ -0,0 +1,168 @@
+/*
+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 "DiskFilesystem.h"
+#include "StringUtils.h"
+#include "TempAllocator.h"
+#include "DiskFile.h"
+#include "OS.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+DiskFilesystem::DiskFilesystem()
+{
+	string::strncpy(m_root_path, os::get_cwd(), MAX_PATH_LENGTH);
+}
+
+//-----------------------------------------------------------------------------
+DiskFilesystem::DiskFilesystem(const char* root_path)
+{
+	CE_ASSERT_NOT_NULL(root_path);
+
+	string::strncpy(m_root_path, root_path, MAX_PATH_LENGTH);
+}
+
+//-----------------------------------------------------------------------------
+File* DiskFilesystem::open(const char* path, FileOpenMode mode)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	return CE_NEW(default_allocator(), DiskFile)(mode, abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::close(File* file)
+{
+	CE_ASSERT_NOT_NULL(file);
+
+	CE_DELETE(default_allocator(), file);
+}
+
+//-----------------------------------------------------------------------------
+bool DiskFilesystem::is_directory(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	return os::is_directory(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+bool DiskFilesystem::is_file(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	return os::is_file(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::create_directory(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	os::create_directory(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::delete_directory(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	os::delete_directory(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::create_file(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	os::create_file(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::delete_file(const char* path)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	os::delete_file(abs_path.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::list_files(const char* path, Vector<DynamicString>& files)
+{
+	CE_ASSERT_NOT_NULL(path);
+
+	TempAllocator256 alloc;
+	DynamicString abs_path(alloc);
+	get_absolute_path(path, abs_path);
+
+	os::list_files(abs_path.c_str(), files);
+}
+
+//-----------------------------------------------------------------------------
+void DiskFilesystem::get_absolute_path(const char* path, DynamicString& os_path)
+{
+	if (os::is_absolute_path(path))
+	{
+		os_path = path;
+		return;
+	}
+
+	os_path += m_root_path;
+	os_path += PATH_SEPARATOR;
+	os_path += path;
+}
+
+} // namespace crown

+ 91 - 0
engine/core/filesystem/DiskFilesystem.h

@@ -0,0 +1,91 @@
+/*
+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 "Filesystem.h"
+#include "OS.h" // For MAX_PATH_LENGTH
+
+namespace crown
+{
+
+/// Access files on disk.
+/// All the file paths can be either relative or absolute.
+/// When a relative path is given, it is automatically translated
+/// to its absolute counterpart based on the file source's root path.
+/// Accessing files using absolute path directly is also possible,
+/// but platform-specific and thus generally not recommended.
+class DiskFilesystem : public Filesystem
+{
+public:
+
+	/// Sets the root path to the current working directory of
+	/// the engine executable.
+	DiskFilesystem();
+
+	/// Sets the root path to the given @a root_path.
+	/// @note
+	/// The @a root_path must be absolute.
+	DiskFilesystem(const char* root_path);
+
+	/// Opens the file at the given @a path with the given @a mode.
+	File* open(const char* path, FileOpenMode mode);
+
+	/// Closes the given @a file.
+	void close(File* file);
+
+	/// Returns true if @a path is a directory.
+	bool is_directory(const char* path);
+
+	/// Returns true if @a path is a regular file.
+	bool is_file(const char* path);
+
+	/// Creates the directory at the given @a path.
+	void create_directory(const char* path);
+
+	/// Deletes the directory at the given @a path.
+	void delete_directory(const char* path);
+
+	/// Creates the file at the given @a path.
+	void create_file(const char* path);
+
+	/// Deletes the file at the given @a path.
+	void delete_file(const char* path);
+
+	/// Returns the relative file names in the given @a path.
+	void list_files(const char* path, Vector<DynamicString>& files);
+
+	/// Returns the absolute path of the given @a path based on
+	/// the root path of the file source. If @a path is absolute,
+	/// the given path is returned.
+	void get_absolute_path(const char* path, DynamicString& os_path);
+
+private:
+
+	char m_root_path[MAX_PATH_LENGTH];
+};
+
+} // namespace crown

+ 0 - 205
engine/core/filesystem/Filesystem.cpp

@@ -1,205 +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 "Filesystem.h"
-#include "Log.h"
-#include "OS.h"
-#include "DiskFile.h"
-#include "Memory.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Filesystem::Filesystem(const char* root_path)
-{
-	CE_ASSERT(root_path != NULL, "Root path must be != NULL");
-	CE_ASSERT(os::is_absolute_path(root_path), "Root path must be absolute");
-
-	string::strncpy(m_root_path, root_path, MAX_PATH_LENGTH);
-}
-
-//-----------------------------------------------------------------------------
-Filesystem::~Filesystem()
-{
-}
-
-//-----------------------------------------------------------------------------
-const char* Filesystem::root_path() const
-{
-	return m_root_path;
-}
-
-//-----------------------------------------------------------------------------
-const char* Filesystem::build_os_path(const char* base_path, const char* relative_path)
-{
-	static char os_path[MAX_PATH_LENGTH];
-
-	string::strncpy(os_path, base_path, MAX_PATH_LENGTH);
-
-	size_t base_path_len = string::strlen(base_path);
-
-	os_path[base_path_len] = PATH_SEPARATOR;
-	os_path[base_path_len + 1] = '\0';
-
-	string::strcat(os_path, relative_path);
-
-	// FIXME FIXME FIXME Replace Crown-specific path separator with OS-speficic one
-	for (size_t j = 0; j < string::strlen(os_path); j++)
-	{
-		if (os_path[j] == '/')
-		{
-			os_path[j] = PATH_SEPARATOR;
-		}
-	}
-
-	return os_path;
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::get_info(const char* relative_path, FilesystemEntry& info)
-{
-	// Entering OS-DEPENDENT-PATH-MODE
-	// (i.e. os_path is of the form: C:\foo\relative_path or /foo/relative_path)
-
-	const char* os_path = build_os_path(m_root_path, relative_path);
-	
-	string::strncpy(info.os_path, os_path, MAX_PATH_LENGTH);
-	string::strncpy(info.relative_path, relative_path, MAX_PATH_LENGTH);
-
-	if (os::is_reg(os_path))
-	{
-		info.type = FilesystemEntry::FILE;
-		return true;
-	}
-	else if (os::is_dir(os_path))
-	{
-		info.type = FilesystemEntry::DIRECTORY;
-		return true;
-	}
-	
-	info.type = FilesystemEntry::UNKNOWN;
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::exists(const char* relative_path)
-{
-	FilesystemEntry dummy;
-
-	return get_info(relative_path, dummy);
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::is_file(const char* relative_path)
-{
-	FilesystemEntry info;
-
-	if (get_info(relative_path, info))
-	{
-		return info.type == FilesystemEntry::FILE;
-	}
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::is_dir(const char* relative_path)
-{
-	FilesystemEntry info;
-
-	if (get_info(relative_path, info))
-	{
-		return info.type == FilesystemEntry::DIRECTORY;
-	}
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::create_file(const char* relative_path)
-{
-	const char* os_path = build_os_path(m_root_path, relative_path);
-
-	return os::mknod(os_path);
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::create_dir(const char* relative_path)
-{
-	const char* os_path = build_os_path(m_root_path, relative_path);
-
-	return os::mkdir(os_path);
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::delete_file(const char* relative_path)
-{
-	const char* os_path = build_os_path(m_root_path, relative_path);
-
-	return os::unlink(os_path);
-}
-
-//-----------------------------------------------------------------------------
-bool Filesystem::delete_dir(const char* relative_path)
-{
-	const char* os_path = build_os_path(m_root_path, relative_path);
-
-	return os::rmdir(os_path);
-}
-
-//-----------------------------------------------------------------------------
-const char* Filesystem::os_path(const char* relative_path)
-{
-	static char os_path[MAX_PATH_LENGTH];
-
-	FilesystemEntry entry;
-
-	get_info(relative_path, entry);
-
-	string::strncpy(os_path, entry.os_path, MAX_PATH_LENGTH);
-
-	return os_path;
-}
-
-//-----------------------------------------------------------------------------
-DiskFile* Filesystem::open(const char* relative_path, FileOpenMode mode)
-{
-	CE_ASSERT(exists(relative_path), "File does not exist: %s", relative_path);
-	CE_ASSERT(is_file(relative_path), "File is not a regular file: %s", relative_path);
-
-	return CE_NEW(m_allocator, DiskFile)(mode, os_path(relative_path));
-}
-
-//-----------------------------------------------------------------------------
-void Filesystem::close(DiskFile* stream)
-{
-	CE_DELETE(m_allocator, stream);
-}
-
-} // namespace crown
-

+ 26 - 67
engine/core/filesystem/Filesystem.h

@@ -26,33 +26,13 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "StringUtils.h"
-#include "OS.h"
 #include "File.h"
-#include "HeapAllocator.h"
+#include "Vector.h"
+#include "DynamicString.h"
 
 namespace crown
 {
 
-struct FilesystemEntry
-{
-	enum Type
-	{
-		DIRECTORY = 0,		///< The entry is a directory
-		FILE,				///< The entry is a file
-		MEMORY,				///< The entry is a memory file (i.e. does not exist on the disk)
-		UNKNOWN				///< The entry type is unknown
-	};
-
-	FilesystemEntry() : type(UNKNOWN) {}
-
-	Type			type;								///< Type of the entry
-	char			os_path[MAX_PATH_LENGTH];			///< OS-specific path (use only for debug)
-	char			relative_path[MAX_PATH_LENGTH];		///< Relative path of the entry
-};
-
-class DiskFile;
-
 /// Provides a platform-independent way to access files and directories
 /// on the host filesystem.
 ///
@@ -102,67 +82,46 @@ class Filesystem
 {
 public:
 
-	/// The @a root_path must be absolute.
-						Filesystem(const char* root_path);
-						~Filesystem();
-
-	/// Returns the root path of the filesystem
-	const char*			root_path() const;
+						Filesystem() {};
+	virtual				~Filesystem() {};
 
-	/// Returns whether the @a relative_path exists and fills @a info with
-	/// with informations about the given @a relative_path path
-	bool				get_info(const char* relative_path, FilesystemEntry& info);
-	
-	/// Returns whether the @a relative_path exists on disk
-	bool				exists(const char* relative_path);
+	/// Opens the file at the given @a path with the given @a mode.
+	virtual File*		open(const char* path, FileOpenMode mode) = 0;
 
-	/// Returns whether @a relative_path is a regular file
-	bool				is_file(const char* relative_path);
+	/// Closes the given @a file.
+	virtual void		close(File* file) = 0;
 
-	/// Returns whether @a relative_path is a directory
-	bool				is_dir(const char* relative_path);
+	/// Returns true if @a path is a directory.
+	virtual bool		is_directory(const char* path) = 0;
 
-	/// Creates a regular file named @a relative_path
-	bool				create_file(const char* relative_path);
+	/// Returns true if @a path is a regular file.
+	virtual bool		is_file(const char* path) = 0;
 
-	/// Creates a directory named @a relative_path
-	bool				create_dir(const char* relative_path);
+	/// Creates the directory at the given @a path.
+	virtual void		create_directory(const char* path) = 0;
 
-	/// Deletes the regular file @a relative_path
-	bool				delete_file(const char* relative_path);
+	/// Deletes the directory at the given @a path.
+	virtual void		delete_directory(const char* path) = 0;
 
-	/// Deletes the directory @a relative_path
-	bool				delete_dir(const char* relative_path);
+	/// Creates the file at the given @a path.
+	virtual void		create_file(const char* path) = 0;
 
-	/// Returns the os-specific path which @a relative_path refers to.
-	/// @note
-	/// In general, you typically do not want to use it for normal
-	/// file interactions. Prefer using the other methods whenever possible.
-	const char*			os_path(const char* relative_path);
+	/// Deletes the file at the given @a path.
+	virtual void		delete_file(const char* path) = 0;
 
-	/// Opens the file @a relative_path with the specified access @a mode
-	DiskFile*			open(const char* relative_path, FileOpenMode mode);
+	/// Returns the relative file names in the given @a path.
+	virtual void		list_files(const char* path, Vector<DynamicString>& files) = 0;
 
-	/// Closes a previously opened file @a stream
-	void				close(DiskFile* stream);
+	/// Returns the absolute path of the given @a path based on
+	/// the root path of the file source. If @a path is absolute,
+	/// the given path is returned.
+	virtual void		get_absolute_path(const char* path, DynamicString& os_path) = 0;
 
 private:
 
-	// Builds the OS-dependent path from base_path and relative_path
-	const char*			build_os_path(const char* base_path, const char* relative_path);
-	
-private:
-
-	HeapAllocator		m_allocator;
-
-	char				m_root_path[MAX_PATH_LENGTH];
-
 	// Disable copying
 						Filesystem(const Filesystem&);
 	Filesystem&			operator=(const Filesystem&);
-
-	friend class		Device;
 };
 
 } // namespace crown
-

+ 0 - 64
engine/core/filesystem/TextReader.cpp

@@ -1,64 +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 "TextReader.h"
-#include "File.h"
-#include "Types.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-TextReader::TextReader(File& file) : m_file(file)
-{
-}
-
-//-----------------------------------------------------------------------------
-size_t TextReader::read_string(char* string, size_t size)
-{
-	char current_char;
-	size_t bytes_read = 0;
-
-	while(!m_file.end_of_file() && bytes_read < size - 1)
-	{
-		m_file.read(&current_char, 1);
-		string[bytes_read] = current_char;
-
-		bytes_read++;
-
-		if (current_char == '\n')
-		{
-			break;
-		}
-	}
-
-	string[bytes_read] = '\0';
-
-	return bytes_read;
-}
-
-} // namespace crown
-

+ 27 - 3
engine/core/filesystem/TextReader.h

@@ -36,7 +36,10 @@ class TextReader
 {
 public:
 
-						TextReader(File& file);
+	//-----------------------------------------------------------------------------
+	TextReader(File& file) : m_file(file)
+	{
+	}
 
 	/// Reads characters from file and stores them as a C string
 	/// into string until (size-1) characters have been read or
@@ -46,11 +49,32 @@ public:
 	/// a valid character and therefore it is included in the string copied to string.
 	/// A null character is automatically appended in str after the characters read to
 	/// signal the end of the C string.
-	size_t				read_string(char* string, size_t size);
+	size_t read_string(char* string, size_t size)
+	{
+		char current_char;
+		size_t bytes_read = 0;
+
+		while(!m_file.end_of_file() && bytes_read < size - 1)
+		{
+			m_file.read(&current_char, 1);
+			string[bytes_read] = current_char;
+
+			bytes_read++;
+
+			if (current_char == '\n')
+			{
+				break;
+			}
+		}
+
+		string[bytes_read] = '\0';
+
+		return bytes_read;
+	}
 
 private:
 
-	File&				m_file;
+	File& m_file;
 };
 
 } // namespace crown

+ 10 - 4
engine/core/filesystem/TextWriter.h

@@ -34,17 +34,23 @@ class TextWriter
 {
 public:
 
-						TextWriter(File& file);
-	
+	//-----------------------------------------------------------------------------
+	TextWriter(File& file) : m_file(file)
+	{
+	}
+
 	/// Writes the string pointed by string to the file.
 	/// The function begins copying from the address specified (string)
 	/// until it reaches the terminating null character ('\0').
 	/// The final null character is not copied to the file.
-	void				write_string(const char* string);
+	void write_string(const char* string)
+	{
+		m_file.write(string, string::strlen(string));
+	}
 
 private:
 
-	File&				m_file;
+	File& m_file;
 };
 
 } // namespace crown

+ 260 - 28
engine/core/json/JSONParser.cpp

@@ -192,26 +192,42 @@ static bool is_escapee(char c)
 }
 
 //--------------------------------------------------------------------------
-JSONElement::JSONElement() :
-	m_parser(NULL),
-	m_at(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)
+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");
 
@@ -226,13 +242,35 @@ JSONElement& JSONElement::index(uint32_t i)
 	return this->operator[](i);
 }
 
+//--------------------------------------------------------------------------
+JSONElement JSONElement::index_or_nil(uint32_t i)
+{
+	if (m_at != NULL)
+	{
+		TempAllocator1024 alloc;
+		List<const char*> array(alloc);
+
+		JSONParser::parse_array(m_begin, array);
+
+		if (i >= array.size())
+		{
+			return JSONElement();
+		}
+
+		m_at = array[i];
+		return *this;
+	}
+
+	return JSONElement();
+}
+
 //--------------------------------------------------------------------------
 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;
 
@@ -255,16 +293,58 @@ JSONElement& JSONElement::key(const char* k)
 	return *this;
 }
 
+//--------------------------------------------------------------------------
+JSONElement JSONElement::key_or_nil(const char* k)
+{
+	if (m_at != NULL)
+	{
+		TempAllocator1024 alloc;
+		List<JSONPair> object(alloc);
+
+		JSONParser::parse_object(m_begin, object);
+
+		bool found = false;
+
+		for (uint32_t i = 0; i < object.size(); i++)
+		{
+			TempAllocator256 key_alloc;
+			List<char> key(key_alloc);
+
+			JSONParser::parse_string(object[i].key, key);
+
+			if (string::strcmp(k, key.begin()) == 0)
+			{
+				m_at = object[i].val;
+				found = true;
+			}
+		}
+
+		if (!found)
+		{
+			return JSONElement();
+		}
+
+		return *this;
+	}
+
+	return JSONElement();
+}
+
 //--------------------------------------------------------------------------
 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++)
 	{
-		if (string::strcmp(k, object[i].key) == 0)
+		TempAllocator256 key_alloc;
+		List<char> key(key_alloc);
+
+		JSONParser::parse_string(object[i].key, key);
+
+		if (string::strcmp(k, key.begin()) == 0)
 		{
 			return true;
 		}
@@ -278,13 +358,18 @@ 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;
 
 	for (uint32_t i = 0; i < object.size(); i++)
 	{
-		if (string::strcmp(k, object[i].key) == 0)
+		TempAllocator256 key_alloc;
+		List<char> key(key_alloc);
+
+		JSONParser::parse_string(object[i].key, key);
+
+		if (string::strcmp(k, key.begin()) == 0)
 		{
 			if (found == true)
 			{
@@ -299,25 +384,37 @@ bool JSONElement::is_key_unique(const char* k) const
 }
 
 //--------------------------------------------------------------------------
-bool JSONElement::bool_value() const
+bool JSONElement::bool_value()
 {
-	return JSONParser::parse_bool(m_at);
+	const bool value = JSONParser::parse_bool(m_at);
+
+	m_at = m_begin;
+
+	return value;
 }
 
 //--------------------------------------------------------------------------
-int32_t JSONElement::int_value() const
+int32_t JSONElement::int_value()
 {
-	return JSONParser::parse_int(m_at);
+	const int32_t value = JSONParser::parse_int(m_at);
+
+	m_at = m_begin;
+
+	return value;
 }
 
 //--------------------------------------------------------------------------
-float JSONElement::float_value() const
+float JSONElement::float_value()
 {
-	return JSONParser::parse_float(m_at);
+	const float value = JSONParser::parse_float(m_at);
+
+	m_at = m_begin;
+
+	return value;
 }
 
 //--------------------------------------------------------------------------
-const char* JSONElement::string_value() const
+const char* JSONElement::string_value()
 {
 	static TempAllocator1024 alloc;
 	static List<char> string(alloc);
@@ -326,48 +423,181 @@ const char* JSONElement::string_value() const
 
 	JSONParser::parse_string(m_at, string);
 
+	m_at = m_begin;
+
 	return string.begin();
 }
 
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<bool>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back(JSONParser::parse_bool(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<int16_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((int16_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<uint16_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((uint16_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<int32_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((int32_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<uint32_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((uint32_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<float>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back(JSONParser::parse_float(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
 //--------------------------------------------------------------------------
 bool JSONElement::is_nil() const
 {
-	return JSONParser::type(m_at) == JT_NIL;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_NIL;
+	}
+
+	return true;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_bool() const
 {
-	return JSONParser::type(m_at) == JT_BOOL;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_BOOL;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_number() const
 {
-	return JSONParser::type(m_at) == JT_NUMBER;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_NUMBER;		
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_string() const
 {
-	return JSONParser::type(m_at) == JT_STRING;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_STRING;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_array() const
 {
-	return JSONParser::type(m_at) == JT_ARRAY;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_ARRAY;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_object() const
 {
-	return JSONParser::type(m_at) == JT_OBJECT;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_OBJECT;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 uint32_t JSONElement::size() const
 {
+	if (m_at == NULL)
+	{
+		return 0;
+	}
+
 	switch(JSONParser::type(m_at))
 	{
 		case JT_NIL:
@@ -567,10 +797,12 @@ bool JSONParser::parse_bool(const char* s)
 			ch = next(ch, 'e');
 			return false;
 		}
-		default: break;
+		default:
+		{
+			CE_ASSERT(false, "Bad boolean");
+			return false;
+		}
 	}
-
-	CE_ASSERT(false, "Bad boolean");
 }
 
 //-----------------------------------------------------------------------------

+ 44 - 10
engine/core/json/JSONParser.h

@@ -58,18 +58,24 @@ class JSONElement
 {
 public:
 
-	/// Used only to forward-instantiate elements.
-	/// In order to be able to use the element, it must be
-	/// obtained from JSONParser::root() or copied from an
-	/// already existent and valid element.
+	/// Construct the nil JSONElement.
+	/// Used to forward-instantiate elements or as a special
+	/// nil 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);
 
-	/// @copydoc JSONParser::operator[]
+	/// @copydoc JSONElement::operator[]
 	JSONElement&		index(uint32_t i);
 
+	/// Returns the @a i -th item of the current array or
+	/// the special nil JSONElement() if the index does not exist.
+	JSONElement			index_or_nil(uint32_t i);
+
 	/// Returns the element corresponding to key @a k of the
 	/// current object.
 	/// @note
@@ -77,6 +83,10 @@ public:
 	/// key in order of appearance will be selected.
 	JSONElement&		key(const char* k);
 
+	/// Returns the element corresponding to key @a k of the current
+	/// object, or the special nil JSONElement() if the key does not exist.
+	JSONElement			key_or_nil(const char* k);
+
 	/// Returns whether the element has the @a k key.
 	bool				has_key(const char* k) const;
 
@@ -111,26 +121,50 @@ public:
 	uint32_t			size() const;
 
 	/// Returns the boolean value of the element.
-	bool				bool_value() const;
+	bool				bool_value();
 
 	/// Returns the integer value of the element.
-	int32_t				int_value() const;
+	int32_t				int_value();
 
 	/// Returns the float value of the element.
-	float				float_value() const;
+	float				float_value();
 
 	/// Returns the string value of the element.
 	/// @warning
 	/// The returned string is kept internally until the next call to
 	/// this function, so it is highly unsafe to just keep the pointer
 	/// instead of copying its content somewhere else.
-	const char*			string_value() const;
+	const char*			string_value();
+
+	/// Returns the array value of the element.
+	/// @note
+	/// Calling this function is way faster than accessing individual
+	/// array elements by JSONElement::operator[] and it is the very preferred way
+	/// for retrieving array elemets. However, you have to be sure that the array
+	/// contains only items of the given @array type.
+	void				array_value(List<bool>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<int16_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<uint16_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<int32_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<uint32_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<float>& array);
 
 private:
 
-						JSONElement(JSONParser& parser, const char* at);
+	explicit			JSONElement(JSONParser& parser, const char* at);
 
 	JSONParser*			m_parser;
+	const char*			m_begin;
 	const char*			m_at;
 
 	friend class 		JSONParser;

+ 0 - 38
engine/core/mem/Allocator.cpp

@@ -1,38 +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 "HeapAllocator.h"
-
-namespace crown
-{
-
-HeapAllocator g_default_allocator;
-Allocator& default_allocator()
-{
-	return g_default_allocator;
-}
-
-} // namespace crown

+ 1 - 1
engine/core/mem/Allocator.h

@@ -59,7 +59,7 @@ private:
 	Allocator&			operator=(const Allocator&);
 };
 
-Allocator& default_allocator();
+CE_EXPORT Allocator& default_allocator();
 
 /// Respects standard behaviour when calling on NULL @a ptr
 template <typename T>

+ 15 - 5
engine/core/mem/LinearAllocator.cpp

@@ -30,17 +30,27 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-LinearAllocator::LinearAllocator(void* start, size_t size) :
-	m_physical_start(start),
-	m_total_size(size),
-	m_offset(0)
+LinearAllocator::LinearAllocator(Allocator& backing, size_t size)
+	: m_backing(&backing), m_physical_start(NULL), m_total_size(size), m_offset(0)
+{
+	m_physical_start = backing.allocate(size);
+}
+
+//-----------------------------------------------------------------------------
+LinearAllocator::LinearAllocator(void* start, size_t size)
+	: m_backing(NULL), m_physical_start(start), m_total_size(size), m_offset(0)
 {
 }
 
 //-----------------------------------------------------------------------------
 LinearAllocator::~LinearAllocator()
 {
-	CE_ASSERT(m_offset == 0, "Memory leak of %d bytes", m_offset);
+	if (m_backing)
+	{
+		m_backing->deallocate(m_physical_start);
+	}
+
+	CE_ASSERT(m_offset == 0, "Memory leak of %d bytes, maybe you forgot to call clear()?", m_offset);
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 0
engine/core/mem/LinearAllocator.h

@@ -37,6 +37,7 @@ class LinearAllocator : public Allocator
 {
 public:
 
+				LinearAllocator(Allocator& backing, size_t size);
 				LinearAllocator(void* start, size_t size);
 				~LinearAllocator();
 
@@ -58,6 +59,7 @@ public:
 
 private:
 
+	Allocator*	m_backing;
 	void*		m_physical_start;
 	size_t		m_total_size;
 	size_t		m_offset;

+ 43 - 16
engine/core/mem/Memory.cpp

@@ -27,30 +27,57 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Memory.h"
 #include "HeapAllocator.h"
 
-//-----------------------------------------------------------------------------
-void* operator new(size_t) throw (std::bad_alloc)
-{
-	CE_ASSERT(false, "operator new forbidden");
+// //-----------------------------------------------------------------------------
+// void* operator new(size_t) throw (std::bad_alloc)
+// {
+// 	CE_ASSERT(false, "operator new forbidden");
 
-	return NULL;
-}
+// 	return NULL;
+// }
+
+// //-----------------------------------------------------------------------------
+// void* operator new[](size_t) throw (std::bad_alloc)
+// {
+// 	CE_ASSERT(false, "operator new[] forbidden");
+
+// 	return NULL;
+// }
+
+// //-----------------------------------------------------------------------------
+// void operator delete(void*) throw ()
+// {
+// 	CE_ASSERT(false, "operator delete forbidden");
+// }
+
+// //-----------------------------------------------------------------------------
+// void operator delete[](void*) throw ()
+// {
+// 	CE_ASSERT(false, "operator delete[] forbidden");
+// }
 
-//-----------------------------------------------------------------------------
-void* operator new[](size_t) throw (std::bad_alloc)
+namespace crown
 {
-	CE_ASSERT(false, "operator new[] forbidden");
+namespace memory
+{
+
+static char buffer[1024];
+static HeapAllocator* g_default_allocator = NULL;
 
-	return NULL;
+void init()
+{
+	g_default_allocator = new (buffer) HeapAllocator();
 }
 
-//-----------------------------------------------------------------------------
-void operator delete(void*) throw ()
+void shutdown()
 {
-	CE_ASSERT(false, "operator delete forbidden");
+	g_default_allocator->~HeapAllocator();
 }
 
-//-----------------------------------------------------------------------------
-void operator delete[](void*) throw ()
+} // namespace memory
+
+Allocator& default_allocator()
 {
-	CE_ASSERT(false, "operator delete[] forbidden");
+	return *memory::g_default_allocator;
 }
+
+} // namespace crown

+ 27 - 18
engine/core/mem/Memory.h

@@ -28,7 +28,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "Assert.h"
-#include "OS.h"
 
 namespace crown
 {
@@ -38,11 +37,21 @@ namespace memory
 const uint32_t	PADDING_VALUE	= 0xFFFFFFFFu;	//!< Value used to fill unused memory
 const size_t	DEFAULT_ALIGN	= 4;			//!< Default memory alignment in bytes
 
+/// Constructs the initial default allocators.
+/// @note
+/// Has to be called before anything else during the engine startup.
+CE_EXPORT void init();
+
+/// Destroys the allocators created with memory::init().
+/// @note
+/// Should be the last call of the program.
+CE_EXPORT void shutdown();
+
 /// Returns the pointer @a p aligned to the desired @a align byte
 inline void* align_top(void* p, size_t align)
 {
-	CE_ASSERT(align > 1, "Alignment must be > 1");
-	CE_ASSERT(align % 2 == 0, "Alignment must be a power of two");
+	CE_ASSERT(align >= 1, "Alignment must be > 1");
+	CE_ASSERT(align % 2 == 0 || align == 1, "Alignment must be a power of two");
 
 	uintptr_t ptr = (uintptr_t)p;
 
@@ -56,24 +65,24 @@ inline void* align_top(void* p, size_t align)
 	return (void*) ptr;
 }
 
-/// Dumps the memory content pointed by @a p
-inline void dump(void* p, size_t size, size_t word_size)
-{
-	uint8_t* mem = (uint8_t*) p;
+// /// Dumps the memory content pointed by @a p
+// inline void dump(void* p, size_t size, size_t word_size)
+// {
+// 	uint8_t* mem = (uint8_t*) p;
 
-	for (size_t i = 0; i < size; i++, mem++)
-	{
-		if (i % word_size == 0)
-		{
-			os::printf("\n");
-			os::printf("[.. %.4X] ", (size_t)mem);
-		}
+// 	for (size_t i = 0; i < size; i++, mem++)
+// 	{
+// 		if (i % word_size == 0)
+// 		{
+// 			os::printf("\n");
+// 			os::printf("[.. %.4X] ", (size_t)mem);
+// 		}
 
-		os::printf("%.2X ", *mem);
-	}
+// 		os::printf("%.2X ", *mem);
+// 	}
 
-	os::printf("\n");
-}
+// 	os::printf("\n");
+// }
 
 #ifdef _MSC_VER
 	#define CE_ALIGNOF(x) __alignof(x)

+ 1 - 1
engine/core/mem/ProxyAllocator.h

@@ -36,7 +36,7 @@ namespace crown
 /// Offers the facility to tag allocators by a string identifier.
 /// Proxy allocator is appended to a global linked list when instantiated
 /// so that it is possible to later visit that list for debugging purposes.
-class ProxyAllocator : public Allocator
+class CE_EXPORT ProxyAllocator : public Allocator
 {
 public:
 

+ 229 - 0
engine/core/strings/DynamicString.h

@@ -0,0 +1,229 @@
+/*
+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 <algorithm>
+#include <cstring>
+
+#include "Assert.h"
+#include "Allocator.h"
+#include "StringUtils.h"
+#include "List.h"
+
+namespace crown
+{
+
+///
+class DynamicString
+{
+public:
+
+						DynamicString(Allocator& allocator);
+						DynamicString(Allocator& allocator, const char* s);
+
+						~DynamicString();
+
+	DynamicString&		operator+=(DynamicString& s);
+	DynamicString&		operator+=(const char* s);
+	DynamicString&		operator+=(const char c);
+	///
+	DynamicString&		operator=(DynamicString& s);
+	DynamicString&		operator=(const char* s);
+	DynamicString&		operator=(const char c);
+
+	bool				operator==(DynamicString& s);
+	bool				operator==(const char* s);
+
+	/// Removes the leading string @a s.
+	/// @note
+	/// The string must start with @a s.
+	void				strip_leading(const char* s);
+
+	/// Removes the trailing string @a s.
+	/// @note
+	/// The string must end with @a s.
+	void				strip_trailing(const char* s);
+
+	/// Returns whether the string starts with the given @a s string.
+	bool				starts_with(const char* s);
+
+	/// Returns wheterh the string ends with the given @æ s string.
+	bool				ends_with(const char* s);
+
+	///
+	const char*			c_str();
+
+private:
+
+	List<char>			m_string;
+};
+
+//-----------------------------------------------------------------------------
+inline DynamicString::DynamicString(Allocator& allocator) :
+	m_string(allocator)
+{
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString::DynamicString(Allocator& allocator, const char* s) :
+	m_string(allocator)
+{
+	m_string.push(s, string::strlen(s));
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString::~DynamicString()
+{
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator+=(DynamicString& s)
+{
+	const char* tmp = s.c_str();
+
+	return *this += tmp;
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator+=(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	m_string.push(s, string::strlen(s));
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator+=(const char c)
+{
+	m_string.push_back(c);
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator=(DynamicString& s)
+{
+	const char* tmp = s.c_str();
+
+	return *this = tmp;
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator=(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	m_string.clear();
+	m_string.push(s, string::strlen(s));
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+inline DynamicString& DynamicString::operator=(const char c)
+{
+	m_string.clear();
+	m_string.push_back(c);
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+inline bool DynamicString::operator==(DynamicString& s)
+{
+	return string::strcmp(c_str(), s.c_str()) == 0;
+}
+
+//-----------------------------------------------------------------------------
+inline bool DynamicString::operator==(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	return string::strcmp(c_str(), s) == 0;
+}
+
+//-----------------------------------------------------------------------------
+inline void DynamicString::strip_leading(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+	CE_ASSERT(starts_with(s), "String does not start with %s", s);
+
+	const size_t my_len = string::strlen(c_str());
+	const size_t s_len = string::strlen(s);
+
+	memmove(m_string.begin(), m_string.begin() + s_len, (my_len - s_len));
+	m_string.resize(my_len - s_len);
+}
+
+//-----------------------------------------------------------------------------
+inline void DynamicString::strip_trailing(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+	CE_ASSERT(ends_with(s), "String does not end with %s", s);
+
+	const size_t my_len = string::strlen(c_str());
+	const size_t s_len = string::strlen(s);
+
+	m_string.resize(my_len - s_len);
+}
+
+//-----------------------------------------------------------------------------
+inline bool DynamicString::starts_with(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	return string::strncmp(c_str(), s, string::strlen(s)) == 0;
+}
+
+//-----------------------------------------------------------------------------
+inline bool DynamicString::ends_with(const char* s)
+{
+	CE_ASSERT_NOT_NULL(s);
+
+	const size_t my_len = string::strlen(c_str());
+	const size_t s_len = string::strlen(s);
+
+	if (my_len >= s_len)
+	{
+		return string::strncmp(m_string.begin() + (my_len - s_len), s, s_len) == 0;
+	}
+
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+inline const char* DynamicString::c_str()
+{
+	m_string.push_back('\0');
+	m_string.pop_back();
+
+	return m_string.begin();
+}
+
+} // namespace crown

+ 56 - 1
engine/core/strings/Hash.h

@@ -44,6 +44,7 @@ const uint64_t FNV1A_PRIME_64				= 1099511628211ull;
 
 // Functions
 uint32_t murmur2_32(const void* key, size_t len, uint32_t seed);
+uint64_t murmur2_64(const void* key, size_t len, unsigned int seed);
 uint32_t fnv1a_32(const void* key, size_t len);
 uint64_t fnv1a_64(const void* key, size_t len);
 
@@ -63,7 +64,7 @@ uint64_t fnv1a_64(const void* key, size_t len);
 ///    machines.
 inline uint32_t murmur2_32(const void* key, size_t len, uint32_t seed)
 {
-	CE_ASSERT(key != NULL, "Key must be != NULL");
+	CE_ASSERT_NOT_NULL(key);
 
 	// 'm' and 'r' are mixing constants generated offline.
 	// They're not really 'magic', they just happen to work well.
@@ -109,6 +110,60 @@ inline uint32_t murmur2_32(const void* key, size_t len, uint32_t seed)
 	return h;
 }
 
+//-----------------------------------------------------------------------------
+inline uint64_t murmur2_64(const void* key, size_t len, unsigned int seed)
+{
+	CE_ASSERT_NOT_NULL(key);
+
+	const unsigned int m = 0x5bd1e995;
+	const int r = 24;
+
+	unsigned int h1 = seed ^ len;
+	unsigned int h2 = 0;
+
+	const unsigned int * data = (const unsigned int *)key;
+
+	while(len >= 8)
+	{
+		unsigned int k1 = *data++;
+		k1 *= m; k1 ^= k1 >> r; k1 *= m;
+		h1 *= m; h1 ^= k1;
+		len -= 4;
+
+		unsigned int k2 = *data++;
+		k2 *= m; k2 ^= k2 >> r; k2 *= m;
+		h2 *= m; h2 ^= k2;
+		len -= 4;
+	}
+
+	if(len >= 4)
+	{
+		unsigned int k1 = *data++;
+		k1 *= m; k1 ^= k1 >> r; k1 *= m;
+		h1 *= m; h1 ^= k1;
+		len -= 4;
+	}
+
+	switch(len)
+	{
+	case 3: h2 ^= ((unsigned char*)data)[2] << 16;
+	case 2: h2 ^= ((unsigned char*)data)[1] << 8;
+	case 1: h2 ^= ((unsigned char*)data)[0];
+			h2 *= m;
+	};
+
+	h1 ^= h2 >> 18; h1 *= m;
+	h2 ^= h1 >> 22; h2 *= m;
+	h1 ^= h2 >> 17; h1 *= m;
+	h2 ^= h1 >> 19; h2 *= m;
+
+	uint64_t h = h1;
+
+	h = (h << 32) | h2;
+
+	return h;
+} 
+
 //-----------------------------------------------------------------------------
 /// FNV-1a hash, 32 bit
 inline uint32_t fnv1a_32(const void* key, size_t len)

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

@@ -0,0 +1,154 @@
+/*
+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 <stdio.h>
+#include "List.h"
+#include "StringUtils.h"
+
+namespace crown
+{
+
+class StringStream
+{
+public:
+
+						StringStream(Allocator& allocator);
+
+	void				clear();
+
+	StringStream&		operator<<(int16_t val);
+	StringStream&		operator<<(uint16_t val);
+	StringStream&		operator<<(int32_t val);
+	StringStream&		operator<<(uint32_t val);
+	StringStream&		operator<<(int64_t val);
+	StringStream&		operator<<(uint64_t val);
+	StringStream&		operator<<(float val);
+	StringStream&		operator<<(double val);
+
+	StringStream&		operator<<(const char* s);
+
+	const char*			c_str();
+
+private:
+
+	template <typename T>
+	StringStream&		stream_printf(const char* format, T& val);
+
+private:
+
+	List<char>			m_string;
+};
+
+//-----------------------------------------------------------------------------
+inline StringStream::StringStream(Allocator& allocator)
+	: m_string(allocator)
+{
+}
+
+//-----------------------------------------------------------------------------
+inline void StringStream::clear()
+{
+	m_string.clear();
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(int16_t val)
+{
+	return stream_printf("%hd", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(uint16_t val)
+{
+	return stream_printf("%hu", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(int32_t val)
+{
+	return stream_printf("%d", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(uint32_t val)
+{
+	return stream_printf("%u", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(int64_t val)
+{
+	return stream_printf("%lld", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(uint64_t val)
+{
+	return stream_printf("%llu", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(float val)
+{
+	return stream_printf("%g", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(double val)
+{
+	return stream_printf("%g", val);
+}
+
+//-----------------------------------------------------------------------------
+inline StringStream& StringStream::operator<<(const char* s)
+{
+	m_string.push(s, string::strlen(s));
+
+	return *this;
+}
+
+//-----------------------------------------------------------------------------
+inline const char* StringStream::c_str()
+{
+	m_string.push_back('\0');
+	m_string.pop_back();
+
+	return m_string.begin();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+inline StringStream& StringStream::stream_printf(const char* format, T& val)
+{
+	char buf[32];
+	snprintf(buf, 32, format, val);
+
+	return *this << buf;
+}
+
+} // namespace crown

+ 7 - 12
engine/core/strings/StringUtils.h

@@ -72,18 +72,7 @@ inline bool is_whitespace(char c)
 //-----------------------------------------------------------------------------
 inline size_t strlen(const char* str)
 {
-	size_t chars = 0;
-
-	while(*str)
-	{
-		if ((*str & 0xC0) != 0x80)
-		{
-			chars++;
-		}
-		str++;
-	}
-
-	return chars;
+	return ::strlen(str);
 }
 
 //-----------------------------------------------------------------------------
@@ -98,6 +87,12 @@ inline int32_t strcmp(const char* str1, const char* str2)
 	return ::strcmp(str1, str2);
 }
 
+//-----------------------------------------------------------------------------
+inline int32_t strncmp(const char* s1, const char* s2, size_t len)
+{
+	return ::strncmp(s1, s2, len);
+}
+
 //-----------------------------------------------------------------------------
 inline char* strncpy(char* dest, const char* src, size_t len)
 {

+ 0 - 44
engine/input/Accelerometer.cpp

@@ -1,44 +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 "Accelerometer.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Accelerometer::Accelerometer() :
-	m_orientation(0.0f, 0.0f, 0.0f)
-{
-}
-
-//-----------------------------------------------------------------------------
-const Vec3& Accelerometer::orientation() const
-{
-	return m_orientation;
-}
-
-} // namespace crown

+ 11 - 24
engine/input/Accelerometer.h

@@ -32,38 +32,25 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-class InputManager;
-
-struct AccelerometerEvent
-{
-	float x;
-	float y;
-	float z;
-};
-
-class AccelerometerListener
-{
-public:
-
-	virtual void accelerometer_changed(const AccelerometerEvent& event) { (void)event; }
-};
-
 /// Interface for accessing accelerometer input device.
-class Accelerometer
+struct Accelerometer
 {
-public:
-	
-					Accelerometer();
+	//-----------------------------------------------------------------------------
+	Accelerometer()
+		: m_orientation(0.0f, 0.0f, 0.0f)
+	{
+	}
 
 	/// Returns the orientation of the accelerometer.
 	/// FIXME NEED MORE DOCUMENTATION
-	const Vec3&		orientation() const;
+	const Vec3& orientation() const
+	{
+		return m_orientation;
+	}
 
-private:
+public:
 
 	Vec3			m_orientation;
-
-	friend class	InputManager;
 };
 
 } // namespace crown

+ 0 - 178
engine/input/EventDispatcher.cpp

@@ -1,178 +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 "EventDispatcher.h"
-#include "Allocator.h"
-#include "Log.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-EventDispatcher::EventDispatcher() :
-	m_mouse_listener_list(default_allocator()),
-	m_keyboard_listener_list(default_allocator()),
-	m_touch_listener_list(default_allocator()),
-	m_acc_listener_list(default_allocator())
-{
-}
-
-//-----------------------------------------------------------------------------
-EventDispatcher::~EventDispatcher()
-{
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::add_mouse_listener(MouseListener* listener)
-{
-	CE_ASSERT(listener != NULL, "Listener must be != NULL");
-
-	m_mouse_listener_list.push_back(listener);
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::add_keyboard_listener(KeyboardListener* listener)
-{
-	CE_ASSERT(listener != NULL, "Listener must be != NULL");
-
-	m_keyboard_listener_list.push_back(listener);
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::add_touch_listener(TouchListener* listener)
-{
-	CE_ASSERT(listener != NULL, "Listener must be != NULL");
-
-	m_touch_listener_list.push_back(listener);
-}
-
-void EventDispatcher::add_accelerometer_listener(AccelerometerListener* listener)
-{
-	CE_ASSERT(listener != NULL, "Listener must be != NULL");
-	m_acc_listener_list.push_back(listener);
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::button_pressed(const MouseEvent& event)
-{
-	for (uint32_t i = 0; i < m_mouse_listener_list.size(); i++)
-	{
-		m_mouse_listener_list[i]->button_pressed(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::button_released(const MouseEvent& event)
-{
-	for (uint32_t i = 0; i < m_mouse_listener_list.size(); i++)
-	{
-		m_mouse_listener_list[i]->button_released(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::cursor_moved(const MouseEvent& event)
-{
-	for (uint32_t i = 0; i < m_mouse_listener_list.size(); i++)
-	{
-		m_mouse_listener_list[i]->cursor_moved(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::key_pressed(const KeyboardEvent& event)
-{
-	for (uint32_t i = 0; i < m_keyboard_listener_list.size(); i++)
-	{
-		m_keyboard_listener_list[i]->key_pressed(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::key_released(const KeyboardEvent& event)
-{
-	for (uint32_t i = 0; i < m_keyboard_listener_list.size(); i++)
-	{
-		m_keyboard_listener_list[i]->key_released(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::text_input(const KeyboardEvent& event)
-{
-	for (uint32_t i = 0; i < m_keyboard_listener_list.size(); i++)
-	{
-		m_keyboard_listener_list[i]->text_input(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::touch_down(const TouchEvent& event)
-{
-	for (uint32_t i = 0; i < m_touch_listener_list.size(); i++)
-	{
-		m_touch_listener_list[i]->touch_down(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::touch_up(const TouchEvent& event)
-{
-	for (uint32_t i = 0; i < m_touch_listener_list.size(); i++)
-	{
-		m_touch_listener_list[i]->touch_up(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::touch_move(const TouchEvent& event)
-{
-	for (uint32_t i = 0; i < m_touch_listener_list.size(); i++)
-	{
-		m_touch_listener_list[i]->touch_move(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::touch_cancel(const TouchEvent& event)
-{
-	for (uint32_t i = 0; i < m_touch_listener_list.size(); i++)
-	{
-		m_touch_listener_list[i]->touch_cancel(event);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void EventDispatcher::accelerometer_changed(const AccelerometerEvent& event)
-{
-	for (uint32_t i = 0; i < m_acc_listener_list.size(); i++)
-	{
-		m_acc_listener_list[i]->accelerometer_changed(event);
-	}
-}
-
-} // namespace crown
-

+ 0 - 79
engine/input/EventDispatcher.h

@@ -1,79 +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.
-*/
-
-#pragma once
-
-#include "List.h"
-#include "Mouse.h"
-#include "Keyboard.h"
-#include "Touch.h"
-#include "Accelerometer.h"
-
-namespace crown
-{
-
-class EventDispatcher
-{
-	typedef List<MouseListener*>			MouseListenerList;
-	typedef List<KeyboardListener*>			KeyboardListenerList;
-	typedef List<TouchListener*>			TouchListenerList;
-	typedef List<AccelerometerListener*>	AccelerometerListenerList;
-
-public:
-
-	EventDispatcher();
-	~EventDispatcher();
-
-	void add_mouse_listener(MouseListener* listener);
-	void add_keyboard_listener(KeyboardListener* listener);
-	void add_touch_listener(TouchListener* listener);
-	void add_accelerometer_listener(AccelerometerListener* listener);
-
-	void button_pressed(const MouseEvent&);
-	void button_released(const MouseEvent&);
-	void cursor_moved(const MouseEvent&);
-
-	void key_pressed(const KeyboardEvent&);
-	void key_released(const KeyboardEvent&);
-	void text_input(const KeyboardEvent&);
-
-	void touch_down(const TouchEvent& event);
-	void touch_up(const TouchEvent& event);
-	void touch_move(const TouchEvent& event);
-	void touch_cancel(const TouchEvent& event);
-
-	void accelerometer_changed(const AccelerometerEvent& event);
-
-private:
-
-	MouseListenerList			m_mouse_listener_list;
-	KeyboardListenerList		m_keyboard_listener_list;
-	TouchListenerList			m_touch_listener_list;
-	AccelerometerListenerList	m_acc_listener_list;
-};
-
-} // namespace crown
-

+ 0 - 230
engine/input/InputManager.cpp

@@ -1,230 +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 "InputManager.h"
-#include "OS.h"
-#include "Log.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-InputManager::InputManager()
-{
-}
-
-//-----------------------------------------------------------------------------
-InputManager::~InputManager()
-{
-}
-
-//-----------------------------------------------------------------------------
-Keyboard* InputManager::keyboard()
-{
-	return &m_keyboard;
-}
-
-//-----------------------------------------------------------------------------
-Mouse* InputManager::mouse()
-{
-	return &m_mouse;
-}
-
-//-----------------------------------------------------------------------------
-Touch* InputManager::touch()
-{
-	return &m_touch;
-}
-
-//-----------------------------------------------------------------------------
-Accelerometer* InputManager::accelerometer()
-{
-	return &m_accelerometer;
-}
-
-//-----------------------------------------------------------------------------
-void InputManager::register_mouse_listener(MouseListener* listener)
-{
-	m_event_dispatcher.add_mouse_listener(listener);
-}
-
-//-----------------------------------------------------------------------------
-void InputManager::register_keyboard_listener(KeyboardListener* listener)
-{
-	m_event_dispatcher.add_keyboard_listener(listener);
-}
-
-//-----------------------------------------------------------------------------
-void InputManager::register_touch_listener(TouchListener* listener)
-{
-	m_event_dispatcher.add_touch_listener(listener);
-}
-
-//-----------------------------------------------------------------------------
-void InputManager::register_accelerometer_listener(AccelerometerListener* listener)
-{
-	m_event_dispatcher.add_accelerometer_listener(listener);
-}
-
-//-----------------------------------------------------------------------------
-EventDispatcher* InputManager::get_event_dispatcher()
-{
-	return &m_event_dispatcher;
-}
-
-//-----------------------------------------------------------------------------
-void InputManager::frame(uint64_t frame_count)
-{
-	OsEvent event;
-
-	// Update input devices
-	m_keyboard.m_current_frame = frame_count;
-	m_mouse.m_current_frame = frame_count;
-
-	while (1)
-	{
-		event = pop_event();
-
-		switch (event.type)
-		{
-			case OSET_NONE:
-			{
-				return;
-			}
-			case OSET_BUTTON_PRESS:
-			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.wheel = 0.0f;
-
-				if (event.type == OSET_BUTTON_PRESS)
-				{
-					m_mouse.update(frame_count, mouse_event.button, true);
-					m_event_dispatcher.button_pressed(mouse_event);
-				}
-				else
-				{
-					m_mouse.update(frame_count, mouse_event.button, false);
-					m_event_dispatcher.button_released(mouse_event);
-				}
-
-				break;
-			}
-			case OSET_KEY_PRESS:
-			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;
-
-				m_keyboard.m_modifier = keyboard_event.modifier;
-
-				if (event.type == OSET_KEY_PRESS)
-				{
-					m_keyboard.update(frame_count, keyboard_event.key, true);
-					m_event_dispatcher.key_pressed(keyboard_event);
-				}
-				else
-				{
-					m_keyboard.update(frame_count, keyboard_event.key, false);
-					m_event_dispatcher.key_released(keyboard_event);
-				}
-
-				break;
-			}
-			case OSET_TOUCH_DOWN:
-			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;
-
-				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
-				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
-
-				// FIXME
-				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)
-				{
-					m_touch.m_pointers[touch_event.pointer_id].up = false;
-					m_event_dispatcher.touch_down(touch_event);
-				}
-				else
-				{
-					m_touch.m_pointers[touch_event.pointer_id].up = true;
-					m_event_dispatcher.touch_up(touch_event);
-				}
-
-				break;
-			}
-			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;
-
-				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
-				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
-
-				// FIXME
-				m_touch.m_pointers[touch_event.pointer_id].relative_x = 0.0f;
-				m_touch.m_pointers[touch_event.pointer_id].relative_y = 0.0f;
-
-				m_event_dispatcher.touch_move(touch_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;
-			}
-		}
-	}
-}
-
-} // namespace crown
-

+ 0 - 74
engine/input/InputManager.h

@@ -1,74 +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.
-*/
-
-#pragma once
-
-#include "EventDispatcher.h"
-#include "Mouse.h"
-#include "Keyboard.h"
-#include "Touch.h"
-#include "Accelerometer.h"
-
-namespace crown
-{
-
-class MouseListener;
-class KeyboardListener;
-class TouchListener;
-
-class InputManager
-{
-public:
-
-						InputManager();
-						~InputManager();
-
-	Keyboard*			keyboard();
-	Mouse*				mouse();
-	Touch*				touch();
-	Accelerometer*		accelerometer();
-
-	void				register_mouse_listener(MouseListener* listener);
-	void				register_keyboard_listener(KeyboardListener* listener);
-	void				register_touch_listener(TouchListener* listener);
-	void				register_accelerometer_listener(AccelerometerListener* listener);
-
-	EventDispatcher*	get_event_dispatcher();
-
-	void				frame(uint64_t frame_count);
-
-private:
-
-	EventDispatcher		m_event_dispatcher;
-
-	Keyboard			m_keyboard;
-	Mouse				m_mouse;
-	Touch				m_touch;
-	Accelerometer		m_accelerometer;
-};
-
-} // namespace crown
-

+ 129 - 131
engine/input/KeyCode.h

@@ -29,138 +29,136 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-const uint16_t MAX_KEYCODES = 256;
-
-typedef uint8_t Key;
-
-/// A KeyCode is the number which uniquely identifies a key
-/// on the keyboard.
-enum KeyCode
+/// Uniquely identifies a button on the keyboard.
+struct KeyboardButton
 {
-	KC_NOKEY		= 0x00,
-
-	KC_TAB			= 0x09,		// ASCII value
-	KC_ENTER		= 0x0D,		// ASCII value
-	KC_ESCAPE		= 0x1B,		// ASCII value
-	KC_SPACE		= 0x20,		// ASCII value
-	KC_BACKSPACE	= 0x7F,		// ASCII value
-
-	/* KeyPad */
-	KC_KP_0			= 0x80,
-	KC_KP_1			= 0x81,
-	KC_KP_2			= 0x82,
-	KC_KP_3			= 0x83,
-	KC_KP_4			= 0x84,
-	KC_KP_5			= 0x85,
-	KC_KP_6			= 0x86,
-	KC_KP_7			= 0x87,
-	KC_KP_8			= 0x88,
-	KC_KP_9			= 0x89,
-
-	/* Function keys */
-	KC_F1			= 0x90,
-	KC_F2			= 0x91,
-	KC_F3			= 0x92,
-	KC_F4			= 0x93,
-	KC_F5			= 0x94,
-	KC_F6			= 0x95,
-	KC_F7			= 0x96,
-	KC_F8			= 0x97,
-	KC_F9			= 0x98,
-	KC_F10			= 0x99,
-	KC_F11			= 0x9A,
-	KC_F12			= 0x9B,
-
-	/* Other keys */
-	KC_HOME			= 0xA0,
-	KC_LEFT			= 0xA1,
-	KC_UP			= 0xA2,
-	KC_RIGHT		= 0xA3,
-	KC_DOWN			= 0xA4,
-	KC_PAGE_UP		= 0xA5,
-	KC_PAGE_DOWN	= 0xA6,
-
-	/* Modifier keys */
-	KC_LCONTROL		= 0xB0,
-	KC_RCONTROL		= 0xB1,
-	KC_LSHIFT		= 0xB2,
-	KC_RSHIFT		= 0xB3,
-	KC_CAPS_LOCK	= 0xB4,
-	KC_LALT			= 0xB5,
-	KC_RALT			= 0xB6,
-	KC_LSUPER		= 0xB7,
-	KC_RSUPER		= 0xB8,
-
-	/* [0x30, 0x39] reserved for ASCII digits */
-	KC_0			= 0x30,
-	KC_1			= 0x31,
-	KC_2			= 0x32,
-	KC_3			= 0x33,
-	KC_4			= 0x34,
-	KC_5			= 0x35,
-	KC_6			= 0x36,
-	KC_7			= 0x37,
-	KC_8			= 0x38,
-	KC_9			= 0x39,
-
-	/* [0x41, 0x5A] reserved for ASCII alphabet */
-	KC_A			= 0x41,
-	KC_B			= 0x42,
-	KC_C			= 0x43,
-	KC_D			= 0x44,
-	KC_E			= 0x45,
-	KC_F			= 0x46,
-	KC_G			= 0x47,
-	KC_H			= 0x48,
-	KC_I			= 0x49,
-	KC_J			= 0x4A,
-	KC_K			= 0x4B,
-	KC_L			= 0x4C,
-	KC_M			= 0x4D,
-	KC_N			= 0x4E,
-	KC_O			= 0x4F,
-	KC_P			= 0x50,
-	KC_Q			= 0x51,
-	KC_R			= 0x52,
-	KC_S			= 0x53,
-	KC_T			= 0x54,
-	KC_U			= 0x55,
-	KC_V			= 0x56,
-	KC_W			= 0x57,
-	KC_X			= 0x58,
-	KC_Y			= 0x59,
-	KC_Z			= 0x5A,
-
-	/* [0x61, 0x7A] reserved for ASCII alphabet */
-	KC_a			= 0x61,
-	KC_b			= 0x62,
-	KC_c			= 0x63,
-	KC_d			= 0x64,
-	KC_e			= 0x65,
-	KC_f			= 0x66,
-	KC_g			= 0x67,
-	KC_h			= 0x68,
-	KC_i			= 0x69,
-	KC_j			= 0x6A,
-	KC_k			= 0x6B,
-	KC_l			= 0x6C,
-	KC_m			= 0x6D,
-	KC_n			= 0x6E,
-	KC_o			= 0x6F,
-	KC_p			= 0x70,
-	KC_q			= 0x71,
-	KC_r			= 0x72,
-	KC_s			= 0x73,
-	KC_t			= 0x74,
-	KC_u			= 0x75,
-	KC_v			= 0x76,
-	KC_w			= 0x77,
-	KC_x			= 0x78,
-	KC_y			= 0x79,
-	KC_z			= 0x7A,
-
-	// The last key _must_ be <= 0xFF
-	KC_COUNT		= 0xFF
+	enum Enum
+	{
+		NONE		= 0x00,
+
+		TAB			= 0x09,		// ASCII value
+		ENTER		= 0x0D,		// ASCII value
+		ESCAPE		= 0x1B,		// ASCII value
+		SPACE		= 0x20,		// ASCII value
+		BACKSPACE	= 0x7F,		// ASCII value
+
+		/* KeyPad */
+		KP_0		= 0x80,
+		KP_1		= 0x81,
+		KP_2		= 0x82,
+		KP_3		= 0x83,
+		KP_4		= 0x84,
+		KP_5		= 0x85,
+		KP_6		= 0x86,
+		KP_7		= 0x87,
+		KP_8		= 0x88,
+		KP_9		= 0x89,
+
+		/* Function keys */
+		F1			= 0x90,
+		F2			= 0x91,
+		F3			= 0x92,
+		F4			= 0x93,
+		F5			= 0x94,
+		F6			= 0x95,
+		F7			= 0x96,
+		F8			= 0x97,
+		F9			= 0x98,
+		F10			= 0x99,
+		F11			= 0x9A,
+		F12			= 0x9B,
+
+		/* Other keys */
+		HOME		= 0xA0,
+		LEFT		= 0xA1,
+		UP			= 0xA2,
+		RIGHT		= 0xA3,
+		DOWN		= 0xA4,
+		PAGE_UP		= 0xA5,
+		PAGE_DOWN	= 0xA6,
+
+		/* Modifier keys */
+		LCONTROL	= 0xB0,
+		RCONTROL	= 0xB1,
+		LSHIFT		= 0xB2,
+		RSHIFT		= 0xB3,
+		CAPS_LOCK	= 0xB4,
+		LALT		= 0xB5,
+		RALT		= 0xB6,
+		LSUPER		= 0xB7,
+		RSUPER		= 0xB8,
+
+		/* [0x30, 0x39] reserved for ASCII digits */
+		NUM_0		= 0x30,
+		NUM_1		= 0x31,
+		NUM_2		= 0x32,
+		NUM_3		= 0x33,
+		NUM_4		= 0x34,
+		NUM_5		= 0x35,
+		NUM_6		= 0x36,
+		NUM_7		= 0x37,
+		NUM_8		= 0x38,
+		NUM_9		= 0x39,
+
+		/* [0x41, 0x5A] reserved for ASCII alphabet */
+		A			= 0x41,
+		B			= 0x42,
+		C			= 0x43,
+		D			= 0x44,
+		E			= 0x45,
+		F			= 0x46,
+		G			= 0x47,
+		H			= 0x48,
+		I			= 0x49,
+		J			= 0x4A,
+		K			= 0x4B,
+		L			= 0x4C,
+		M			= 0x4D,
+		N			= 0x4E,
+		O			= 0x4F,
+		P			= 0x50,
+		Q			= 0x51,
+		R			= 0x52,
+		S			= 0x53,
+		T			= 0x54,
+		U			= 0x55,
+		V			= 0x56,
+		W			= 0x57,
+		X			= 0x58,
+		Y			= 0x59,
+		Z			= 0x5A,
+
+		/* [0x61, 0x7A] reserved for ASCII alphabet */
+		a			= 0x61,
+		b			= 0x62,
+		c			= 0x63,
+		d			= 0x64,
+		e			= 0x65,
+		f			= 0x66,
+		g			= 0x67,
+		h			= 0x68,
+		i			= 0x69,
+		j			= 0x6A,
+		k			= 0x6B,
+		l			= 0x6C,
+		m			= 0x6D,
+		n			= 0x6E,
+		o			= 0x6F,
+		p			= 0x70,
+		q			= 0x71,
+		r			= 0x72,
+		s			= 0x73,
+		t			= 0x74,
+		u			= 0x75,
+		v			= 0x76,
+		w			= 0x77,
+		x			= 0x78,
+		y			= 0x79,
+		z			= 0x7A,
+
+		// The last key _must_ be <= 0xFF
+		COUNT		= 0xFF
+	};
 };
 
 } // namespace crown

+ 0 - 90
engine/input/Keyboard.cpp

@@ -1,90 +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 "Keyboard.h"
-#include "Assert.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Keyboard::Keyboard() :
-	m_modifier(0),
-	m_current_frame(0),
-	m_last_key(KC_NOKEY)
-{
-	for (uint32_t i = 0; i < MAX_KEYCODES; i++)
-	{
-		m_keys[i] = ~0;
-		m_state[i] = false;
-	}
-}
-
-//-----------------------------------------------------------------------------
-bool Keyboard::modifier_pressed(ModifierKey modifier) const
-{
-	return (m_modifier & modifier) == modifier;
-}
-
-//-----------------------------------------------------------------------------
-bool Keyboard::key_pressed(KeyCode key) const
-{
-	CE_ASSERT(key >= 0 && key < MAX_KEYCODES, "KeyCode out of range: %d", key);
-
-	return (m_state[key] == true) && (m_keys[key] == m_current_frame);
-}
-
-//-----------------------------------------------------------------------------
-bool Keyboard::key_released(KeyCode key) const
-{
-	CE_ASSERT(key >= 0 && key < MAX_KEYCODES, "KeyCode out of range: %d", key);
-
-	return (m_state[key] == false) && (m_keys[key] == m_current_frame);
-}
-
-//-----------------------------------------------------------------------------
-bool Keyboard::any_pressed() const
-{
-	return key_pressed(m_last_key);
-}
-
-//-----------------------------------------------------------------------------
-bool Keyboard::any_released() const
-{
-	return key_released(m_last_key);
-}
-
-//-----------------------------------------------------------------------------
-void Keyboard::update(uint64_t frame, KeyCode k, bool state)
-{
-	CE_ASSERT(k >= 0 && k < MAX_KEYCODES, "KeyCode out of range: %d", k);
-
-	m_last_key = k;
-	m_keys[k] = frame;
-	m_state[k] = state;
-}
-
-} // namespace crown

+ 62 - 59
engine/input/Keyboard.h

@@ -26,50 +26,34 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
+#include <cstring>
 #include "Types.h"
 #include "KeyCode.h"
-#include "OS.h"
-
-#undef MK_SHIFT
-#undef MK_ALT
+#include "Assert.h"
 
 namespace crown
 {
 
-class InputManager;
-
-
 /// Enumerates modifier keys.
-enum ModifierKey
-{
-	MK_SHIFT	= 1,
-	MK_CTRL		= 2,
-	MK_ALT		= 4
-};
-
-struct KeyboardEvent
+struct ModifierButton
 {
-	KeyCode		key;
-	uint8_t		modifier;
-	char		text[4];
-};
-
-class KeyboardListener
-{
-
-public:
-
-	virtual void key_pressed(const KeyboardEvent& event) { (void)event; }
-	virtual void key_released(const KeyboardEvent& event) { (void)event; }
-	virtual void text_input(const KeyboardEvent& event) { (void)event; }
+	enum Enum
+	{
+		SHIFT	= 1,
+		CTRL	= 2,
+		ALT		= 4
+	};
 };
 
 /// Interface for accessing keyboard input device.
-class Keyboard
+struct Keyboard
 {
-public:
-
-					Keyboard();
+	Keyboard()
+		: m_modifier(0), m_last_button(KeyboardButton::NONE)
+	{
+		memset(m_last_state, 0, KeyboardButton::COUNT);
+		memset(m_current_state, 0, KeyboardButton::COUNT);
+	}
 
 	/// Returns whether the specified @a modifier is pressed.
 	/// @note
@@ -77,36 +61,55 @@ public:
 	/// of another key when the two are pressed in combination. (Thanks wikipedia.)
 	/// @note
 	/// Crown currently supports three different modifier keys: Shift, Ctrl and Alt.
-	bool			modifier_pressed(ModifierKey modifier) const;
-
-	/// Returns whether the specified @a key is pressed in the current frame.
-	bool			key_pressed(KeyCode key) const;
-
-	/// Returns whether the specified @a key is released in the current frame.
-	bool			key_released(KeyCode key) const;
-
-	/// Returns wheter any key is pressed in the current frame.
-	bool			any_pressed() const;
-
-	/// Returns whether any key is released in the current frame.
-	bool			any_released() const;
+	bool modifier_pressed(ModifierButton::Enum modifier) const
+	{
+		return (m_modifier & (uint8_t) modifier) == modifier;
+	}
+
+	/// Returns whether the specified @a b button is pressed in the current frame.
+	bool button_pressed(KeyboardButton::Enum b) const
+	{
+		return bool(~m_last_state[b] & m_current_state[b]);
+	}
+
+	/// Returns whether the specified @a b button is released in the current frame.
+	bool button_released(KeyboardButton::Enum b) const
+	{
+		return bool(m_last_state[b] & ~m_current_state[b]);
+	}
+
+	/// Returns wheter any button is pressed in the current frame.
+	bool any_pressed()
+	{
+		return button_pressed(m_last_button);
+	}
+
+	/// Returns whether any button is released in the current frame.
+	bool any_released()
+	{
+		return button_released(m_last_button);
+	}
+
+	//-------------------------------------------------------------------------
+	void set_button_state(KeyboardButton::Enum b, bool state)
+	{
+		m_last_button = b;
+		m_current_state[b] = state;
+	}
+
+	//-------------------------------------------------------------------------
+	void update()
+	{
+		memcpy(m_last_state, m_current_state, KeyboardButton::COUNT);
+	}
 
-private:
-
-	void			update(uint64_t frame, KeyCode k, bool state);
-
-	uint8_t			m_modifier;
-
-	// The current frame number
-	uint64_t		m_current_frame;
+public:
 
-	// Last key updated
-	KeyCode			m_last_key;
-	uint64_t		m_keys[MAX_KEYCODES];
-	bool			m_state[MAX_KEYCODES];
+	uint8_t m_modifier;
 
-	friend class	InputManager;
+	KeyboardButton::Enum m_last_button;
+	uint8_t m_last_state[KeyboardButton::COUNT];
+	uint8_t m_current_state[KeyboardButton::COUNT];
 };
 
 } // namespace crown
-

+ 0 - 131
engine/input/Mouse.cpp

@@ -1,131 +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 "Mouse.h"
-#include "Device.h"
-#include "OsWindow.h"
-
-#undef MB_RIGHT
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Mouse::Mouse() :
-	m_current_frame(0),
-	m_last_button(MB_LEFT)
-{
-	m_buttons[MB_LEFT] = ~0;
-	m_buttons[MB_MIDDLE] = ~0;
-	m_buttons[MB_RIGHT] = ~0;
-
-	m_state[MB_LEFT] = false;
-	m_state[MB_MIDDLE] = false;
-	m_state[MB_RIGHT] = false;
-}
-
-//-----------------------------------------------------------------------------
-bool Mouse::button_pressed(MouseButton button) const
-{
-	CE_ASSERT(button >= 0 && button < MAX_MOUSE_BUTTONS, "MouseButton out of range: %d", button);
-
-	return (m_state[button] == true) && (m_buttons[button] == m_current_frame);
-}
-
-//-----------------------------------------------------------------------------
-bool Mouse::button_released(MouseButton button) const
-{
-	CE_ASSERT(button >= 0 && button < MAX_MOUSE_BUTTONS, "MouseButton out of range: %d", button);
-
-	return (m_state[button] == false) && (m_buttons[button] == m_current_frame);
-}
-
-//-----------------------------------------------------------------------------
-bool Mouse::any_pressed() const
-{
-	return button_pressed(m_last_button);
-}
-
-//-----------------------------------------------------------------------------
-bool Mouse::any_released() const
-{
-	return button_released(m_last_button);
-}
-
-//-----------------------------------------------------------------------------
-Vec2 Mouse::cursor_xy() const
-{
-	int32_t x, y;
-
-	device()->window()->get_cursor_xy(x, y);
-
-	return Vec2(x, y);
-}
-
-//-----------------------------------------------------------------------------
-void Mouse::set_cursor_xy(const Vec2& position)
-{
-	device()->window()->set_cursor_xy((int32_t) position.x, (int32_t) position.y);
-}
-
-//-----------------------------------------------------------------------------
-Vec2 Mouse::cursor_relative_xy() const
-{
-	uint32_t window_width;
-	uint32_t window_height;
-
-	device()->window()->get_size(window_width, window_height);
-
-	Vec2 pos = cursor_xy();
-
-	pos.x = pos.x / (float) window_width;
-	pos.y = pos.y / (float) window_height;
-
-	return pos;
-}
-
-//-----------------------------------------------------------------------------
-void Mouse::set_cursor_relative_xy(const Vec2& position)
-{
-	uint32_t window_width;
-	uint32_t window_height;
-
-	device()->window()->get_size(window_width, window_height);
-
-	set_cursor_xy(Vec2(position.x * (float) window_width, position.y * (float) window_height));
-}
-
-//-----------------------------------------------------------------------------
-void Mouse::update(uint64_t frame, MouseButton b, bool state)
-{
-	CE_ASSERT(b >= 0 && b < MAX_MOUSE_BUTTONS, "MouseButton out of range: %d", b);
-
-	m_last_button = b;
-	m_buttons[b] = frame;
-	m_state[b] = state;
-}
-
-} // namespace crown

+ 93 - 51
engine/input/Mouse.h

@@ -25,41 +25,25 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #pragma once
-#undef MB_RIGHT
 
+#include <cstring>
 #include "Types.h"
 #include "Vec2.h"
 
 namespace crown
 {
 
-const uint32_t MAX_MOUSE_BUTTONS = 3;
-
 /// Enumerates mouse buttons.
-enum MouseButton
-{
-	MB_LEFT		= 0,
-	MB_MIDDLE	= 1,
-	MB_RIGHT	= 2
-};
-
-struct MouseEvent
+struct MouseButton
 {
-	MouseButton button;
-	int32_t x;
-	int32_t y;
-	float wheel;
-};
-
-/// Interface for managing mouse input.
-class MouseListener
-{
-
-public:
-
-	virtual void button_pressed(const MouseEvent& event) { (void)event; }
-	virtual void button_released(const MouseEvent& event) { (void)event; }
-	virtual void cursor_moved(const MouseEvent& event) { (void)event; }
+	enum Enum
+	{
+		NONE,
+		LEFT,
+		MIDDLE,
+		RIGHT,
+		COUNT
+	};
 };
 
 /// Interface for accessing mouse input device.
@@ -67,34 +51,58 @@ class Mouse
 {
 public:
 
-					Mouse();
-
-
-	/// Returns whether @a button is pressed in the current frame.
-	bool			button_pressed(MouseButton button) const;
-
-	/// Returns whether @a button is released in the current frame.
-	bool			button_released(MouseButton button) const;
+	//-----------------------------------------------------------------------------
+	Mouse()
+		: m_last_button(MouseButton::NONE)
+	{
+		memset(m_last_state, 0, MouseButton::COUNT);
+		memset(m_current_state, 0, MouseButton::COUNT);
+	}
+
+	/// Returns whether the @a b button is pressed in the current frame.
+	bool button_pressed(MouseButton::Enum b)
+	{
+		return bool(~m_last_state[b] & m_current_state[b]);
+	}
+
+	/// Returns whether the @a b button is released in the current frame.
+	bool button_released(MouseButton::Enum b)
+	{
+		return bool(m_last_state[b] & ~m_current_state[b]);
+	}
 
 	/// Returns wheter any button is pressed in the current frame.
-	bool			any_pressed() const;
+	bool any_pressed()
+	{
+		return button_pressed(m_last_button);
+	}
 
 	/// Returns whether any button is released in the current frame.
-	bool			any_released() const;
+	bool any_released()
+	{
+		return button_released(m_last_button);
+	}
 
 	/// Returns the position of the cursor in window space.
 	/// @note
 	/// Coordinates in window space have the origin at the
 	/// upper-left corner of the window. +X extends from left
 	/// to right and +Y extends from top to bottom.
-	Vec2			cursor_xy() const;
+	Vec2 cursor_xy()
+	{
+		return Vec2(m_x, m_y);
+	}
 
 	/// Sets the position of the cursor in window space.
 	/// @note
 	/// Coordinates in window space have the origin at the
 	/// upper-left corner of the window. +X extends from left
 	/// to right and +Y extends from top to bottom.
-	void			set_cursor_xy(const Vec2& position);
+	void set_cursor_xy(const Vec2& position)
+	{
+		m_x = (uint16_t) position.x;
+		m_y = (uint16_t) position.y;
+	}
 
 	/// Returns the relative position of the cursor in window space.
 	/// @note
@@ -105,7 +113,10 @@ public:
 	/// Relative coordinates are mapped to a float varying
 	/// from 0.0 to 1.0 where 0.0 is the origin and 1.0 the
 	/// maximum extent of the cosidered axis.
-	Vec2			cursor_relative_xy() const;
+	Vec2 cursor_relative_xy()
+	{
+		return Vec2(m_x / m_width, m_y / m_height);
+	}
 
 	/// Sets the relative position of the cursor in window space.
 	/// @note
@@ -116,22 +127,53 @@ public:
 	/// Relative coordinates are mapped to a float varying
 	/// from 0.0 to 1.0 where 0.0 is the origin and 1.0 the
 	/// maximum extent of the cosidered axis.
-	void			set_cursor_relative_xy(const Vec2& position);
-
-private:
+	void set_cursor_relative_xy(const Vec2& position)
+	{
+		set_cursor_xy(Vec2(position.x * (float) m_width, position.y * (float) m_height));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_position(uint16_t x, uint16_t y)
+	{
+		m_x = x;
+		m_y = y;
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_metrics(uint16_t width, uint16_t height)
+	{
+		m_width = width;
+		m_height = height;
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_button_state(uint16_t x, uint16_t y, MouseButton::Enum b, bool state)
+	{
+		set_position(x, y);
+
+		m_last_button = b;
+		m_current_state[b] = state;
+	}
+
+	//-----------------------------------------------------------------------------
+	void update()
+	{
+		memcpy(m_last_state, m_current_state, MouseButton::COUNT);
+	}
 
-	void			update(uint64_t frame, MouseButton b, bool state);
-
-	// The current frame number
-	uint64_t		m_current_frame;
+public:
 
-	// Last button updated
-	MouseButton		m_last_button;
+	MouseButton::Enum m_last_button;
+	uint8_t m_last_state[MouseButton::COUNT];
+	uint8_t m_current_state[MouseButton::COUNT];
 
-	uint64_t		m_buttons[MAX_MOUSE_BUTTONS];
-	bool			m_state[MAX_MOUSE_BUTTONS];
+	// Position within the window
+	uint16_t m_x;
+	uint16_t m_y;
 
-	friend class	InputManager;
+	// Window size
+	uint16_t m_width;
+	uint16_t m_height;
 };
 
 } // namespace crown

+ 0 - 66
engine/input/Touch.cpp

@@ -1,66 +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 "Touch.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Touch::Touch()
-{
-
-}
-
-//-----------------------------------------------------------------------------
-bool Touch::touch_up(uint16_t id) const
-{
-	return m_pointers[id].up == true;
-}
-
-//-----------------------------------------------------------------------------
-bool Touch::touch_down(uint16_t id) const
-{
-	return m_pointers[id].up == false;
-}
-
-//----------------------------------------------------------------------------- 
-Vec2 Touch::touch_xy(uint16_t id) const
-{
-	const PointerData& data = m_pointers[id];
-
-	return Vec2(data.x, data.y);
-}
-
-//-----------------------------------------------------------------------------
-Vec2 Touch::touch_relative_xy(uint16_t id)
-{
-	const PointerData& data = m_pointers[id];
-
-	return Vec2(data.relative_x, data.relative_y);
-}
-
-} // namespace crown

+ 22 - 31
engine/input/Touch.h

@@ -43,44 +43,32 @@ struct PointerData
 	bool		up;
 };
 
-struct TouchEvent
-{
-	uint32_t	pointer_id;
-	uint32_t	x;
-	uint32_t	y;
-};
-
-/// Interface for managing touch input device.
-class TouchListener
-{
-
-public:
-
-	virtual void touch_down(const TouchEvent& event) { (void)event; }
-	virtual void touch_up(const TouchEvent& event) { (void)event; }
-	virtual void touch_move(const TouchEvent& event) { (void)event; }
-	virtual void touch_cancel(const TouchEvent& event) { (void)event; }
-};
-
 /// Interface for accessing touch input device.
-class Touch
+struct Touch
 {
-public:
-
-					Touch();
-
 	/// Returns whether the touch pointer @a id is up.
-	bool			touch_up(uint16_t id) const;
+	bool touch_up(uint16_t id) const
+	{
+		return m_pointers[id].up == true;
+	}
 
 	/// Returns whether the touch pointer @a id is down.
-	bool			touch_down(uint16_t id) const;
+	bool touch_down(uint16_t id) const
+	{
+		return m_pointers[id].up == false;
+	}
 
 	/// Returns the position of the pointer @a id in windows space.
 	/// @note
 	/// Coordinates in window space have the origin at the
 	/// upper-left corner of the window. +X extends from left
 	/// to right and +Y extends from top to bottom.
-	Vec2			touch_xy(uint16_t id) const;
+	Vec2 touch_xy(uint16_t id) const
+	{
+		const PointerData& data = m_pointers[id];
+
+		return Vec2(data.x, data.y);
+	}
 
 	/// Returns the relative position of the pointer @a id in window space.
 	/// @note
@@ -91,13 +79,16 @@ public:
 	/// Relative coordinates are mapped to a float varying
 	/// from 0.0 to 1.0 where 0.0 is the origin and 1.0 the
 	/// maximum extent of the cosidered axis.
-	Vec2			touch_relative_xy(uint16_t id);
+	Vec2 touch_relative_xy(uint16_t id)
+	{
+		const PointerData& data = m_pointers[id];
 
-private:
+		return Vec2(data.relative_x, data.relative_y);
+	}
 
-	PointerData		m_pointers[MAX_POINTER_IDS];
+public:
 
-	friend class	InputManager;
+	PointerData		m_pointers[MAX_POINTER_IDS];
 };
 
 }

+ 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

+ 141 - 218
engine/lua/LuaEnvironment.cpp

@@ -24,184 +24,156 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#include <stdarg.h>
 
-#include "Device.h"
-#include "OS.h"
-#include "Assert.h"
-#include "Log.h"
 #include "LuaEnvironment.h"
-#include "StringSetting.h"
-#include "Filesystem.h"
+#include "Assert.h"
+#include "StringUtils.h"
+#include "LuaStack.h"
+#include "Device.h"
+#include "LuaResource.h"
+#include "ResourceManager.h"
 
 namespace crown
 {
 
-StringSetting g_boot("boot_file", "lua main file", "lua/game.raw");
-
-/*
-*N.B: Lua garbage collection is actually disabled
-*/
-
 //-----------------------------------------------------------------------------
-LuaEnvironment::LuaEnvironment() :
-	m_state(luaL_newstate()),
-	m_is_used(false)
-	//m_thread(LuaEnvironment::background_thread, (void*)this, "lua-environment-thread")
+CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
 {
-	// Open Lua default libraries
-	string::strncpy(m_error_buffer, "", 1024);
-
-	string::strncpy(m_tmp_buffer, "", 1024);
-}
+	LuaEnvironment* env = device()->lua_environment();
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::init()
-{
-	// Open default libraries
-	luaL_openlibs(m_state);
-	// Open Crown library
-	lua_cpcall(m_state, luaopen_libcrown, NULL);
+	load_int_setting(*env);
+	load_float_setting(*env);
+	load_string_setting(*env);
 
-	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);
+	load_vec2(*env);
+	load_vec3(*env);
+	load_mat4(*env);
+	load_quat(*env);
+	load_math(*env);
+	load_window(*env);
+	load_mouse(*env);
+	load_keyboard(*env);
+	load_accelerometer(*env);
+	load_device(*env);
+	load_resource_package(*env);
+	// load_unit(*env);
+	// load_world(*env);
 
-	m_is_used = true;
+	return 1;
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::shutdown()
+static int crown_lua_require(lua_State* L)
 {
-	lua_close(m_state);
+	LuaStack stack(L);
 
-	m_is_used = false;
-}
+	const char* filename = stack.get_string(1);
 
-//-----------------------------------------------------------------------------
-lua_State* LuaEnvironment::state()
-{
-	return m_state;
-}
+	const ResourceId lua_res = device()->resource_manager()->load("lua", filename);
+	device()->resource_manager()->flush();
 
-//-----------------------------------------------------------------------------
-const char* LuaEnvironment::error()
-{	
-	string::strncpy(m_tmp_buffer, m_error_buffer, 1024);
+	const LuaResource* lr = (LuaResource*) device()->resource_manager()->data(lua_res);
+	luaL_loadbuffer(L, (const char*) lr->code(), lr->size(), "");
 
-	string::strncpy(m_error_buffer, "", 1024);
+	device()->resource_manager()->unload(lua_res);
 
-	return m_tmp_buffer;
+	return 1;
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::load_buffer(const char* buffer, size_t len)
+LuaEnvironment::LuaEnvironment()
+	: m_state(luaL_newstate()), m_is_used(false)
 {
-	int32_t loaded = luaL_loadbuffer(m_state, buffer, len, "");
-
-	if (loaded != 0)
-	{
-		lua_error();
-	}
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::load_file(const char* file)
+void LuaEnvironment::init()
 {
-	int32_t loaded = luaL_loadfile(m_state, file);
+	// Open default libraries
+	luaL_openlibs(m_state);
+	// Open Crown library
+	lua_cpcall(m_state, luaopen_libcrown, NULL);
 
-	if (loaded != 0)
+	// Register custom loader
+	lua_getfield(m_state, LUA_GLOBALSINDEX, "package");
+	lua_getfield(m_state, -1, "loaders");
+	lua_remove(m_state, -2);
+
+	int num_loaders = 0;
+	lua_pushnil(m_state);
+	while (lua_next(m_state, -2) != 0)
 	{
-		lua_error();
+		lua_pop(m_state, 1);
+		num_loaders++;
 	}
-}
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::load_string(const char* str)
-{
-	int32_t loaded = luaL_loadstring(m_state, str);
+	lua_pushinteger(m_state, num_loaders + 1);
+	lua_pushcfunction(m_state, crown_lua_require);
+	lua_rawset(m_state, -3);
 
-	if (loaded != 0)
-	{
-		lua_error();
-	}
-}
+	lua_pop(m_state, 1);
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::get_global_symbol(const char* symbol)
-{
-	lua_getglobal(m_state, symbol);
+	m_is_used = true;
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::execute(int32_t args, int32_t results)
+void LuaEnvironment::shutdown()
 {
-	int32_t executed = lua_pcall(m_state, args, results, 0);
-
-	if (executed != 0)
-	{
-		lua_error();
-	}
+	lua_close(m_state);
+	m_is_used = false;
 }
 
-// //-----------------------------------------------------------------------------
-// void LuaEnvironment::collect_garbage()
-// {
-// 	uint64_t start = os::milliseconds();
-
-// 	while ((os::milliseconds() - start) < device()->last_delta_time() && !m_is_used)
-// 	{
-// 		lua_gc(m_state, LUA_GCSTEP, 0);
-// 	}
-// }
-
-// //-----------------------------------------------------------------------------
-// void* LuaEnvironment::background_thread(void* thiz)
-// {
-// 	((LuaEnvironment*)thiz)->collect_garbage();	
-// }
-
 //-----------------------------------------------------------------------------
-void LuaEnvironment::game_init()
+bool LuaEnvironment::load_and_execute(const char* res_name)
 {
-	const char* path = device()->filesystem()->os_path(g_boot.value());
+	CE_ASSERT_NOT_NULL(res_name);
 
-	load_file(path);
-	execute(0, 0);
+	ResourceManager* resman = device()->resource_manager();
 
-	get_global_symbol("init");
-	execute(0, 0);
-}
+	// 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;
+		}
+	}
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::game_shutdown()
-{
-	get_global_symbol("shutdown");
-	execute(0, 0);
+	error();
+	lua_pop(m_state, 2); // Pop debug.traceback
+	return false;
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::game_frame(float dt)
+bool LuaEnvironment::execute_string(const char* s)
 {
-	LuaStack stack(m_state);
-
-	get_global_symbol("frame");
-	stack.push_float(dt);
-	execute(1, 0);
-}
+	CE_ASSERT_NOT_NULL(s);
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::lua_error()
-{
-	string::strncpy(m_error_buffer, "", 1024);
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
+	if (luaL_loadstring(m_state, s) == 0)
+	{
+		if (lua_pcall(m_state, 0, 0, -2) == 0)
+		{
+			// Unloading is OK since the script data has been copied to Lua
+			lua_pop(m_state, 2); // Pop debug.traceback
+			return true;
+		}
+	}
 
-	string::strncpy(m_error_buffer, lua_tostring(m_state, -1), 1024);
+	error();
+	lua_pop(m_state, 2); // Pop debug.traceback
+	return false;
 }
 
 //-----------------------------------------------------------------------------
@@ -211,7 +183,6 @@ void LuaEnvironment::load_module_function(const char* module, const char* name,
 
 	entry[0].name = name;
 	entry[0].func = func;
-
 	entry[1].name = NULL;
 	entry[1].func = NULL;
 
@@ -226,105 +197,57 @@ void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name,
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t luaopen_libcrown(lua_State* /*L*/)
+bool LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 {
-	LuaEnvironment* env = device()->lua_environment();
+	CE_ASSERT_NOT_NULL(func);
 
-	load_int_setting(*env);
-	load_float_setting(*env);
-	load_string_setting(*env);
+	LuaStack stack(m_state);
 
-	load_vec2(*env);
-	load_vec3(*env);
-	load_mat4(*env);
-	load_quat(*env);
-	load_math(*env);
+	va_list vl;
+	va_start(vl, argc);
 
-	load_mouse(*env);
-	load_keyboard(*env);
-	load_accelerometer(*env);
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
+	lua_getglobal(m_state, func);
 
-	load_device(*env);
+	for (uint8_t i = 0; i < argc; i++)
+	{
+		const int type = va_arg(vl, int);
+		switch (type)
+		{
+			case ARGUMENT_FLOAT:
+			{
+				stack.push_float(va_arg(vl, double));
+				break;
+			}
+			default:
+			{
+				CE_ASSERT(false, "Oops, lua argument unknown");
+				break;
+			}
+		}
+	}
 
-	load_window(*env);
+	va_end(vl);
 
-	load_unit(*env);
-	load_world(*env);
+	if (lua_pcall(m_state, argc, 0, -argc - 2) != 0)
+	{
+		error();
+		lua_pop(m_state, 2); // Pop debug.traceback
+		return false;
+	}
 
-	return 1;
+	lua_pop(m_state, 2); // Pop debug.traceback
+
+	return true;
 }
 
-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";
+//-----------------------------------------------------------------------------
+void LuaEnvironment::error()
+{
+	const char* msg = lua_tostring(m_state, -1);
+	Log::e(msg);
+	lua_pop(m_state, 1);
+}
 
 } // namespace crown

+ 28 - 53
engine/lua/LuaEnvironment.h

@@ -27,15 +27,19 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "lua.hpp"
-#include "Types.h"
 #include "Config.h"
-#include "LuaStack.h"
-#include "LinearAllocator.h"
-#include "Thread.h"
+#include "Types.h"
 
 namespace crown
 {
 
+enum LuaArgumentType
+{
+	ARGUMENT_FLOAT
+};
+
+class LuaResource;
+
 /// LuaEnvironment is a wrapper of a subset of Lua functions and 
 /// provides utilities for extending Lua
 class LuaEnvironment
@@ -48,43 +52,34 @@ public:
 	void					init();
 	/// Close Lua state and shutdown LuaEnvironment
 	void					shutdown();
-	/// Return the __lua_State__ pointer required by each Lua function
-	lua_State*				state();
-
-	const char*				error();
-	/// Load Lua chunk as buffer. @a buffer contains lua chunk, @len is length of buffer
-	void					load_buffer(const char* buffer, size_t len);
-	/// Load Lua chunk as file. @a file is path to lua file
-	void					load_file(const char* file);
-	/// Load Lua chunk as string
-	void 					load_string(const char* str);
-	/// Get global symbol from Lua stack. @symbol is the name of required symbol
-	void					get_global_symbol(const char* symbol);
-	/// Execute Lua chunk. @a args is the number of arguments required
-	/// @a results is the number of results returned
-	void					execute(int32_t args, int32_t results);
-	/// Collect garbage generated by Lua
-	void					collect_garbage();
-	/// Call init function in the Lua game file
-	void					game_init();
-	/// Call shutdown function in the Lua game file
-	void					game_shutdown();
-	/// Call frame function in the Lua game file
-	void					game_frame(float dt);
+
+	/// Loads and execute the given @a res_name Lua resource, returns
+	/// true if success, false otherwise.
+	bool					load_and_execute(const char* res_name);
+
+	bool					execute_string(const char* s);
+
 	/// 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.
 	/// _func_ must be a C/lua function (__int32_t function_name(lua_State* L)__)
 	void					load_module_function(const char* module, const char* name, const lua_CFunction func);
+
 	/// Load a enum's value which will be used in Lua. 
 	/// @a module is the name of table contenitor, generally take  enum's name
 	/// @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:
-	/// Thread used for garbage collection. It calls __collect_garbage()__
-	static void*			background_thread(void* thiz);
 
-	void					lua_error();
 	// Disable copying
 							LuaEnvironment(const LuaEnvironment&);
 	LuaEnvironment& 		operator=(const LuaEnvironment&);
@@ -92,31 +87,11 @@ private:
 private:
 	/// Required by each Lua function
 	lua_State*				m_state;
+
 	/// LuaEnvironment is used right now?
 	bool					m_is_used;
-	/// Thread used for garbage collection
-	// os::Thread 				m_thread;
-
-	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;
-
-	// static const char*		type_name;
-
-	// static const char*		type_count;
 };
 
-
 void load_int_setting(LuaEnvironment& env);
 void load_float_setting(LuaEnvironment& env);
 void load_string_setting(LuaEnvironment& env);
@@ -132,11 +107,11 @@ void load_touch(LuaEnvironment& env);
 void load_accelerometer(LuaEnvironment& env);
 void load_device(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
-
+void load_resource_package(LuaEnvironment& env);
 void load_unit(LuaEnvironment& env);
 void load_camera(LuaEnvironment& env);
 void load_world(LuaEnvironment& env);
 
 CE_EXPORT int32_t luaopen_libcrown(lua_State* L);
 
-} // namespace crown
+} // namespace crown

+ 114 - 119
engine/lua/LuaKeyboard.cpp

@@ -39,31 +39,31 @@ CE_EXPORT int keyboard_modifier_pressed(lua_State* L)
 
 	int32_t modifier = stack.get_int(1);
 
-	stack.push_bool(device()->keyboard()->modifier_pressed((ModifierKey) modifier));
+	stack.push_bool(device()->keyboard()->modifier_pressed((ModifierButton::Enum) modifier));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int keyboard_key_pressed(lua_State* L)
+CE_EXPORT int keyboard_button_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
-	int32_t key = stack.get_int(1);
+	int32_t button = stack.get_int(1);
 
-	stack.push_bool(device()->keyboard()->key_pressed((KeyCode) key));
+	stack.push_bool(device()->keyboard()->button_pressed((KeyboardButton::Enum) button));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int keyboard_key_released(lua_State* L)
+CE_EXPORT int keyboard_button_released(lua_State* L)
 {
 	LuaStack stack(L);
 
-	int32_t key = stack.get_int(1);
+	int32_t button = stack.get_int(1);
 
-	stack.push_bool(device()->keyboard()->key_released((KeyCode) key));
+	stack.push_bool(device()->keyboard()->button_released((KeyboardButton::Enum) button));
 
 	return 1;
 }
@@ -92,135 +92,130 @@ CE_EXPORT int keyboard_any_released(lua_State* L)
 void load_keyboard(LuaEnvironment& env)
 {
 	env.load_module_function("Keyboard", "modifier_pressed",	keyboard_modifier_pressed);
-	env.load_module_function("Keyboard", "key_pressed",			keyboard_key_pressed);
-	env.load_module_function("Keyboard", "key_released",		keyboard_key_released);
+	env.load_module_function("Keyboard", "button_pressed",		keyboard_button_pressed);
+	env.load_module_function("Keyboard", "button_released",		keyboard_button_released);
 	env.load_module_function("Keyboard", "any_pressed",			keyboard_any_pressed);
 	env.load_module_function("Keyboard", "any_released",		keyboard_any_released);
 
-	env.load_module_enum("Keyboard", "KC_NOKEY",		KC_NOKEY);
-
-	env.load_module_enum("Keyboard", "KC_TAB",			KC_TAB);
-	env.load_module_enum("Keyboard", "KC_ENTER",		KC_ENTER);
-	env.load_module_enum("Keyboard", "KC_ESCAPE",		KC_ESCAPE);
-	env.load_module_enum("Keyboard", "KC_SPACE",		KC_SPACE);
-	env.load_module_enum("Keyboard", "KC_BACKSPACE",	KC_BACKSPACE);
+	env.load_module_enum("Keyboard", "TAB",			KeyboardButton::TAB);
+	env.load_module_enum("Keyboard", "ENTER",		KeyboardButton::ENTER);
+	env.load_module_enum("Keyboard", "ESCAPE",		KeyboardButton::ESCAPE);
+	env.load_module_enum("Keyboard", "SPACE",		KeyboardButton::SPACE);
+	env.load_module_enum("Keyboard", "BACKSPACE",	KeyboardButton::BACKSPACE);
 
 	/* KeyPad */
-	env.load_module_enum("Keyboard", "KC_KP_0",			KC_KP_0);
-	env.load_module_enum("Keyboard", "KC_KP_1",			KC_KP_1);
-	env.load_module_enum("Keyboard", "KC_KP_2",			KC_KP_2);
-	env.load_module_enum("Keyboard", "KC_KP_3",			KC_KP_3);
-	env.load_module_enum("Keyboard", "KC_KP_4",			KC_KP_4);
-	env.load_module_enum("Keyboard", "KC_KP_5",			KC_KP_5);
-	env.load_module_enum("Keyboard", "KC_KP_6",			KC_KP_6);
-	env.load_module_enum("Keyboard", "KC_KP_7",			KC_KP_7);
-	env.load_module_enum("Keyboard", "KC_KP_8",			KC_KP_8);
-	env.load_module_enum("Keyboard", "KC_KP_9",			KC_KP_9);
+	env.load_module_enum("Keyboard", "KP_0",		KeyboardButton::KP_0);
+	env.load_module_enum("Keyboard", "KP_1",		KeyboardButton::KP_1);
+	env.load_module_enum("Keyboard", "KP_2",		KeyboardButton::KP_2);
+	env.load_module_enum("Keyboard", "KP_3",		KeyboardButton::KP_3);
+	env.load_module_enum("Keyboard", "KP_4",		KeyboardButton::KP_4);
+	env.load_module_enum("Keyboard", "KP_5",		KeyboardButton::KP_5);
+	env.load_module_enum("Keyboard", "KP_6",		KeyboardButton::KP_6);
+	env.load_module_enum("Keyboard", "KP_7",		KeyboardButton::KP_7);
+	env.load_module_enum("Keyboard", "KP_8",		KeyboardButton::KP_8);
+	env.load_module_enum("Keyboard", "KP_9",		KeyboardButton::KP_9);
 
 	/* Function keys */
-	env.load_module_enum("Keyboard", "KC_F1",			KC_F1);
-	env.load_module_enum("Keyboard", "KC_F2",			KC_F2);
-	env.load_module_enum("Keyboard", "KC_F3",			KC_F3);
-	env.load_module_enum("Keyboard", "KC_F4",			KC_F4);
-	env.load_module_enum("Keyboard", "KC_F5",			KC_F5);
-	env.load_module_enum("Keyboard", "KC_F6",			KC_F6);
-	env.load_module_enum("Keyboard", "KC_F7",			KC_F7);
-	env.load_module_enum("Keyboard", "KC_F8",			KC_F8);
-	env.load_module_enum("Keyboard", "KC_F9",			KC_F9);
-	env.load_module_enum("Keyboard", "KC_F10",			KC_F10);
-	env.load_module_enum("Keyboard", "KC_F11",			KC_F11);
-	env.load_module_enum("Keyboard", "KC_F12",			KC_F12);
+	env.load_module_enum("Keyboard", "F1",			KeyboardButton::F1);
+	env.load_module_enum("Keyboard", "F2",			KeyboardButton::F2);
+	env.load_module_enum("Keyboard", "F3",			KeyboardButton::F3);
+	env.load_module_enum("Keyboard", "F4",			KeyboardButton::F4);
+	env.load_module_enum("Keyboard", "F5",			KeyboardButton::F5);
+	env.load_module_enum("Keyboard", "F6",			KeyboardButton::F6);
+	env.load_module_enum("Keyboard", "F7",			KeyboardButton::F7);
+	env.load_module_enum("Keyboard", "F8",			KeyboardButton::F8);
+	env.load_module_enum("Keyboard", "F9",			KeyboardButton::F9);
+	env.load_module_enum("Keyboard", "F10",			KeyboardButton::F10);
+	env.load_module_enum("Keyboard", "F11",			KeyboardButton::F11);
+	env.load_module_enum("Keyboard", "F12",			KeyboardButton::F12);
 
 	/* Other keys */
-	env.load_module_enum("Keyboard", "KC_HOME",			KC_HOME);
-	env.load_module_enum("Keyboard", "KC_LEFT",			KC_LEFT);
-	env.load_module_enum("Keyboard", "KC_UP",			KC_UP);
-	env.load_module_enum("Keyboard", "KC_RIGHT",		KC_RIGHT);
-	env.load_module_enum("Keyboard", "KC_DOWN",			KC_DOWN);
-	env.load_module_enum("Keyboard", "KC_PAGE_UP",		KC_PAGE_UP);
-	env.load_module_enum("Keyboard", "KC_PAGE_DOWN",	KC_PAGE_DOWN);
+	env.load_module_enum("Keyboard", "HOME",		KeyboardButton::HOME);
+	env.load_module_enum("Keyboard", "LEFT",		KeyboardButton::LEFT);
+	env.load_module_enum("Keyboard", "UP",			KeyboardButton::UP);
+	env.load_module_enum("Keyboard", "RIGHT",		KeyboardButton::RIGHT);
+	env.load_module_enum("Keyboard", "DOWN",		KeyboardButton::DOWN);
+	env.load_module_enum("Keyboard", "PAGE_UP",		KeyboardButton::PAGE_UP);
+	env.load_module_enum("Keyboard", "PAGE_DOWN",	KeyboardButton::PAGE_DOWN);
 
 	/* Modifier keys */
-	env.load_module_enum("Keyboard", "KC_LCONTROL",		KC_LCONTROL);
-	env.load_module_enum("Keyboard", "KC_RCONTROL",		KC_RCONTROL);
-	env.load_module_enum("Keyboard", "KC_LSHIFT",		KC_LSHIFT);
-	env.load_module_enum("Keyboard", "KC_RSHIFT",		KC_RSHIFT);
-	env.load_module_enum("Keyboard", "KC_CAPS_LOCK",	KC_CAPS_LOCK);
-	env.load_module_enum("Keyboard", "KC_LALT",			KC_LALT);
-	env.load_module_enum("Keyboard", "KC_RALT",			KC_RALT);
-	env.load_module_enum("Keyboard", "KC_LSUPER",		KC_LSUPER);
-	env.load_module_enum("Keyboard", "KC_RSUPER",		KC_RSUPER);
+	env.load_module_enum("Keyboard", "LCONTROL",	KeyboardButton::LCONTROL);
+	env.load_module_enum("Keyboard", "RCONTROL",	KeyboardButton::RCONTROL);
+	env.load_module_enum("Keyboard", "LSHIFT",		KeyboardButton::LSHIFT);
+	env.load_module_enum("Keyboard", "RSHIFT",		KeyboardButton::RSHIFT);
+	env.load_module_enum("Keyboard", "CAPS_LOCK",	KeyboardButton::CAPS_LOCK);
+	env.load_module_enum("Keyboard", "LALT",		KeyboardButton::LALT);
+	env.load_module_enum("Keyboard", "RALT",		KeyboardButton::RALT);
+	env.load_module_enum("Keyboard", "LSUPER",		KeyboardButton::LSUPER);
+	env.load_module_enum("Keyboard", "RSUPER",		KeyboardButton::RSUPER);
 
 	/* [0x30, 0x39] reserved for ASCII digits */
-	env.load_module_enum("Keyboard", "KC_0",			KC_0);
-	env.load_module_enum("Keyboard", "KC_1",			KC_1);
-	env.load_module_enum("Keyboard", "KC_2",			KC_2);
-	env.load_module_enum("Keyboard", "KC_3",			KC_3);
-	env.load_module_enum("Keyboard", "KC_4",			KC_4);
-	env.load_module_enum("Keyboard", "KC_5",			KC_5);
-	env.load_module_enum("Keyboard", "KC_6",			KC_6);
-	env.load_module_enum("Keyboard", "KC_7",			KC_7);
-	env.load_module_enum("Keyboard", "KC_8",			KC_8);
-	env.load_module_enum("Keyboard", "KC_9",			KC_9);
+	env.load_module_enum("Keyboard", "NUM_0",		KeyboardButton::NUM_0);
+	env.load_module_enum("Keyboard", "NUM_1",		KeyboardButton::NUM_1);
+	env.load_module_enum("Keyboard", "NUM_2",		KeyboardButton::NUM_2);
+	env.load_module_enum("Keyboard", "NUM_3",		KeyboardButton::NUM_3);
+	env.load_module_enum("Keyboard", "NUM_4",		KeyboardButton::NUM_4);
+	env.load_module_enum("Keyboard", "NUM_5",		KeyboardButton::NUM_5);
+	env.load_module_enum("Keyboard", "NUM_6",		KeyboardButton::NUM_6);
+	env.load_module_enum("Keyboard", "NUM_7",		KeyboardButton::NUM_7);
+	env.load_module_enum("Keyboard", "NUM_8",		KeyboardButton::NUM_8);
+	env.load_module_enum("Keyboard", "NUM_9",		KeyboardButton::NUM_9);
 
 	/* [0x41, 0x5A] reserved for ASCII alph,abet */
-	env.load_module_enum("Keyboard", "KC_A",			KC_A);
-	env.load_module_enum("Keyboard", "KC_B",			KC_B);
-	env.load_module_enum("Keyboard", "KC_C",			KC_C);
-	env.load_module_enum("Keyboard", "KC_D",			KC_D);
-	env.load_module_enum("Keyboard", "KC_E",			KC_E);
-	env.load_module_enum("Keyboard", "KC_F",			KC_F);
-	env.load_module_enum("Keyboard", "KC_G",			KC_G);
-	env.load_module_enum("Keyboard", "KC_H",			KC_H);
-	env.load_module_enum("Keyboard", "KC_I",			KC_I);
-	env.load_module_enum("Keyboard", "KC_J",			KC_J);
-	env.load_module_enum("Keyboard", "KC_K",			KC_K);
-	env.load_module_enum("Keyboard", "KC_L",			KC_L);
-	env.load_module_enum("Keyboard", "KC_M",			KC_M);
-	env.load_module_enum("Keyboard", "KC_N",			KC_N);
-	env.load_module_enum("Keyboard", "KC_O",			KC_O);
-	env.load_module_enum("Keyboard", "KC_P",			KC_P);
-	env.load_module_enum("Keyboard", "KC_Q",			KC_Q);
-	env.load_module_enum("Keyboard", "KC_R",			KC_R);
-	env.load_module_enum("Keyboard", "KC_S",			KC_S);
-	env.load_module_enum("Keyboard", "KC_T",			KC_T);
-	env.load_module_enum("Keyboard", "KC_U",			KC_U);
-	env.load_module_enum("Keyboard", "KC_V",			KC_V);
-	env.load_module_enum("Keyboard", "KC_W",			KC_W);
-	env.load_module_enum("Keyboard", "KC_X",			KC_X);
-	env.load_module_enum("Keyboard", "KC_Y",			KC_Y);
-	env.load_module_enum("Keyboard", "KC_Z",			KC_Z);
+	env.load_module_enum("Keyboard", "A",			KeyboardButton::A);
+	env.load_module_enum("Keyboard", "B",			KeyboardButton::B);
+	env.load_module_enum("Keyboard", "C",			KeyboardButton::C);
+	env.load_module_enum("Keyboard", "D",			KeyboardButton::D);
+	env.load_module_enum("Keyboard", "E",			KeyboardButton::E);
+	env.load_module_enum("Keyboard", "F",			KeyboardButton::F);
+	env.load_module_enum("Keyboard", "G",			KeyboardButton::G);
+	env.load_module_enum("Keyboard", "H",			KeyboardButton::H);
+	env.load_module_enum("Keyboard", "I",			KeyboardButton::I);
+	env.load_module_enum("Keyboard", "J",			KeyboardButton::J);
+	env.load_module_enum("Keyboard", "K",			KeyboardButton::K);
+	env.load_module_enum("Keyboard", "L",			KeyboardButton::L);
+	env.load_module_enum("Keyboard", "M",			KeyboardButton::M);
+	env.load_module_enum("Keyboard", "N",			KeyboardButton::N);
+	env.load_module_enum("Keyboard", "O",			KeyboardButton::O);
+	env.load_module_enum("Keyboard", "P",			KeyboardButton::P);
+	env.load_module_enum("Keyboard", "Q",			KeyboardButton::Q);
+	env.load_module_enum("Keyboard", "R",			KeyboardButton::R);
+	env.load_module_enum("Keyboard", "S",			KeyboardButton::S);
+	env.load_module_enum("Keyboard", "T",			KeyboardButton::T);
+	env.load_module_enum("Keyboard", "U",			KeyboardButton::U);
+	env.load_module_enum("Keyboard", "V",			KeyboardButton::V);
+	env.load_module_enum("Keyboard", "W",			KeyboardButton::W);
+	env.load_module_enum("Keyboard", "X",			KeyboardButton::X);
+	env.load_module_enum("Keyboard", "Y",			KeyboardButton::Y);
+	env.load_module_enum("Keyboard", "Z",			KeyboardButton::Z);
 
 	/* [0x61, 0x7A] reserved for ASCII alphabet */
-	env.load_module_enum("Keyboard", "KC_a",			KC_a);
-	env.load_module_enum("Keyboard", "KC_b",			KC_b);
-	env.load_module_enum("Keyboard", "KC_c",			KC_c);
-	env.load_module_enum("Keyboard", "KC_d",			KC_d);
-	env.load_module_enum("Keyboard", "KC_e",			KC_e);
-	env.load_module_enum("Keyboard", "KC_f",			KC_f);
-	env.load_module_enum("Keyboard", "KC_g",			KC_g);
-	env.load_module_enum("Keyboard", "KC_h",			KC_h);
-	env.load_module_enum("Keyboard", "KC_i",			KC_i);
-	env.load_module_enum("Keyboard", "KC_j",			KC_j);
-	env.load_module_enum("Keyboard", "KC_k",			KC_k);
-	env.load_module_enum("Keyboard", "KC_l",			KC_l);
-	env.load_module_enum("Keyboard", "KC_m",			KC_m);
-	env.load_module_enum("Keyboard", "KC_n",			KC_n);
-	env.load_module_enum("Keyboard", "KC_o",			KC_o);
-	env.load_module_enum("Keyboard", "KC_p",			KC_p);
-	env.load_module_enum("Keyboard", "KC_q",			KC_q);
-	env.load_module_enum("Keyboard", "KC_r",			KC_r);
-	env.load_module_enum("Keyboard", "KC_s",			KC_s);
-	env.load_module_enum("Keyboard", "KC_t",			KC_t);
-	env.load_module_enum("Keyboard", "KC_u",			KC_u);
-	env.load_module_enum("Keyboard", "KC_v",			KC_v);
-	env.load_module_enum("Keyboard", "KC_w",			KC_w);
-	env.load_module_enum("Keyboard", "KC_x",			KC_x);
-	env.load_module_enum("Keyboard", "KC_y",			KC_y);
-	env.load_module_enum("Keyboard", "KC_z",			KC_z);
-
-	// The last key _must_ be <= 0xFF
-	env.load_module_enum("Keyboard", "KC_COUNT",		KC_COUNT);
+	env.load_module_enum("Keyboard", "a",			KeyboardButton::a);
+	env.load_module_enum("Keyboard", "b",			KeyboardButton::b);
+	env.load_module_enum("Keyboard", "c",			KeyboardButton::c);
+	env.load_module_enum("Keyboard", "d",			KeyboardButton::d);
+	env.load_module_enum("Keyboard", "e",			KeyboardButton::e);
+	env.load_module_enum("Keyboard", "f",			KeyboardButton::f);
+	env.load_module_enum("Keyboard", "g",			KeyboardButton::g);
+	env.load_module_enum("Keyboard", "h",			KeyboardButton::h);
+	env.load_module_enum("Keyboard", "i",			KeyboardButton::i);
+	env.load_module_enum("Keyboard", "j",			KeyboardButton::j);
+	env.load_module_enum("Keyboard", "k",			KeyboardButton::k);
+	env.load_module_enum("Keyboard", "l",			KeyboardButton::l);
+	env.load_module_enum("Keyboard", "m",			KeyboardButton::m);
+	env.load_module_enum("Keyboard", "n",			KeyboardButton::n);
+	env.load_module_enum("Keyboard", "o",			KeyboardButton::o);
+	env.load_module_enum("Keyboard", "p",			KeyboardButton::p);
+	env.load_module_enum("Keyboard", "q",			KeyboardButton::q);
+	env.load_module_enum("Keyboard", "r",			KeyboardButton::r);
+	env.load_module_enum("Keyboard", "s",			KeyboardButton::s);
+	env.load_module_enum("Keyboard", "t",			KeyboardButton::t);
+	env.load_module_enum("Keyboard", "u",			KeyboardButton::u);
+	env.load_module_enum("Keyboard", "v",			KeyboardButton::v);
+	env.load_module_enum("Keyboard", "w",			KeyboardButton::w);
+	env.load_module_enum("Keyboard", "x",			KeyboardButton::x);
+	env.load_module_enum("Keyboard", "y",			KeyboardButton::y);
+	env.load_module_enum("Keyboard", "z",			KeyboardButton::z);
 }
 
 } // namespace crown

+ 5 - 5
engine/lua/LuaMouse.cpp

@@ -40,7 +40,7 @@ CE_EXPORT int mouse_button_pressed(lua_State* L)
 
 	int32_t button = stack.get_int(1);
 
-	stack.push_bool(device()->mouse()->button_pressed((MouseButton) button));
+	stack.push_bool(device()->mouse()->button_pressed((MouseButton::Enum) button));
 
 	return 1;
 }
@@ -52,7 +52,7 @@ CE_EXPORT int mouse_button_released(lua_State* L)
 
 	int32_t button = stack.get_int(1);
 
-	stack.push_bool(device()->mouse()->button_released((MouseButton) button));
+	stack.push_bool(device()->mouse()->button_released((MouseButton::Enum) button));
 
 	return 1;
 }
@@ -133,9 +133,9 @@ void load_mouse(LuaEnvironment& env)
 	env.load_module_function("Mouse", "cursor_relative_xy",		mouse_cursor_relative_xy);
 	env.load_module_function("Mouse", "set_cursor_relative_xy",	mouse_set_cursor_relative_xy);
 
-	env.load_module_enum("Mouse", "MB_LEFT",		MB_LEFT);
-	env.load_module_enum("Mouse", "KB_MIDDLE",		MB_MIDDLE);
-	env.load_module_enum("Mouse", "MB_RIGHT",		MB_RIGHT);
+	env.load_module_enum("Mouse", "LEFT",						MouseButton::LEFT);
+	env.load_module_enum("Mouse", "MIDDLE",						MouseButton::MIDDLE);
+	env.load_module_enum("Mouse", "RIGHT", 						MouseButton::RIGHT);
 }
 
 } // namespace crown

+ 32 - 32
engine/core/filesystem/BinaryWriter.cpp → engine/lua/LuaResourcePackage.cpp

@@ -24,64 +24,64 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "BinaryWriter.h"
-#include "File.h"
+#include "ResourcePackage.h"
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-BinaryWriter::BinaryWriter(File& file) : m_file(file)
+CE_EXPORT int resource_package_load(lua_State* L)
 {
-}
+	LuaStack stack(L);
 
-//-----------------------------------------------------------------------------
-void BinaryWriter::write_byte(int8_t buffer)
-{
-	m_file.write(&buffer, sizeof(int8_t));
-}
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->load();
 
-//-----------------------------------------------------------------------------
-void BinaryWriter::write_int16(int16_t buffer)
-{
-	m_file.write(&buffer, sizeof(int16_t));
+	return 0;
 }
 
 //-----------------------------------------------------------------------------
-void BinaryWriter::write_uint16(uint16_t buffer)
+CE_EXPORT int resource_package_unload(lua_State* L)
 {
-	m_file.write(&buffer, sizeof(uint16_t));
-}
+	LuaStack stack(L);
 
-//-----------------------------------------------------------------------------
-void BinaryWriter::write_int32(int32_t buffer)
-{
-	m_file.write(&buffer, sizeof(int32_t));
-}
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->unload();
 
-//-----------------------------------------------------------------------------
-void BinaryWriter::write_uint32(uint32_t buffer)
-{
-	m_file.write(&buffer, sizeof(uint32_t));
+	return 0;
 }
 
 //-----------------------------------------------------------------------------
-void BinaryWriter::write_int64(int64_t buffer)
+CE_EXPORT int resource_package_flush(lua_State* L)
 {
-	m_file.write(&buffer, sizeof(int64_t));
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->flush();
+
+	return 0;
 }
 
 //-----------------------------------------------------------------------------
-void BinaryWriter::write_double(double buffer)
+CE_EXPORT int resource_package_has_loaded(lua_State* L)
 {
-	m_file.write(&buffer, sizeof(double));
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	stack.push_bool(package->has_loaded());
+
+	return 1;
 }
 
 //-----------------------------------------------------------------------------
-void BinaryWriter::write_float(float buffer)
+void load_resource_package(LuaEnvironment& env)
 {
-	m_file.write(&buffer, sizeof(float));
+	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
-

+ 42 - 160
engine/lua/LuaStack.cpp

@@ -30,189 +30,56 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Vec3.h"
 #include "Mat4.h"
 #include "Quat.h"
-#include "Unit.h"
 
 namespace crown
 {
 
-static const int32_t 	LUA_VEC2_BUFFER_SIZE = 4096;
-static Vec2 			vec2_buffer[LUA_VEC2_BUFFER_SIZE];
-static uint32_t 		vec2_used = 0;
+static const uint32_t 	LUA_VEC2_BUFFER_SIZE = 4096;
+static Vec2 			g_vec2_buffer[LUA_VEC2_BUFFER_SIZE];
+static uint32_t 		g_vec2_used = 0;
 
-static const int32_t 	LUA_VEC3_BUFFER_SIZE = 4096;
-static Vec3 			vec3_buffer[LUA_VEC3_BUFFER_SIZE];
-static uint32_t 		vec3_used = 0;
+static const uint32_t 	LUA_VEC3_BUFFER_SIZE = 4096;
+static Vec3 			g_vec3_buffer[LUA_VEC3_BUFFER_SIZE];
+static uint32_t 		g_vec3_used = 0;
 
-static const int32_t 	LUA_MAT4_BUFFER_SIZE = 4096;
-static Mat4 			mat4_buffer[LUA_MAT4_BUFFER_SIZE];
-static uint32_t 		mat4_used = 0;
+static const uint32_t 	LUA_MAT4_BUFFER_SIZE = 4096;
+static Mat4 			g_mat4_buffer[LUA_MAT4_BUFFER_SIZE];
+static uint32_t 		g_mat4_used = 0;
 
-static const int32_t 	LUA_QUAT_BUFFER_SIZE = 4096;
-static Quat 			quat_buffer[LUA_QUAT_BUFFER_SIZE];
-static uint32_t 		quat_used = 0;
+static const uint32_t 	LUA_QUAT_BUFFER_SIZE = 4096;
+static Quat 			g_quat_buffer[LUA_QUAT_BUFFER_SIZE];
+static uint32_t 		g_quat_used = 0;
 
 //-----------------------------------------------------------------------------
 static Vec2* next_vec2(const Vec2& v)
 {
-	CE_ASSERT(vec2_used < LUA_VEC2_BUFFER_SIZE, "Maximum number of Vec2 reached");
+	CE_ASSERT(g_vec2_used < LUA_VEC2_BUFFER_SIZE, "Maximum number of Vec2 reached");
 
-	return &(vec2_buffer[vec2_used++] = v);
+	return &(g_vec2_buffer[g_vec2_used++] = v);
 }
 
 //-----------------------------------------------------------------------------
 static Vec3* next_vec3(const Vec3& v)
 {
-	CE_ASSERT(vec3_used < LUA_VEC3_BUFFER_SIZE, "Maximum number of Vec3 reached");
+	CE_ASSERT(g_vec3_used < LUA_VEC3_BUFFER_SIZE, "Maximum number of Vec3 reached");
 
-	return &(vec3_buffer[vec3_used++] = v);
+	return &(g_vec3_buffer[g_vec3_used++] = v);
 }
 
 //-----------------------------------------------------------------------------
 static Mat4* next_mat4(const Mat4& m)
 {
-	CE_ASSERT(mat4_used < LUA_MAT4_BUFFER_SIZE, "Maximum number of Mat4 reached");
+	CE_ASSERT(g_mat4_used < LUA_MAT4_BUFFER_SIZE, "Maximum number of Mat4 reached");
 
-	return &(mat4_buffer[mat4_used++] = m);
+	return &(g_mat4_buffer[g_mat4_used++] = m);
 }
 
 //-----------------------------------------------------------------------------
 static Quat* next_quat(const Quat& q)
 {
-	CE_ASSERT(quat_used < LUA_QUAT_BUFFER_SIZE, "Maximum number of Quat reached");
+	CE_ASSERT(g_quat_used < LUA_QUAT_BUFFER_SIZE, "Maximum number of Quat reached");
 
-	return &(quat_buffer[quat_used++] = q);
-}
-
-//-----------------------------------------------------------------------------	
-LuaStack::LuaStack(lua_State* L)
-{
-	m_state = L;
-}
-
-//-----------------------------------------------------------------------------
-lua_State* LuaStack::state()
-{
-	return m_state;
-}
-
-//-----------------------------------------------------------------------------
-int32_t LuaStack::num_args()
-{
-	return lua_gettop(m_state);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_bool(bool value)
-{
-	lua_pushboolean(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_int32(int32_t value)
-{
-	lua_pushinteger(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_uint32(uint32_t value)
-{
-	lua_pushinteger(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_int64(int64_t value)
-{
-	lua_pushinteger(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_uint64(uint64_t value)
-{
-	lua_pushinteger(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_float(float value)
-{
-	lua_pushnumber(m_state, value);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_string(const char* s)
-{
-	lua_pushstring(m_state, s);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_literal(const char* s, size_t len)
-{
-	lua_pushlstring(m_state, s, len);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_lightdata(void* data)
-{
-	lua_pushlightuserdata(m_state, data);
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_vec2(const Vec2& v)
-{
-	lua_pushlightuserdata(m_state, next_vec2(v));
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_vec3(const Vec3& v)
-{
-	lua_pushlightuserdata(m_state, next_vec3(v));
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_mat4(const Mat4& m)
-{
-	lua_pushlightuserdata(m_state, next_mat4(m));
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_quat(const Quat& q)
-{
-	lua_pushlightuserdata(m_state, next_quat(q));
-}
-
-//-----------------------------------------------------------------------------
-void LuaStack::push_unit(Unit* unit)
-{
-	lua_pushlightuserdata(m_state, unit);
-}
-
-//-----------------------------------------------------------------------------
-bool LuaStack::get_bool(int32_t index)
-{
-	return (bool) luaL_checkinteger(m_state, index);
-}
-
-//-----------------------------------------------------------------------------
-int32_t LuaStack::get_int(int32_t index)
-{
-	return luaL_checkinteger(m_state, index);
-}
-
-//-----------------------------------------------------------------------------
-float LuaStack::get_float(int32_t index)
-{
-	return luaL_checknumber(m_state, index);
-}
-
-//-----------------------------------------------------------------------------
-const char* LuaStack::get_string(int32_t index)
-{
-	return luaL_checkstring(m_state, index);
-}
-
-//-----------------------------------------------------------------------------
-void* LuaStack::get_lightdata(int32_t index)
-{
-	return lua_touserdata(m_state, index);	
+	return &(g_quat_buffer[g_quat_used++] = q);
 }
 
 //-----------------------------------------------------------------------------
@@ -220,7 +87,7 @@ Vec2& LuaStack::get_vec2(int32_t index)
 {
 	void* v = lua_touserdata(m_state, index);
 
-	if (v < &vec2_buffer[0] || v > &vec2_buffer[LUA_VEC2_BUFFER_SIZE-1])
+	if (v < &g_vec2_buffer[0] || v > &g_vec2_buffer[LUA_VEC2_BUFFER_SIZE-1])
 	{
 		luaL_typerror(m_state, index, "Vec2");
 	}
@@ -233,7 +100,7 @@ Vec3& LuaStack::get_vec3(int32_t index)
 {
 	void* v = lua_touserdata(m_state, index);
 
-	if (v < &vec3_buffer[0] || v > &vec3_buffer[LUA_VEC3_BUFFER_SIZE-1])
+	if (v < &g_vec3_buffer[0] || v > &g_vec3_buffer[LUA_VEC3_BUFFER_SIZE-1])
 	{
 		luaL_typerror(m_state, index, "Vec3");
 	}
@@ -246,7 +113,7 @@ Mat4& LuaStack::get_mat4(int32_t index)
 {
 	void* m = lua_touserdata(m_state, index);
 
-	if (m < &mat4_buffer[0] || m > &mat4_buffer[LUA_MAT4_BUFFER_SIZE-1])
+	if (m < &g_mat4_buffer[0] || m > &g_mat4_buffer[LUA_MAT4_BUFFER_SIZE-1])
 	{
 		luaL_typerror(m_state, index, "Mat4");
 	}
@@ -259,7 +126,7 @@ Quat& LuaStack::get_quat(int32_t index)
 {
 	void* q = lua_touserdata(m_state, index);
 
-	if (q < &quat_buffer[0] || q > &quat_buffer[LUA_QUAT_BUFFER_SIZE-1])
+	if (q < &g_quat_buffer[0] || q > &g_quat_buffer[LUA_QUAT_BUFFER_SIZE-1])
 	{
 		luaL_typerror(m_state, index, "Quat");
 	}
@@ -267,12 +134,27 @@ Quat& LuaStack::get_quat(int32_t index)
 	return *(Quat*)q;
 }
 
+void LuaStack::push_vec2(const Vec2& v)
+{
+	lua_pushlightuserdata(m_state, next_vec2(v));
+}
+
+//-----------------------------------------------------------------------------
+void LuaStack::push_vec3(const Vec3& v)
+{
+	lua_pushlightuserdata(m_state, next_vec3(v));
+}
+
 //-----------------------------------------------------------------------------
-Unit* LuaStack::get_unit(int32_t index)
+void LuaStack::push_mat4(const Mat4& m)
 {
-	Unit* u = (Unit*)lua_touserdata(m_state, index);
+	lua_pushlightuserdata(m_state, next_mat4(m));
+}
 
-	return u;
+//-----------------------------------------------------------------------------
+void LuaStack::push_quat(const Quat& q)
+{
+	lua_pushlightuserdata(m_state, next_quat(q));
 }
 
 } // namespace crown

+ 121 - 34
engine/lua/LuaStack.h

@@ -28,6 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "lua.hpp"
 #include "Types.h"
+#include "Unit.h"
 
 namespace crown
 {
@@ -42,48 +43,134 @@ class LuaStack
 {
 public:
 
-							LuaStack(lua_State* L);
+	//-----------------------------------------------------------------------------	
+	LuaStack(lua_State* L)
+		: m_state(L)
+	{
+	}
 
-	lua_State*				state();
+	//-----------------------------------------------------------------------------
+	lua_State* state()
+	{
+		return m_state;
+	}
 
 	/// Returns the number of elements in the stack.
 	/// When called inside a function, it can be used to count
 	/// the number of arguments passed to the function itself.
-	int32_t					num_args();
-
-	void					push_bool(bool value);
-	void					push_int32(int32_t value);
-	void					push_uint32(uint32_t value);
-	void					push_int64(int64_t value);
-	void					push_uint64(uint64_t value);
-	void 					push_float(float value);
-	void 					push_string(const char* s);
-	void					push_literal(const char* s, size_t len);
-	void					push_lightdata(void* data);
-
-	void					push_vec2(const Vec2& v);
-	void					push_vec3(const Vec3& v);
-	void					push_mat4(const Mat4& m);
-	void					push_quat(const Quat& q);
-
-	void					push_unit(Unit* unit);
-
-	bool 					get_bool(int32_t index);
-	int32_t					get_int(int32_t index);
-	float 					get_float(int32_t index);
-	const char*				get_string(int32_t index);
-	void*					get_lightdata(int32_t index);
-
-	Vec2&					get_vec2(int32_t index);
-	Vec3&					get_vec3(int32_t index);
-	Mat4&					get_mat4(int32_t index);
-	Quat&					get_quat(int32_t index);
-
-	Unit*					get_unit(int32_t index);
+	int32_t num_args()
+	{
+		return lua_gettop(m_state);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_bool(bool value)
+	{
+		lua_pushboolean(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_int32(int32_t value)
+	{
+		lua_pushinteger(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_uint32(uint32_t value)
+	{
+		lua_pushinteger(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_int64(int64_t value)
+	{
+		lua_pushinteger(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_uint64(uint64_t value)
+	{
+		lua_pushinteger(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_float(float value)
+	{
+		lua_pushnumber(m_state, value);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_string(const char* s)
+	{
+		lua_pushstring(m_state, s);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_literal(const char* s, size_t len)
+	{
+		lua_pushlstring(m_state, s, len);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_lightdata(void* data)
+	{
+		lua_pushlightuserdata(m_state, data);
+	}
+
+	//-----------------------------------------------------------------------------
+	bool get_bool(int32_t index)
+	{
+		return (bool) lua_toboolean(m_state, index);
+	}
+
+	//-----------------------------------------------------------------------------
+	int32_t get_int(int32_t index)
+	{
+		return luaL_checkinteger(m_state, index);
+	}
+
+	//-----------------------------------------------------------------------------
+	float get_float(int32_t index)
+	{
+		return luaL_checknumber(m_state, index);
+	}
+
+	//-----------------------------------------------------------------------------
+	const char* get_string(int32_t index)
+	{
+		return luaL_checkstring(m_state, index);
+	}
+
+	//-----------------------------------------------------------------------------
+	void* get_lightdata(int32_t index)
+	{
+		return lua_touserdata(m_state, index);	
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_unit(Unit* unit)
+	{
+		lua_pushlightuserdata(m_state, unit);
+	}
+
+	//-----------------------------------------------------------------------------
+	Unit* get_unit(int32_t index)
+	{
+		return (Unit*) lua_touserdata(m_state, index);
+	}
+
+	Vec2& get_vec2(int32_t index);
+	Vec3& get_vec3(int32_t index);
+	Mat4& get_mat4(int32_t index);
+	Quat& get_quat(int32_t index);
+	void push_vec2(const Vec2& v);
+	void push_vec3(const Vec3& v);
+	void push_mat4(const Mat4& m);
+	void push_quat(const Quat& q);
 
 private:
 
-	lua_State* 				m_state;
+	lua_State* m_state;
 };
 
 } // namespace crown

+ 14 - 28
engine/lua/LuaWindow.cpp

@@ -24,8 +24,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "Device.h"
 #include "OsWindow.h"
+#include "Device.h"
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
 
@@ -109,49 +109,35 @@ CE_EXPORT int window_move(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_show_cursor(lua_State* L)
+CE_EXPORT int window_minimize(lua_State* /*L*/)
 {
-	LuaStack stack(L);
-
-	device()->window()->show_cursor();
-
+	device()->window()->minimize();
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_hide_cursor(lua_State* L)
+CE_EXPORT int window_restore(lua_State* /*L*/)
 {
-	LuaStack stack(L);
-
-	device()->window()->hide_cursor();
-
+	device()->window()->restore();
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_get_cursor_xy(lua_State* L)
+CE_EXPORT int window_is_resizable(lua_State* L)
 {
 	LuaStack stack(L);
 
-	int32_t x, y;
+	stack.push_bool(device()->window()->is_resizable());
 
-	device()->window()->get_cursor_xy(x, y);
-
-	stack.push_int32(x);
-	stack.push_int32(y);
-
-	return 2;
+	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_set_cursor_xy(lua_State* L)
+CE_EXPORT int window_set_resizable(lua_State* L)
 {
 	LuaStack stack(L);
 
-	const int32_t x = stack.get_int(1);
-	const int32_t y = stack.get_int(2);
-
-	device()->window()->set_cursor_xy(x, y);
+	device()->window()->set_resizable(stack.get_bool(1));
 
 	return 0;
 }
@@ -189,10 +175,10 @@ void load_window(LuaEnvironment& env)
 	env.load_module_function("Window", "get_position",	window_get_position);
 	env.load_module_function("Window", "resize",		window_resize);
 	env.load_module_function("Window", "move",			window_move);
-	env.load_module_function("Window", "show_cursor",	window_show_cursor);
-	env.load_module_function("Window", "hide_cursor",	window_hide_cursor);
-	env.load_module_function("Window", "get_cursor_xy",	window_get_cursor_xy);
-	env.load_module_function("Window", "set_cursor_xy",	window_set_cursor_xy);
+	env.load_module_function("Window", "minimize",		window_minimize);
+	env.load_module_function("Window", "restore",		window_restore);
+	env.load_module_function("Window", "is_resizable",	window_is_resizable);
+	env.load_module_function("Window", "set_resizable",	window_set_resizable);
 	env.load_module_function("Window", "title",			window_title);
 	env.load_module_function("Window", "set_title",		window_set_title);
 }

+ 12 - 35
engine/os/NetAddress.h

@@ -31,34 +31,28 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 /// OS level network address.
 class NetAddress
 {
 public:
 
-	/// Initializes the address to 127.0.0.1 and port to 1000.
+	/// Initializes the address to 127.0.0.1
 					NetAddress();
 
 	/// Initializes the address from IP address (as single elemets)
-	/// and the port number.
-					NetAddress(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port);
+					NetAddress(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
 
 	
 	/// Returns the IP address as packed 32-bit integer.
 	uint32_t		address() const;
 
-	/// Returns the port number bind to the address.
-	uint16_t		port() const;
+	/// Sets both the IP address (packed 32-bit integer)
+	void			set(uint32_t address);
 
-	/// Sets both the IP address (packed 32-bit integer) and the port number.
-	void			set(uint32_t address, uint16_t port);
+	/// Sets both the IP address (as single elements)
+	void			set(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
 
-	/// Sets both the IP address (as single elements) and the port number.
-	void			set(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port);
-	
 	bool			operator==(const NetAddress& addr) const;
 	NetAddress&		operator=(const NetAddress& addr);
 	
@@ -67,12 +61,10 @@ public:
 public:
 
 	uint8_t 		m_address[4];
-	uint16_t 		m_port;
 };
 
 //-----------------------------------------------------------------------------
-inline NetAddress::NetAddress() :
-	m_port(1000)
+inline NetAddress::NetAddress()
 {
 	m_address[0] = 127;
 	m_address[1] = 0;
@@ -81,8 +73,7 @@ inline NetAddress::NetAddress() :
 }
 
 //-----------------------------------------------------------------------------
-inline NetAddress::NetAddress(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) :
-	m_port(port)
+inline NetAddress::NetAddress(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
 {
 	m_address[0] = a;
 	m_address[1] = b;
@@ -99,31 +90,21 @@ inline uint32_t NetAddress::address() const
 }
 
 //-----------------------------------------------------------------------------
-inline uint16_t NetAddress::port() const
-{
-	return m_port;
-}
-
-//-----------------------------------------------------------------------------
-inline void NetAddress::set(uint32_t address, uint16_t port)
+inline void NetAddress::set(uint32_t address)
 {
 	m_address[0] = address >> 24;
 	m_address[1] = address >> 16;
 	m_address[2] = address >> 8;
 	m_address[3] = address;
-
-	m_port = port;
 }
 
 //-----------------------------------------------------------------------------
-inline void NetAddress::set(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port)
+inline void NetAddress::set(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
 {
 	m_address[0] = a;
 	m_address[1] = b;
 	m_address[2] = c;
 	m_address[3] = d;
-	
-	m_port = port;
 }
 
 //-----------------------------------------------------------------------------
@@ -132,8 +113,7 @@ inline bool NetAddress::operator==(const NetAddress& addr) const
 	return m_address[0] == addr.m_address[0] &&
 		   m_address[1] == addr.m_address[1] &&
 		   m_address[2] == addr.m_address[2] &&
-		   m_address[3] == addr.m_address[3] &&
-		   m_port == addr.m_port;
+		   m_address[3] == addr.m_address[3];
 }
 
 //-----------------------------------------------------------------------------
@@ -144,16 +124,13 @@ inline NetAddress& NetAddress::operator=(const NetAddress& addr)
 	m_address[2] = addr.m_address[2];
 	m_address[3] = addr.m_address[3];
 	
-	m_port = addr.m_port;
-	
 	return *this;
 }
 
 //-----------------------------------------------------------------------------
 inline void NetAddress::print() const
 {
-	os::printf("NetAddress: %i.%i.%i.%i:%i\n", m_address[0], m_address[1], m_address[2], m_address[3], m_port);
+	os::printf("NetAddress: %i.%i.%i.%i\n", m_address[0], m_address[1], m_address[2], m_address[3]);
 }
 
-} // namespace os
 } // namespace crown

+ 0 - 73
engine/os/OS.cpp

@@ -1,73 +0,0 @@
-/*
-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 "OS.h"
-
-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;
-
-//-----------------------------------------------------------------------------
-void push_event(OsEventType type, OsEventParameter data_a, OsEventParameter data_b, OsEventParameter data_c, OsEventParameter data_d)
-{
-	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;
-}
-
-//-----------------------------------------------------------------------------
-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
-

+ 57 - 54
engine/os/OS.h

@@ -30,17 +30,17 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Config.h"
 #include "Types.h"
+#include "Vector.h"
+#include "DynamicString.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-#ifdef LINUX
+#if defined(LINUX)
 	const size_t	MAX_PATH_LENGTH = 1024;
 	const char		PATH_SEPARATOR = '/';
-#endif
-
-#ifdef WINDOWS
+#elif defined(WINDOWS)
 	const size_t	MAX_PATH_LENGTH = 1024;
 	const char		PATH_SEPARATOR = '\\';
 
@@ -48,6 +48,11 @@ namespace crown
 
 	#undef MK_SHIFT
 	#undef MK_ALT
+#elif defined(ANDROID)
+	const size_t	MAX_PATH_LENGTH = 1024;
+	const char		PATH_SEPARATOR = '/';
+#else
+	#error "Oops, invalid platform!"
 #endif
 
 namespace os
@@ -55,7 +60,7 @@ namespace os
 //-----------------------------------------------------------------------------
 // Print and log functions
 //-----------------------------------------------------------------------------
-void			printf(const char* string, ...);				//!< Printf wrapper
+void CE_EXPORT	printf(const char* string, ...);				//!< Printf wrapper
 void			vprintf(const char* string, va_list arg);		//!< VPrintf wrapper
 
 void			log_debug(const char* string, va_list arg);		//!< Print debug message
@@ -66,30 +71,55 @@ void			log_info(const char* string, va_list arg);		//!< Print info message
 //-----------------------------------------------------------------------------
 // Paths
 //-----------------------------------------------------------------------------
-bool			is_root_path(const char* path);
-bool			is_absolute_path(const char* path);
+bool CE_EXPORT	is_root_path(const char* path);
+bool CE_EXPORT	is_absolute_path(const char* path);
 
 //-----------------------------------------------------------------------------
 // File management
 //-----------------------------------------------------------------------------
-bool			exists(const char* path);		//!< Returns whether the path is a file or directory on the disk
 
-bool			is_dir(const char* path);		//!< Returns whether the path is a directory. (May not resolve symlinks.)
-bool			is_reg(const char* path);		//!< Returns whether the path is a regular file. (May not resolve symlinks.)
+/// Returns whether the path is a file or directory on the disk
+bool			exists(const char* path);
+
+/// Returns whether the path is a directory. (May not resolve symlinks.)
+bool			is_directory(const char* path);
+
+/// Returns whether the path is a regular file. (May not resolve symlinks.)
+bool			is_file(const char* path);
+
+/// Creates a regular file. Returns true if success, false if not
+bool			create_file(const char* path);
+
+/// Deletes a regular file. Returns true if success, false if not
+bool			delete_file(const char* path);
+
+/// Creates a directory. Returns true if success, false if not
+bool			create_directory(const char* path);
+
+/// Deletes a directory. Returns true if success, false if not
+bool			delete_directory(const char* path);
+
+/// Returns the list of @a files in the given @a dir directory. Optionally walks into
+/// subdirectories whether @a recursive is true.
+/// @note
+/// Does not follow symbolic links.
+void			list_files(const char* path, Vector<DynamicString>& files);
 
-bool			mknod(const char* path);		//! Creates a regular file. Returns true if success, false if not
-bool			unlink(const char* path);		//! Deletes a regular file. Returns true if success, false if not
-bool			mkdir(const char* path);		//! Creates a directory. Returns true if success, false if not
-bool			rmdir(const char* path);		//! Deletes a directory. Returns true if success, false if not
+/// Returns os-dependent path from os-indipendent @a path
+const char*		normalize_path(const char* path);
 
 //-----------------------------------------------------------------------------
 // OS ambient variables
 //-----------------------------------------------------------------------------
-const char*		get_cwd();						//! Fills ret with the path of the current working directory. Returns true if success, false if not 
-const char*		get_home();						//! Fills ret with the path of the user home directory
-const char*		get_env(const char* env);		//! Returns the content of the 'env' environment variable or the empty string
 
-//bool			ls(const char* path, List<Str>& fileList);	//! Returns the list of filenames in a directory.
+/// Fills ret with the path of the current working directory. Returns true if success, false if not 
+const char*		get_cwd();
+
+/// Fills ret with the path of the user home directory
+const char*		get_home();
+
+/// Returns the content of the 'env' environment variable or the empty string
+const char*		get_env(const char* env);
 
 //-----------------------------------------------------------------------------
 // Render window and input management
@@ -112,47 +142,20 @@ void*			open_library(const char* path);
 void			close_library(void* library);
 void*			lookup_symbol(void* library, const char* name);
 
-} // namespace os
-
 //-----------------------------------------------------------------------------
-// Events
+// Process execution
 //-----------------------------------------------------------------------------
-enum OsEventType
-{
-	OSET_NONE				= 0,
 
-	OSET_KEY_PRESS			= 1,
-	OSET_KEY_RELEASE		= 2,
+/// Executes a process.
+/// @a args is an array of arguments where:
+/// @a args[0] is the path to the program executable,
+/// @a args[1, 2, ..., n-1] is a list of arguments to pass to the executable,
+/// @a args[n] is NULL.
+void			execute_process(const char* args[]);
 
-	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;
-};
+//-----------------------------------------------------------------------------
 
-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();
+} // namespace os
 
 } // namespace crown
 

+ 142 - 0
engine/os/OsEventQueue.h

@@ -0,0 +1,142 @@
+/*
+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 "Queue.h"
+#include "Mutex.h"
+#include "ProxyAllocator.h"
+#include "OsTypes.h"
+
+namespace crown
+{
+
+struct OsEventQueue
+{
+	//-----------------------------------------------------------------------------
+	OsEventQueue() 
+		: m_allocator("os-event-queue", default_allocator()), m_queue(m_allocator)
+	{
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_mouse_event(uint16_t x, uint16_t y)
+	{
+		OsEvent ev;
+		ev.type = OsEvent::MOUSE;
+		ev.mouse.type = OsMouseEvent::MOVE;
+		ev.mouse.x = x;
+		ev.mouse.y = y;
+
+		push_event(&ev);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_mouse_event(uint16_t x, uint16_t y, MouseButton::Enum b, bool pressed)
+	{
+		OsEvent ev;
+		ev.type = OsEvent::MOUSE;
+		ev.mouse.type = OsMouseEvent::BUTTON;
+		ev.mouse.x = x;
+		ev.mouse.y = y;
+		ev.mouse.button = b;
+		ev.mouse.pressed = pressed;
+
+		push_event(&ev);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_keyboard_event(uint32_t modifier, KeyboardButton::Enum b, bool pressed)
+	{
+		OsEvent ev;
+		ev.type = OsEvent::KEYBOARD;
+		ev.keyboard.button = b;
+		ev.keyboard.modifier = modifier;
+		ev.keyboard.pressed = pressed;
+
+		push_event(&ev);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_exit_event(int32_t code)
+	{
+		OsEvent ev;
+		ev.type = OsEvent::EXIT;
+		ev.exit.code = code;
+
+		push_event(&ev);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_metrics_event(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+	{
+		OsEvent ev;
+		ev.type = OsEvent::METRICS;
+		ev.metrics.x = x;
+		ev.metrics.y = y;
+		ev.metrics.width = width;
+		ev.metrics.height = height;
+
+		push_event(&ev);
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_event(OsEvent* ev)
+	{
+		CE_ASSERT_NOT_NULL(ev);
+
+		m_mutex.lock();
+		m_queue.push(ev, sizeof(OsEvent));
+		m_mutex.unlock();
+	}
+
+	//-----------------------------------------------------------------------------
+	void pop_event(OsEvent* ev)
+	{
+		CE_ASSERT_NOT_NULL(ev);
+
+		m_mutex.lock();
+		if (m_queue.size() > 0)
+		{
+			memcpy(ev, m_queue.begin(), sizeof(OsEvent));
+			m_queue.pop(sizeof(OsEvent));
+		}
+		else
+		{
+			ev->type = OsEvent::NONE;
+		}
+		m_mutex.unlock();
+	}
+
+private:
+
+	ProxyAllocator m_allocator;
+	Queue<OsEvent> m_queue;
+	Mutex m_mutex;
+};
+
+} // namespace crown

+ 74 - 30
engine/FPSSystem.h → engine/os/OsTypes.h

@@ -27,48 +27,92 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
-#include "Camera.h"
-#include "Vec2.h"
 #include "Mouse.h"
 #include "Keyboard.h"
-#include "Touch.h"
-#include "Accelerometer.h"
-#include "Renderer.h"
 
 namespace crown
 {
-/// TODO: set_view_by_cursor must be implemented through scripting
-class FPSSystem : public MouseListener, public KeyboardListener, public AccelerometerListener
-{
-public:
-
-					/// Constructor
-					FPSSystem(Camera* camera, float speed, float sensibility);
 
-	void 			set_camera(Camera* camera);
-	Camera*			camera();
-
-	void			update(float dt);
-	void			set_view_by_cursor();	
+struct OsMetricsEvent
+{
+	uint16_t x;
+	uint16_t y;
+	uint16_t width;
+	uint16_t height;
+};
 
-	virtual void 	key_pressed(const KeyboardEvent& event);
-	virtual void 	key_released(const KeyboardEvent& event);
-	virtual void 	accelerometer_changed(const AccelerometerEvent& event);
+struct OsExitEvent
+{
+	int32_t code;
+};
 
-private:
+/// Represents an event fired by mouse.
+struct OsMouseEvent
+{
+	enum Enum
+	{
+		BUTTON,
+		MOVE
+	};
+
+	OsMouseEvent::Enum type;
+	MouseButton::Enum button;
+	uint16_t x;
+	uint16_t y;
+	bool pressed;
+};
 
-	Camera*			m_camera;
+/// Represents an event fired by keyboard.
+struct OsKeyboardEvent
+{
+	KeyboardButton::Enum button;
+	uint32_t modifier;
+	bool pressed;
+};
 
-	float			m_camera_speed;
-	float			m_camera_sensibility;
+/// Represents an event fired by touch screen.
+struct OsTouchEvent
+{
+	uint8_t pointer_id;
+	uint16_t x;
+	uint16_t y;
+};
 
-	float 			m_angle_x;
-	float 			m_angle_y;
+/// Represents an event fired by accelerometer.
+struct OsAccelerometerEvent
+{
+	float x;
+	float y;
+	float z;
+};
 
-	bool			m_up_pressed	: 1;
-	bool			m_right_pressed	: 1;
-	bool			m_down_pressed	: 1;
-	bool			m_left_pressed	: 1;
+struct OsEvent
+{
+	/// Represents an event fired by the OS
+	enum Enum
+	{
+		NONE			= 0,
+
+		KEYBOARD		= 1,
+		MOUSE			= 2,
+		TOUCH			= 3,
+		ACCELEROMETER	= 4,
+
+		METRICS,
+		// Exit from program
+		EXIT
+	};
+
+	OsEvent::Enum type;
+	union
+	{
+		OsMetricsEvent metrics;
+		OsExitEvent exit;
+		OsMouseEvent mouse;
+		OsKeyboardEvent keyboard;
+		OsTouchEvent touch;
+		OsAccelerometerEvent accelerometer;
+	};
 };
 
 } // namespace crown

+ 88 - 8
engine/os/android/AndroidDevice.cpp

@@ -26,40 +26,120 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <jni.h>
 #include "Device.h"
+#include "Renderer.h"
+#include "SoundRenderer.h"
+#include "Log.h"
+#include "Allocator.h"
 
 namespace crown
 {
 
+class AndroidDevice : public Device
+{
+public:
+
+	int32_t run(int, char**)
+	{
+		// Do nothing, the game loop is java-side
+	}
+};
+
+static AndroidDevice* g_engine;
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initCrown(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	memory::init();
+	os::init_os();
+
+	g_engine = CE_NEW(default_allocator(), AndroidDevice);
+	set_device(g_engine);
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownCrown(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	CE_DELETE(default_allocator(), g_engine);
+	memory::shutdown();
+}
+
 //-----------------------------------------------------------------------------
-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", "--root-path", "/sdcard/crown-android-project", "--dev" };
+	device()->init();
+}
 
-	device()->init(4, (char**)argv);
+//-----------------------------------------------------------------------------
+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_shutdown(JNIEnv* env, jobject obj)
+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();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->renderer()->shutdown();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pauseSoundRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->sound_renderer()->pause();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_unpauseSoundRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->sound_renderer()->unpause();
+
+}
+
 } // namespace crown

+ 93 - 23
engine/os/android/AndroidOS.cpp

@@ -30,23 +30,25 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <cstdio>
 #include <cstdlib>
 #include <dirent.h>
+#include <dlfcn.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
 
 #include "OS.h"
 #include "Assert.h"
 #include "StringUtils.h"
+#include "OsTypes.h"
 
 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, ...)
@@ -128,7 +130,7 @@ bool exists(const char* path)
 }
 
 //-----------------------------------------------------------------------------
-bool is_dir(const char* path)
+bool is_directory(const char* path)
 {
 	struct stat info;
 	memset(&info, 0, sizeof(struct stat));
@@ -137,7 +139,7 @@ bool is_dir(const char* path)
 }
 
 //-----------------------------------------------------------------------------
-bool is_reg(const char* path)
+bool is_file(const char* path)
 {
 	struct stat info;
 	memset(&info, 0, sizeof(struct stat));
@@ -146,31 +148,82 @@ bool is_reg(const char* path)
 }
 
 //-----------------------------------------------------------------------------
-bool mknod(const char* path)
+bool create_file(const char* path)
 {
 	// Permission mask: rw-r--r--
 	return ::mknod(path, S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0) == 0;
 }
 
 //-----------------------------------------------------------------------------
-bool unlink(const char* path)
+bool delete_file(const char* path)
 {
 	return (::unlink(path) == 0);
 }
 
 //-----------------------------------------------------------------------------
-bool mkdir(const char* path)
+bool create_directory(const char* path)
 {
 	// rwxr-xr-x permission mask
 	return (::mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0);
 }
 
 //-----------------------------------------------------------------------------
-bool rmdir(const char* path)
+bool delete_directory(const char* path)
 {
 	return (::rmdir(path) == 0);
 }
 
+//-----------------------------------------------------------------------------
+void list_files(const char* path, Vector<DynamicString>& files)
+{
+	DIR *dir;
+	struct dirent *entry;
+
+	if (!(dir = opendir(path)))
+	{
+		return;
+	}
+
+	while ((entry = readdir(dir)))
+	{
+		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+		{
+			continue;
+		}
+
+		DynamicString filename(default_allocator());
+
+		filename = entry->d_name;
+		files.push_back(filename);
+	}
+
+	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()
 {
@@ -236,32 +289,49 @@ uint64_t microseconds()
 	return (tmp.tv_sec - base_time.tv_sec) * 1000000 + (tmp.tv_nsec - base_time.tv_nsec) / 1000;
 }
 
+//-----------------------------------------------------------------------------
+void execute_process(const char* args[])
+{
+	pid_t pid = fork();
+	CE_ASSERT(pid != -1, "Unable to fork");
+
+	if (pid)
+	{
+		int32_t dummy;
+		wait(&dummy);
+	}
+	else
+	{
+		int res = execv(args[0], (char* const*)args);
+		CE_ASSERT(res != -1, "Unable to exec '%s'. errno %d", args[0], res);
+		exit(EXIT_SUCCESS);
+	}
+}
+
 } // 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

+ 57 - 48
engine/os/android/OsFile2.cpp → engine/os/android/ApkFile.cpp

@@ -25,36 +25,36 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include <android/asset_manager_jni.h>
-
+#include "ApkFile.h"
 #include "Assert.h"
-#include "OS.h"
-#include "OsFile.h"
-#include "AndroidOS.h"
-
-namespace crown
-{
 
-static AAssetManager*	g_android_asset_manager = NULL;
+static AAssetManager* g_android_asset_manager = NULL;
 
 //-----------------------------------------------------------------------------
-OsFile::OsFile(const char* path, FileOpenMode mode)
+AAssetManager* get_android_asset_manager()
 {
-	// Android assets are always read-only
-	(void) mode;
-	m_mode = FOM_READ;
-	m_asset = AAssetManager_open(get_android_asset_manager(), path, AASSET_MODE_RANDOM);
+	return g_android_asset_manager;
+}
 
-	CE_ASSERT(m_asset != NULL, "Unable to open file: %s", path);
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initAssetManager(JNIEnv* env, jobject obj, jobject assetManager)
+{
+	g_android_asset_manager = AAssetManager_fromJava(env, assetManager);
 }
 
+namespace crown
+{
+
 //-----------------------------------------------------------------------------
-OsFile::~OsFile()
+ApkFile::ApkFile(const char* path)
+	: File(FOM_READ), m_asset(NULL)
 {
-	close();
+	m_asset = AAssetManager_open(get_android_asset_manager(), path, AASSET_MODE_RANDOM);
+	CE_ASSERT(m_asset != NULL, "Unable to open file: %s", path);
 }
 
 //-----------------------------------------------------------------------------
-void OsFile::close()
+ApkFile::~ApkFile()
 {
 	if (m_asset != NULL)
 	{
@@ -64,85 +64,94 @@ void OsFile::close()
 }
 
 //-----------------------------------------------------------------------------
-bool OsFile::is_open() const
+void ApkFile::seek(size_t position)
 {
-	return m_asset != NULL;
+	off_t seek_result = AAsset_seek(m_asset, (off_t)position, SEEK_SET);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
 }
 
 //-----------------------------------------------------------------------------
-FileOpenMode OsFile::mode() const
+void ApkFile::seek_to_end()
 {
-	return m_mode;
+	off_t seek_result = AAsset_seek(m_asset, 0, SEEK_END);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek to end");
 }
 
 //-----------------------------------------------------------------------------
-size_t OsFile::size() const
+void ApkFile::skip(size_t bytes)
 {
-	return AAsset_getLength(m_asset);
+	off_t seek_result = AAsset_seek(m_asset, (off_t) bytes, SEEK_CUR);
+	CE_ASSERT(seek_result != (off_t) -1, "Failed to skip");
 }
 
 //-----------------------------------------------------------------------------
-size_t OsFile::read(void* data, size_t size)
+void ApkFile::read(void* buffer, size_t size)
 {
-	CE_ASSERT(data != NULL, "Data must be != NULL");
+	CE_ASSERT_NOT_NULL(buffer);
 
-	return (size_t)AAsset_read(m_asset, data, size);
+	size_t bytes_read = (size_t) AAsset_read(m_asset, buffer, size);
+	CE_ASSERT(bytes_read == size, "Failed to read from file: requested: %lu, read: %lu", size, bytes_read);
 }
 
 //-----------------------------------------------------------------------------
-size_t OsFile::write(const void* data, size_t size)
+void ApkFile::write(const void* /*buffer*/, size_t /*size*/)
 {
-	CE_ASSERT(data != NULL, "Data must be != NULL");
+	CE_ASSERT(false, "Attempt to write to android assets folder!");
+}
 
-	os::printf("Android asset directory is read-only!");
+//-----------------------------------------------------------------------------
+bool ApkFile::copy_to(File& /*file*/, size_t /*size = 0*/)
+{
+	CE_ASSERT(false, "Not implemented yet :(");
+	return false;
+}
 
-	return 0;
+//-----------------------------------------------------------------------------
+void ApkFile::flush()
+{
+	// Not needed
 }
 
 //-----------------------------------------------------------------------------
-void OsFile::seek(size_t position)
+bool ApkFile::is_valid() const
 {
-	off_t seek_result = AAsset_seek(m_asset, (off_t)position, SEEK_SET);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return m_asset != NULL;
 }
 
 //-----------------------------------------------------------------------------
-void OsFile::seek_to_end()
+bool ApkFile::end_of_file() const
 {
-	off_t seek_result = AAsset_seek(m_asset, 0, SEEK_END);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return AAsset_getRemainingLength(m_asset) == 0;
 }
 
 //-----------------------------------------------------------------------------
-void OsFile::skip(size_t bytes)
+size_t ApkFile::size() const
 {
-	off_t seek_result = AAsset_seek(m_asset, (off_t) bytes, SEEK_CUR);
-	CE_ASSERT(seek_result != (off_t) -1, "Failed to seek");
+	return AAsset_getLength(m_asset);
 }
 
 //-----------------------------------------------------------------------------
-size_t OsFile::position() const
+size_t ApkFile::position() const
 {
 	return (size_t) (AAsset_getLength(m_asset) - AAsset_getRemainingLength(m_asset));
 }
 
 //-----------------------------------------------------------------------------
-bool OsFile::eof() const
+bool ApkFile::can_read() const
 {
-	return AAsset_getRemainingLength(m_asset) == 0;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
-AAssetManager* get_android_asset_manager()
+bool ApkFile::can_write() const
 {
-	return g_android_asset_manager;
+	return false;
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initAssetManager(JNIEnv* env, jobject obj, jobject assetManager)
+bool ApkFile::can_seek() const
 {
-	g_android_asset_manager = AAssetManager_fromJava(env, assetManager);
+	return true;
 }
 
-} // namespace crown
-
+} // namespace crown

+ 40 - 31
engine/os/posix/TCPSocket.h → engine/os/android/ApkFile.h

@@ -26,55 +26,64 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
+#include "File.h"
 
 namespace crown
 {
-namespace os
-{
-
-class NetAddress;
 
-/// OS level TCP socket.
-class TCPSocket
+class ApkFile : public File 
 {
 public:
 
-				TCPSocket();
-				~TCPSocket();
+	/// Opens the given @a filename.
+				ApkFile(const char* filename);
+				~ApkFile();
+
+	/// @copydoc File::seek()
+	void		seek(size_t position);
+
+	/// @copydoc File::seek_to_end()
+	void		seek_to_end();
+
+	/// @copydoc File::skip()
+	void		skip(size_t bytes);
+
+	/// @copydoc File::read()
+	void		read(void* buffer, size_t size);
+
+	/// @copydoc File::write()
+	void		write(const void* buffer, size_t size);
+
+	/// @copydoc File::copy_to()
+	bool		copy_to(File& file, size_t size = 0);
 
-	// Open connection (server side)
-	bool 		open(uint16_t port);
+	/// @copydoc File::flush()
+	void		flush();
 
-	// Connect (client side)
-	bool		connect(const NetAddress& destination);
+	/// @copydoc File::is_valid()
+	bool		is_valid() const;
 
-	// Close connection
-	void		close();
+	/// @copydoc File::end_of_file()
+	bool		end_of_file() const;
 
-	// Send data through socket
-	bool 		send(const void* data, size_t size);
+	/// @copydoc File::size()
+	size_t		size() const;
 
-	// Receive data through socket
-	size_t		receive(void* data, size_t size);
+	/// @copydoc File::position()
+	size_t		position() const;
 
-	// Is connection open?
-	bool 		is_open();
+	/// @copydoc File::can_read()
+	bool		can_read() const;
 
-	// Getter method for socket descriptor
-	int 		socket_id();
+	/// @copydoc File::can_write()
+	bool		can_write() const;
 
-	// Getter method for active socket descriptor
-	int 		active_socket_id();
+	/// @copydoc File::can_seek()
+	bool		can_seek() const;
 
 private:
-	
-	// Generated by ::socket
-	int 		m_socket;
 
-	// Generated by ::accept
-	int 		m_active_socket;
+	AAsset*		m_asset;
 };
 
-} // namespace os
 } // namespace crown

+ 44 - 49
engine/os/posix/Thread.cpp → engine/os/android/ApkFilesystem.cpp

@@ -24,102 +24,97 @@ 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 <android/asset_manager.h>
+#include "ApkFilesystem.h"
+#include "TempAllocator.h"
+#include "ApkFile.h"
+#include "OS.h"
 
-#include "Thread.h"
-#include "Assert.h"
+extern AAssetManager* get_android_asset_manager();
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-Thread::Thread(const char* name) :
-	m_name(name),
-	m_is_running(false),
-	m_is_terminating(false),
-	m_thread(0)
+ApkFilesystem::ApkFilesystem()
 {
-	memset(&m_thread, 0, sizeof(pthread_t));
 }
 
 //-----------------------------------------------------------------------------
-Thread::~Thread()
+File* ApkFilesystem::open(const char* path, FileOpenMode mode)
 {
+	CE_ASSERT_NOT_NULL(path);
+	CE_ASSERT(mode == FOM_READ, "Cannot open for writing in Android assets folder");
+
+	return CE_NEW(default_allocator(), ApkFile)(path);
 }
 
 //-----------------------------------------------------------------------------
-const char* Thread::name() const
+void ApkFilesystem::close(File* file)
 {
-	return m_name;
+	CE_ASSERT_NOT_NULL(file);
+	CE_DELETE(default_allocator(), file);
 }
 
 //-----------------------------------------------------------------------------
-void Thread::start()
+bool ApkFilesystem::is_directory(const char* path)
 {
-	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;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
-bool Thread::is_running() const
+bool ApkFilesystem::is_file(const char* path)
 {
-	return m_is_running;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
-bool Thread::is_terminating() const
+void ApkFilesystem::create_directory(const char* /*path*/)
 {
-	return m_is_terminating;
+	CE_ASSERT(false, "Attempt to create directory in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-void Thread::stop()
+void ApkFilesystem::delete_directory(const char* /*path*/)
 {
-	m_is_terminating = true;
+	CE_ASSERT(false, "Attempt to delete directory in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-int32_t Thread::run()
+void ApkFilesystem::create_file(const char* /*path*/)
 {
-	return 0;
+	CE_ASSERT(false, "Attempt to create file in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-void* Thread::background_proc(void* thiz)
+void ApkFilesystem::delete_file(const char* /*path*/)
 {
-	Thread* thread = ((Thread*) thiz);
-
-	thread->run();
-
-	thread->m_is_running = false;
-
-	return NULL;
+	CE_ASSERT(false, "Attempt to delete file in Android assets folder");
 }
 
 //-----------------------------------------------------------------------------
-void Thread::join()
+void ApkFilesystem::list_files(const char* path, Vector<DynamicString>& files)
 {
-	pthread_join(m_thread, NULL);
+	CE_ASSERT_NOT_NULL(path);
+
+	AAssetDir* root_dir = AAssetManager_openDir(get_android_asset_manager(), path);
+	CE_ASSERT(root_dir != NULL, "Failed to open Android assets folder");
+
+	const char* filename = NULL;
+	while ((filename = AAssetDir_getNextFileName(root_dir)) != NULL)
+	{
+		DynamicString name(default_allocator());
+		name = filename;
+		files.push_back(name);
+	}
+
+	AAssetDir_close(root_dir);
 }
 
 //-----------------------------------------------------------------------------
-void Thread::detach()
+void ApkFilesystem::get_absolute_path(const char* path, DynamicString& os_path)
 {
-	pthread_detach(m_thread);
+	os_path = path;
 }
 
 } // namespace crown

+ 78 - 0
engine/os/android/ApkFilesystem.h

@@ -0,0 +1,78 @@
+/*
+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 "Filesystem.h"
+
+namespace crown
+{
+
+/// Access files on Android's assets folder.
+/// The assets folder is read-only and all the paths are relative.
+class ApkFilesystem : public Filesystem
+{
+public:
+
+	ApkFilesystem();
+
+	/// @copydoc Filesystem::open()
+	/// @note
+	/// @a mode can only be FOM_READ
+	File* open(const char* rel_path, FileOpenMode mode);
+
+	/// @copydoc Filesystem::close()
+	void close(File* file);
+
+	/// Returns always false under Android.
+	bool is_directory(const char* path);
+
+	/// Returns always false under Android.
+	bool is_file(const char* path);
+
+	/// Stub method, assets folder is read-only.
+	void create_directory(const char* path);
+
+	/// Stub method, assets folder is read-only.
+	void delete_directory(const char* path);
+
+	/// Stub method, assets folder is read-only.
+	void create_file(const char* path);
+
+	/// Stub method, assets folder is read-only.
+	void delete_file(const char* path);
+
+	/// @copydoc Filesystem::list_files().
+	void list_files(const char* path, Vector<DynamicString>& files);
+
+	/// Returns the absolute path of the given @a path.
+	/// @note
+	/// Assets folder has no concept of "absolute path", all paths are
+	/// relative to the assets folder itself, so, all paths are returned unchanged.
+	void get_absolute_path(const char* path, DynamicString& os_path);
+};
+
+} // namespace crown

Some files were not shown because too many files changed in this diff