Bladeren bron

Merge branch 'master' into audio

Conflicts:
	engine/Device.cpp
	engine/resource/ResourceManager.cpp
mikymod 12 jaren geleden
bovenliggende
commit
99217d9624
84 gewijzigde bestanden met toevoegingen van 6358 en 2052 verwijderingen
  1. 3 8
      CMakeLists.txt
  2. 1 1
      engine/Android.mk
  3. 13 10
      engine/CMakeLists.txt
  4. 71 71
      engine/ConsoleServer.cpp
  5. 32 32
      engine/ConsoleServer.h
  6. 12 13
      engine/Crown.h
  7. 26 77
      engine/Device.cpp
  8. 0 5
      engine/Device.h
  9. 0 117
      engine/Glyph.h
  10. 82 35
      engine/core/json/JSONParser.cpp
  11. 63 25
      engine/core/json/JSONParser.h
  12. 15 13
      engine/core/math/Quat.cpp
  13. 10 9
      engine/core/math/Quat.h
  14. 0 49
      engine/core/math/Shape.cpp
  15. 9 0
      engine/core/mem/ProxyAllocator.cpp
  16. 6 3
      engine/core/mem/ProxyAllocator.h
  17. 44 0
      engine/core/strings/StringUtils.h
  18. 2 5
      engine/lua/LuaAccelerometer.cpp
  19. 21 21
      engine/lua/LuaCamera.cpp
  20. 4 4
      engine/lua/LuaDevice.cpp
  21. 7 8
      engine/lua/LuaFloatSetting.cpp
  22. 7 8
      engine/lua/LuaIntSetting.cpp
  23. 5 5
      engine/lua/LuaKeyboard.cpp
  24. 139 173
      engine/lua/LuaMat4.cpp
  25. 16 16
      engine/lua/LuaMath.cpp
  26. 14 21
      engine/lua/LuaMouse.cpp
  27. 37 54
      engine/lua/LuaQuat.cpp
  28. 60 56
      engine/lua/LuaStack.cpp
  29. 15 18
      engine/lua/LuaStack.h
  30. 7 8
      engine/lua/LuaStringSetting.cpp
  31. 80 100
      engine/lua/LuaVec2.cpp
  32. 67 88
      engine/lua/LuaVec3.cpp
  33. 13 14
      engine/lua/LuaWindow.cpp
  34. 0 3
      engine/os/posix/Cond.cpp
  35. 6 3
      engine/os/posix/Cond.h
  36. 0 4
      engine/os/posix/Mutex.cpp
  37. 6 3
      engine/os/posix/Mutex.h
  38. 59 13
      engine/os/posix/Thread.cpp
  39. 48 7
      engine/os/posix/Thread.h
  40. 4 4
      engine/os/win/Cond.cpp
  41. 10 8
      engine/os/win/Cond.h
  42. 0 3
      engine/os/win/Mutex.cpp
  43. 5 3
      engine/os/win/Mutex.h
  44. 0 1
      engine/renderers/VertexFormat.cpp
  45. 6 8
      engine/renderers/VertexFormat.h
  46. 0 3
      engine/renderers/gl/GLRenderer.cpp
  47. 1 1
      engine/resource/FontResource.cpp
  48. 2 3
      engine/resource/FontResource.h
  49. 1 1
      engine/resource/MaterialResource.cpp
  50. 4 4
      engine/resource/MaterialResource.h
  51. 23 23
      engine/resource/MeshResource.cpp
  52. 22 9
      engine/resource/MeshResource.h
  53. 0 83
      engine/resource/PixelShaderResource.cpp
  54. 24 16
      engine/resource/Resource.h
  55. 44 34
      engine/resource/ResourceLoader.cpp
  56. 43 10
      engine/resource/ResourceLoader.h
  57. 56 296
      engine/resource/ResourceManager.cpp
  58. 29 90
      engine/resource/ResourceManager.h
  59. 45 36
      engine/resource/ResourceRegistry.cpp
  60. 4 16
      engine/resource/ResourceRegistry.h
  61. 1 1
      engine/resource/SoundResource.cpp
  62. 2 2
      engine/resource/SoundResource.h
  63. 1 1
      engine/resource/TextureResource.cpp
  64. 2 2
      engine/resource/TextureResource.h
  65. 0 83
      engine/resource/VertexShaderResource.cpp
  66. 0 2
      engine/tests/CMakeLists.txt
  67. 0 0
      engine/tests/allocators.cpp
  68. 1 1
      engine/tests/compressors.cpp
  69. 0 0
      engine/tests/containers.cpp
  70. 0 0
      engine/tests/messages.cpp
  71. 0 0
      engine/tests/paths.cpp
  72. 0 0
      engine/tests/strings.cpp
  73. 21 19
      samples/CMakeLists.txt
  74. 5 4
      tools/CMakeLists.txt
  75. 80 68
      tools/cli/resource-compiler.cpp
  76. 17 14
      tools/compilers/Compiler.cpp
  77. 1 1
      tools/compilers/Compiler.h
  78. 633 0
      tools/compilers/dae/DAECompiler.cpp
  79. 165 0
      tools/compilers/dae/DAECompiler.h
  80. 2099 0
      tools/compilers/dae/tinyxml2.cpp
  81. 1968 0
      tools/compilers/dae/tinyxml2.h
  82. 0 56
      tools/compilers/vs/VSCompiler.h
  83. 31 28
      tools/core/formats/MeshFormat.h
  84. 8 18
      tools/core/formats/VertexFormat.h

+ 3 - 8
CMakeLists.txt

@@ -4,11 +4,11 @@ project(crown)
 
 set (CROWN_VERSION_MAJOR 0)
 set (CROWN_VERSION_MINOR 1)
-set (CROWN_VERSION_MICRO 8)
+set (CROWN_VERSION_MICRO 9)
 
 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" OFF)
+option (CROWN_BUILD_TESTS "Whether to build unit tests" ON)
 
 # always debug mode for now
 set (CROWN_DEBUG 1)
@@ -29,12 +29,7 @@ add_subdirectory(engine)
 if (CROWN_BUILD_TOOLS)
 	add_subdirectory(tools)
 endif (CROWN_BUILD_TOOLS)
+
 if (CROWN_BUILD_SAMPLES)
 	add_subdirectory(samples)
 endif (CROWN_BUILD_SAMPLES)
-
-if (CROWN_BUILD_TESTS)
-	add_subdirectory(tests)
-endif (CROWN_BUILD_TESTS)
-
-

+ 1 - 1
engine/Android.mk

@@ -39,7 +39,6 @@ LOCAL_SRC_FILES :=\
 	core/math/Mat4.cpp\
 	core/math/Plane.cpp\
 	core/math/Quat.cpp\
-	core/math/Shape.cpp\
 	core/math/Vec2.cpp\
 	core/math/Vec3.cpp\
 	core/math/Vec4.cpp\
@@ -90,6 +89,7 @@ LOCAL_SRC_FILES :=\
 	resource/FontResource.cpp\
 	resource/MaterialResource.cpp\
 	resource/PixelShaderResource.cpp\
+	resource/ResourceLoader.cpp\
 	resource/ResourceManager.cpp\
 	resource/TextResource.cpp\
 	resource/TextureResource.cpp\

+ 13 - 10
engine/CMakeLists.txt

@@ -70,7 +70,6 @@ set (HEADERS
 	Config.h
 	Crown.h
 	Device.h
-	Glyph.h
 	ConsoleServer.h
 	FPSSystem.h
 )
@@ -121,7 +120,6 @@ set (MATH_SRC
 	core/math/Plane.cpp
 	core/math/Point2.cpp
 	core/math/Quat.cpp
-	core/math/Shape.cpp
 	core/math/Vec2.cpp
 	core/math/Vec3.cpp
 	core/math/Vec4.cpp
@@ -139,7 +137,6 @@ set (MATH_HEADERS
 	core/math/Quat.h
 	core/math/Random.h
 	core/math/Ray.h
-	core/math/Shape.h
 	core/math/Triangle.h
 	core/math/Vec2.h
 	core/math/Vec3.h
@@ -273,12 +270,12 @@ set (RENDERERS_HEADERS
 
 set (RESOURCE_SRC
 	resource/MaterialResource.cpp
+	resource/ResourceLoader.cpp
 	resource/ResourceManager.cpp
+	resource/ResourceRegistry.cpp
 	resource/TextureResource.cpp
-	resource/TextResource.cpp
+	resource/MeshResource.cpp
 	resource/FontResource.cpp
-	resource/VertexShaderResource.cpp
-	resource/PixelShaderResource.cpp
 	resource/SoundResource.cpp
 	resource/ArchiveBundle.cpp
 	resource/FileBundle.cpp
@@ -287,13 +284,13 @@ set (RESOURCE_SRC
 set (RESOURCE_HEADERS
 	resource/MaterialResource.h
 	resource/Resource.h
+	resource/ResourceLoader.h
 	resource/ResourceManager.h
+	resource/ResourceRegistry.h
 	resource/Bundle.h
 	resource/TextureResource.h
-	resource/TextResource.h
+	resource/MeshResource.h
 	resource/FontResource.h
-	resource/VertexShaderResource.h
-	resource/PixelShaderResource.h
 	resource/SoundResource.h
 	resource/ArchiveBundle.h
 	resource/FileBundle.h
@@ -402,7 +399,7 @@ if (LINUX)
 		-g
 		-pg
 		-fPIC
-		-fvisibility=hidden
+		#-fvisibility=hidden
 	)
 
 	set (CROWN_EXECUTABLE_NAME crown-linux)
@@ -500,6 +497,8 @@ set (CROWN_HEADERS
 
 	${RESOURCE_HEADERS}
 
+	${RPC_HEADERS}
+
 #	${NETWORK_HEADERS}
 
 	${OS_HEADERS}
@@ -521,6 +520,10 @@ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN")
 add_executable(${CROWN_EXECUTABLE_NAME} ${CROWN_MAIN_SRC})
 target_link_libraries(${CROWN_EXECUTABLE_NAME} crown)
 
+if (CROWN_BUILD_TESTS)
+	add_subdirectory(tests)
+endif (CROWN_BUILD_TESTS)
+
 install (TARGETS crown DESTINATION bin)
 install (TARGETS ${CROWN_EXECUTABLE_NAME} DESTINATION bin)
 

+ 71 - 71
engine/ConsoleServer.cpp

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

+ 32 - 32
engine/ConsoleServer.h

@@ -38,38 +38,38 @@ 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;
-
-	os::Thread				m_thread;
-	os::Mutex				m_command_mutex;
-
-	// Is console active?
-	bool					m_active;
-	// Commands buffer
-	char					m_cmd_buffer[1024];
-
-	char 					m_err_buffer[1024];
+// 	/// 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];
 
 };
 

+ 12 - 13
engine/Crown.h

@@ -44,7 +44,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Quat.h"
 #include "Random.h"
 #include "Ray.h"
-#include "Shape.h"
 #include "Triangle.h"
 #include "Vec2.h"
 #include "Vec3.h"
@@ -100,18 +99,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 // Engine
 #include "Camera.h"
 #include "Device.h"
-#include "Glyph.h"
-#include "Bundle.h"
-#include "ArchiveBundle.h"
-#include "FileBundle.h"
-#include "ResourceManager.h"
-
-#include "TextResource.h"
-#include "TextureResource.h"
-#include "MaterialResource.h"
-#include "FontResource.h"
-#include "VertexShaderResource.h"
-#include "PixelShaderResource.h"
 
 // Engine/Input
 #include "EventDispatcher.h"
@@ -143,3 +130,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 #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"
+#include "MeshResource.h"
+#include "SoundResource.h"
+#include "MaterialResource.h"
+#include "FontResource.h"

+ 26 - 77
engine/Device.cpp

@@ -53,6 +53,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "LuaEnvironment.h"
 #include "ConsoleServer.h"
 #include "AudioRenderer.h"
+#include "TextReader.h"
 
 namespace crown
 {
@@ -166,7 +167,7 @@ void Device::shutdown()
 	Log::i("Releasing ConsoleServer...");
 	if (m_console_server)
 	{
-		m_console_server->shutdown();
+		//m_console_server->shutdown();
 
 		CE_DELETE(m_allocator, m_console_server);
 	}
@@ -362,15 +363,14 @@ void Device::frame()
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	m_last_time = m_current_time;
 
-	m_resource_manager->check_load_queue();
-	m_resource_manager->bring_loaded_online();
+	m_resource_manager->poll_resource_loader();
 
 	m_window->frame();
 	m_input_manager->frame(frame_count());
 
 	m_lua_environment->game_frame(last_delta_time());
 
-	m_console_server->execute();
+	//m_console_server->execute();
 
 	m_debug_renderer->draw_all();
 	m_renderer->frame();
@@ -378,36 +378,12 @@ void Device::frame()
 	m_frame_count++;
 }
 
-//-----------------------------------------------------------------------------
-ResourceId Device::load(const char* name)
-{
-	return m_resource_manager->load(name);
-}
-
-//-----------------------------------------------------------------------------
-void Device::unload(ResourceId name)
-{
-	m_resource_manager->unload(name);
-}
-
 //-----------------------------------------------------------------------------
 void Device::reload(ResourceId name)
 {
 	(void)name;
 }
 
-//-----------------------------------------------------------------------------
-bool Device::is_loaded(ResourceId name)
-{
-	return m_resource_manager->is_loaded(name);
-}
-
-//-----------------------------------------------------------------------------
-const void* Device::data(ResourceId name)
-{
-	return m_resource_manager->data(name);
-}
-
 //-----------------------------------------------------------------------------
 void Device::create_filesystem()
 {
@@ -430,8 +406,19 @@ void Device::create_resource_manager()
 		m_resource_bundle = CE_NEW(m_allocator, ArchiveBundle)(*m_filesystem);
 	}
 
+	// Read resource seed
+	DiskFile* seed_file = filesystem()->open("seed.ini", FOM_READ);
+	TextReader reader(*seed_file);
+
+	char tmp_buf[32];
+	reader.read_string(tmp_buf, 32);
+
+	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);
+	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());
@@ -490,9 +477,9 @@ void Device::create_lua_environment()
 //-----------------------------------------------------------------------------
 void Device::create_console_server()
 {
-	m_console_server = CE_NEW(m_allocator, ConsoleServer)();
+	m_console_server = NULL;//CE_NEW(m_allocator, ConsoleServer)();
 
-	m_console_server->init();
+	//m_console_server->init();
 
 	Log::d("Console server created.");
 }
@@ -504,43 +491,6 @@ void Device::create_audio_renderer()
 
 	m_audio_renderer->init();
 
-	Log::i("Start Audio Rendering Test...");
-
-	ResourceId rid1 = load("mono.wav");
-
-	m_resource_manager->flush();
-
-	SoundResource* res1 = (SoundResource*)m_resource_manager->data(rid1);
-
-	SoundBufferId bid1 = m_audio_renderer->create_buffer(res1->data(), res1->size(), res1->sample_rate(), res1->channels(), res1->bits_per_sample());
-
-
-	Vec3 pos(0.0f, 0.0f, -3.0f);
-	Vec3 pos1(100.0f, 0.0f, 100.0f);
-
-	Vec3 vel(0.0f, 0.0f, 0.0f);
-	Vec3 dir(0.0f, 0.0f, 1.0f);
-
-	Vec3 dir1(1.0f, 0.0f, 1.0f);
-	Vec3 dir2(0.0f, 0.0f, -1.0f);
-
-
-	SoundSourceId sid = m_audio_renderer->create_source(pos, vel, dir, false); 
-	SoundSourceId sid1 = m_audio_renderer->create_source(pos1, vel, dir, false); 
-
-
-	m_audio_renderer->bind_buffer(sid, bid1);
-	m_audio_renderer->bind_buffer(sid1, bid1);
-
-	m_audio_renderer->play_source(sid);
-
-	while (m_audio_renderer->source_playing(sid));
-
-	m_audio_renderer->play_source(sid1);
-
-
-	Log::i("End Audio Rendering Test...");
-
 	Log::d("Audio renderer created");
 }
 
@@ -549,15 +499,14 @@ 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
+		{ "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 }
 	};
 
 	Args args(argc, argv, "", options);

+ 0 - 5
engine/Device.h

@@ -94,12 +94,7 @@ public:
 	/// Updates all the subsystems
 	void					frame();
 
-	/// Loads a resource and returns its unique identifier.
-	ResourceId				load(const char* name);
-	void					unload(ResourceId name);
 	void					reload(ResourceId name);
-	bool					is_loaded(ResourceId name);
-	const void*				data(ResourceId name);
 
 	Filesystem*				filesystem();
 	ResourceManager*		resource_manager();

+ 0 - 117
engine/Glyph.h

@@ -1,117 +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"
-
-namespace crown
-{
-
-class Glyph
-{
-public:
-
-	/// Constructor
-	Glyph() :
-		m_code_point(0),
-		m_left(0),
-		m_right(0),
-		m_bottom(0),
-		m_top(0),
-		m_width(0),
-		m_height(0),
-		m_advance(0),
-		m_baseline(0)
-	{
-	}
-
-	/// Constructor
-	Glyph(uint32_t code, float left, float right, float bottom, float top, float width, float height, float advance, float baseline) :
-		m_code_point(code),
-		m_left(left),
-		m_right(right),
-		m_bottom(bottom),
-		m_top(top),
-		m_width(width),
-		m_height(height),
-		m_advance(advance),
-		m_baseline(baseline)
-	{
-	}
-
-	/// Destructor
-	~Glyph()
-	{
-	}
-
-	/// Returns the glyph's metrics
-	void metrics(float& left, float& right, float& bottom, float& top, float& width, float& height, float& advance, float& baseline) const
-	{
-		left = m_left;
-		right = m_right;
-		bottom = m_bottom;
-		top = m_top;
-		width = m_width;
-		height = m_height;
-		advance = m_advance;
-		baseline = m_baseline;
-	}
-
-	/// Sets the glyph's metrics
-	void set_metrics(float left, float right, float bottom, float top, float width, float height, float advance, float baseline)
-	{
-		m_left = left;
-		m_right = right;
-		m_bottom = bottom;
-		m_top = top;
-		m_width = width;
-		m_height = height;
-		m_advance = advance;
-		m_baseline = baseline;
-	}
-
-	/// Returns the glyph's code point
-	uint32_t code_point() const
-	{
-		return m_code_point;
-	}
-
-private:
-
-	uint32_t m_code_point;
-	float m_left;
-	float m_right;
-	float m_bottom;
-	float m_top;
-	float m_width;
-	float m_height;
-	float m_advance;
-	float m_baseline;
-};
-
-} // namespace crown
-

+ 82 - 35
engine/core/json/JSONParser.cpp

@@ -24,8 +24,6 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <cstdio>
-
 #include "JSONParser.h"
 #include "TempAllocator.h"
 #include "StringUtils.h"
@@ -194,23 +192,21 @@ static bool is_escapee(char c)
 }
 
 //--------------------------------------------------------------------------
-JSONParser::JSONParser(const char* s) :
-	m_document(s),
-	m_at(s)
+JSONElement::JSONElement() :
+	m_parser(NULL),
+	m_at(NULL)
 {
-	CE_ASSERT_NOT_NULL(s);
 }
 
 //--------------------------------------------------------------------------
-JSONParser&	JSONParser::root()
+JSONElement::JSONElement(JSONParser& parser, const char* at) :
+	m_parser(&parser),
+	m_at(at)
 {
-	m_at = skip_whites(m_document);
-
-	return *this;
 }
 
 //--------------------------------------------------------------------------
-JSONParser& JSONParser::operator[](uint32_t i)
+JSONElement& JSONElement::operator[](uint32_t i)
 {
 	TempAllocator1024 alloc;
 	List<const char*> array(alloc);
@@ -225,13 +221,13 @@ JSONParser& JSONParser::operator[](uint32_t i)
 }
 
 //--------------------------------------------------------------------------
-JSONParser& JSONParser::index(uint32_t i)
+JSONElement& JSONElement::index(uint32_t i)
 {
 	return this->operator[](i);
 }
 
 //--------------------------------------------------------------------------
-JSONParser& JSONParser::key(const char* k)
+JSONElement& JSONElement::key(const char* k)
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
@@ -254,31 +250,74 @@ JSONParser& JSONParser::key(const char* k)
 		}
 	}
 
-	CE_ASSERT(found, "Key not found");
+	CE_ASSERT(found, "Key not found: '%s'", k);
 
 	return *this;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::bool_value() const
+bool JSONElement::has_key(const char* k) const
+{
+	TempAllocator1024 alloc;
+	List<JSONPair> object(alloc);
+	JSONParser::parse_object(m_at, object);
+
+	for (uint32_t i = 0; i < object.size(); i++)
+	{
+		if (string::strcmp(k, object[i].key) == 0)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+//--------------------------------------------------------------------------
+bool JSONElement::is_key_unique(const char* k) const
+{
+	TempAllocator1024 alloc;
+	List<JSONPair> object(alloc);
+	JSONParser::parse_object(m_at, object);
+
+	bool found = false;
+
+	for (uint32_t i = 0; i < object.size(); i++)
+	{
+		if (string::strcmp(k, object[i].key) == 0)
+		{
+			if (found == true)
+			{
+				return false;
+			}
+
+			found = true;
+		}
+	}
+
+	return found;
+}
+
+//--------------------------------------------------------------------------
+bool JSONElement::bool_value() const
 {
 	return JSONParser::parse_bool(m_at);
 }
 
 //--------------------------------------------------------------------------
-int32_t JSONParser::int_value() const
+int32_t JSONElement::int_value() const
 {
 	return JSONParser::parse_int(m_at);
 }
 
 //--------------------------------------------------------------------------
-float JSONParser::float_value() const
+float JSONElement::float_value() const
 {
 	return JSONParser::parse_float(m_at);
 }
 
 //--------------------------------------------------------------------------
-const char* JSONParser::string_value() const
+const char* JSONElement::string_value() const
 {
 	static TempAllocator1024 alloc;
 	static List<char> string(alloc);
@@ -291,43 +330,43 @@ const char* JSONParser::string_value() const
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_nil() const
+bool JSONElement::is_nil() const
 {
 	return JSONParser::type(m_at) == JT_NIL;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_bool() const
+bool JSONElement::is_bool() const
 {
 	return JSONParser::type(m_at) == JT_BOOL;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_number() const
+bool JSONElement::is_number() const
 {
 	return JSONParser::type(m_at) == JT_NUMBER;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_string() const
+bool JSONElement::is_string() const
 {
 	return JSONParser::type(m_at) == JT_STRING;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_array() const
+bool JSONElement::is_array() const
 {
 	return JSONParser::type(m_at) == JT_ARRAY;
 }
 
 //--------------------------------------------------------------------------
-bool JSONParser::is_object() const
+bool JSONElement::is_object() const
 {
 	return JSONParser::type(m_at) == JT_OBJECT;
 }
 
 //--------------------------------------------------------------------------
-uint32_t JSONParser::size() const
+uint32_t JSONElement::size() const
 {
 	switch(JSONParser::type(m_at))
 	{
@@ -374,6 +413,19 @@ uint32_t JSONParser::size() const
 	}
 }
 
+//--------------------------------------------------------------------------
+JSONParser::JSONParser(const char* s) :
+	m_document(s)
+{
+	CE_ASSERT_NOT_NULL(s);
+}
+
+//--------------------------------------------------------------------------
+JSONElement JSONParser::root()
+{
+	return JSONElement(*this, skip_whites(m_document));
+}
+
 //-----------------------------------------------------------------------------
 JSONType JSONParser::type(const char* s)
 {
@@ -433,7 +485,7 @@ void JSONParser::parse_string(const char* s, List<char>& str)
 		}
 	}
 
-	CE_ASSERT(false, "Not a valid string");
+	CE_ASSERT(false, "Bad string");
 }
 
 //-----------------------------------------------------------------------------
@@ -486,12 +538,7 @@ double JSONParser::parse_number(const char* s)
 	// Ensure null terminated
 	str.push_back('\0');
 
-	float number = 0.0f;
-
-	// Fixme
-	sscanf(str.begin(), "%f", &number);
-
-	return number;
+	return string::parse_double(str.begin());
 }
 
 //-----------------------------------------------------------------------------
@@ -523,7 +570,7 @@ bool JSONParser::parse_bool(const char* s)
 		default: break;
 	}
 
-	CE_ASSERT(false, "Not a boolean");
+	CE_ASSERT(false, "Bad boolean");
 }
 
 //-----------------------------------------------------------------------------
@@ -592,7 +639,7 @@ void JSONParser::parse_array(const char* s, List<const char*>& array)
 		}
 	}
 
-	CE_ASSERT(false, "Not an array");
+	CE_ASSERT(false, "Bad array");
 }
 
 //-----------------------------------------------------------------------------
@@ -654,7 +701,7 @@ void JSONParser::parse_object(const char* s, List<JSONPair>& object)
 		}
 	}
 
-	CE_ASSERT(false, "Not an object");
+	CE_ASSERT(false, "Bad object");
 }
 
 } //namespace crown

+ 63 - 25
engine/core/json/JSONParser.h

@@ -42,58 +42,67 @@ enum JSONType
 	JT_BOOL
 };
 
+/// Represents a key-value pair in a JSON document.
 struct JSONPair
 {
 	const char* key;
 	const char* val;
 };
 
-/// Parses JSON documents.
-class JSONParser
+class JSONParser;
+
+/// Represents a JSON element.
+/// The objects of this class are valid until the parser
+/// which has generated them, will exist.
+class JSONElement
 {
 public:
 
-	/// Read the JSON document contained in the non-null @a s string.
-	/// @note
-	/// The @a s string has to remain valid for the whole parser's
-	/// existence scope.
-						JSONParser(const char* s);
-
-	/// Returns the root element of the JSON document.
-	JSONParser&			root();
+	/// 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.
+						JSONElement();
 
 	/// Returns the @a i -th item of the current array.
-	JSONParser&			operator[](uint32_t i);
+	JSONElement&		operator[](uint32_t i);
 
 	/// @copydoc JSONParser::operator[]
-	JSONParser&			index(uint32_t i);
+	JSONElement&		index(uint32_t i);
 
 	/// Returns the element corresponding to key @a k of the
 	/// current object.
 	/// @note
 	/// If the key is not unique in the object scope, the last
 	/// key in order of appearance will be selected.
-	JSONParser&			key(const char* k);
+	JSONElement&		key(const char* k);
+
+	/// Returns whether the element has the @a k key.
+	bool				has_key(const char* k) const;
+
+	/// Returns whether the @a k key is unique in the object
+	/// element. If no such key is found it returns false.
+	bool				is_key_unique(const char* k) const;
 
-	/// Returns true wheter the current element is the JSON nil special value.
+	/// Returns true wheter the element is the JSON nil special value.
 	bool				is_nil() const;
 
-	/// Returns true wheter the current element is a JSON boolean (true or false).
+	/// Returns true wheter the element is a JSON boolean (true or false).
 	bool				is_bool() const;
 
-	/// Returns true wheter the current element is a JSON number.
+	/// Returns true wheter the element is a JSON number.
 	bool				is_number() const;
 
-	/// Returns true whether the current element is a JSON string.
+	/// Returns true whether the element is a JSON string.
 	bool				is_string() const;
 
-	/// Returns true whether the current element is a JSON array.
+	/// Returns true whether the element is a JSON array.
 	bool				is_array() const;
 
-	/// Returns true whether the current element is a JSON object.
+	/// Returns true whether the element is a JSON object.
 	bool				is_object() const;
 
-	/// Returns the size of the current element based on the
+	/// Returns the size of the element based on the
 	/// element's type:
 	/// * nil, bool, number: 1
 	/// * string: length of the string
@@ -101,22 +110,46 @@ public:
 	/// * object: number of keys in the object
 	uint32_t			size() const;
 
-	/// Returns the boolean value of the current element.
+	/// Returns the boolean value of the element.
 	bool				bool_value() const;
 
-	/// Returns the integer value of the current element.
+	/// Returns the integer value of the element.
 	int32_t				int_value() const;
 
-	/// Returns the float value of the current element.
+	/// Returns the float value of the element.
 	float				float_value() const;
 
-	/// Returns the string value of the current element.
+	/// 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;
 
+private:
+
+						JSONElement(JSONParser& parser, const char* at);
+
+	JSONParser*			m_parser;
+	const char*			m_at;
+
+	friend class 		JSONParser;
+};
+
+/// Parses JSON documents.
+class JSONParser
+{
+public:
+
+	/// Read the JSON document contained in the non-null @a s string.
+	/// @note
+	/// The @a s string has to remain valid for the whole parser's
+	/// existence scope.
+						JSONParser(const char* s);
+
+	/// Returns the root element of the JSON document.
+	JSONElement			root();
+
 public:
 
 	/// Returns the type of the @a s JSON text. 
@@ -148,7 +181,12 @@ public:
 private:
 
 	const char* const	m_document;
-	const char*			m_at;
+
+private:
+
+	// Disable copying
+						JSONParser(const JSONParser&);
+	JSONParser&			operator=(const JSONParser&);
 };
 
 } // namespace crown

+ 15 - 13
engine/core/math/Quat.cpp

@@ -40,10 +40,10 @@ Quat::Quat()
 }
 
 //-----------------------------------------------------------------------------
-Quat::Quat(float angle, const Vec3& v)
+Quat::Quat(const Vec3& axis, float angle)
 {
-	this->w = math::cos((float)(angle * 0.5));
-	this->v = v * math::sin((float)(angle * 0.5));
+	v = axis * math::sin(angle * 0.5);
+	w = math::cos(angle * 0.5);
 }
 
 //-----------------------------------------------------------------------------
@@ -77,22 +77,23 @@ void Quat::conjugate()
 //-----------------------------------------------------------------------------
 Quat Quat::get_conjugate() const
 {
-	return Quat(w, -v);
+	return Quat(-v, w);
 }
 
 //-----------------------------------------------------------------------------
 Quat Quat::get_inverse() const
 {
-	return get_conjugate() * ((float)(1.0 / length()));
+	return get_conjugate() * (1.0 / length());
 }
 
 //-----------------------------------------------------------------------------
 Mat3 Quat::to_mat3() const
 {
+	const float& x = v.x;
+	const float& y = v.y;
+	const float& z = v.z;
+
 	Mat3 tmp;
-	float x = v.x;
-	float y = v.y;
-	float z = v.z;
 
 	tmp.m[0] = (float)(1.0 - 2.0*y*y - 2.0*z*z);
 	tmp.m[1] = (float)(2.0*x*y + 2.0*w*z);
@@ -110,10 +111,11 @@ Mat3 Quat::to_mat3() const
 //-----------------------------------------------------------------------------
 Mat4 Quat::to_mat4() const
 {
+	const float& x = v.x;
+	const float& y = v.y;
+	const float& z = v.z;
+
 	Mat4 tmp;
-	float x = v.x;
-	float y = v.y;
-	float z = v.z;
 
 	tmp.m[0] = (float)(1.0 - 2.0*y*y - 2.0*z*z);
 	tmp.m[1] = (float)(2.0*x*y + 2.0*w*z);
@@ -181,7 +183,7 @@ Quat Quat::power(float exp)
 }
 
 /*
-The geometric interpretation of the Quat dot product is similar to the int32_terpretation of
+The geometric interpretation of the Quat dot product is similar to the interpretation of
 the vector dot product; the larger the absolute value of the Quat dot product axb, the more
 "similar" the angular displacements represented by a and b.
 */
@@ -191,7 +193,7 @@ float dot(const Quat& a, const Quat& b)
 	return a.w * b.w + a.v.dot(b.v);
 }
 
-// Spherical Linear intERPolation
+// Spherical Linear interpolation
 //-----------------------------------------------------------------------------
 Quat slerp(const Quat& start, const Quat& end, float t)
 {

+ 10 - 9
engine/core/math/Quat.h

@@ -55,28 +55,29 @@ public:
 
 public:
 
+	/// Does nothing
 				Quat();
 
-	/// Builds the quaternion from an angle and a vector								
-				Quat(float angle, const Vec3& v);	
+	/// Builds the quaternion from an @a axis and a @a angle.							
+				Quat(const Vec3& axis, float angle);	
 
-	/// Negates the quaternion
+	/// Negates the quaternion.
 	void		negate();
 
-	/// Builds the identity quaternion							
+	/// Builds the identity quaternion.
 	void		load_identity();
 
-	/// Returns the quaternion's length					
+	/// Returns the lenght of the quaternion.
 	float		length() const;		
 
-	/// Conjugates the quaternion				
+	/// Conjugates the quaternion.
 	void		conjugate();
 
-	/// Returns the quaternion's conjugate						
+	/// Returns the quaternion's conjugate.
 	Quat		get_conjugate() const;
 
 	/// Quaternion's inverse				
-	Quat		get_inverse() const;				
+	Quat		get_inverse() const;
 
 	Mat3		to_mat3() const;
 	Mat4		to_mat4() const;
@@ -85,7 +86,7 @@ public:
 	Quat		operator*(const Quat& b) const;
 
 	/// Multiplication by a scalar		
-	Quat		operator*(const float& k) const;		
+	Quat		operator*(const float& k) const;
 
 	Quat		power(float exp);
 };

+ 0 - 49
engine/core/math/Shape.cpp

@@ -1,49 +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 "Shape.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Shape::Shape(ShapeType type):
-	m_type(type)
-{
-}
-
-//-----------------------------------------------------------------------------
-Shape::~Shape()
-{
-}
-
-//-----------------------------------------------------------------------------
-ShapeType Shape::type()
-{
-	return m_type;
-}
-
-}

+ 9 - 0
engine/core/mem/ProxyAllocator.cpp

@@ -38,6 +38,7 @@ static ProxyAllocator* g_proxy_allocators_head = NULL;
 ProxyAllocator::ProxyAllocator(const char* name, Allocator& allocator) :
 	m_allocator(allocator),
 	m_name(name),
+	m_total_allocated(0),
 	m_next(NULL)
 {
 	CE_ASSERT(name != NULL, "Name must be != NULL");
@@ -53,6 +54,8 @@ ProxyAllocator::ProxyAllocator(const char* name, Allocator& allocator) :
 //-----------------------------------------------------------------------------
 void* ProxyAllocator::allocate(size_t size, size_t align)
 {
+	m_total_allocated += size;
+
 	return m_allocator.allocate(size, align);
 }
 
@@ -62,6 +65,12 @@ void ProxyAllocator::deallocate(void* data)
 	m_allocator.deallocate(data);
 }
 
+//-----------------------------------------------------------------------------
+size_t ProxyAllocator::allocated_size()
+{
+	return m_total_allocated;
+}
+
 //-----------------------------------------------------------------------------
 const char* ProxyAllocator::name() const
 {

+ 6 - 3
engine/core/mem/ProxyAllocator.h

@@ -28,16 +28,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "Memory.h"
+#include "Allocator.h"
 
 namespace crown
 {
 
-class Allocator;
-
 /// 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
+class ProxyAllocator : public Allocator
 {
 public:
 
@@ -50,6 +49,9 @@ public:
 	/// @copydoc Allocator::deallocate()
 	void					deallocate(void* data);
 
+	/// @copydoc Allocator::allocated_size()
+	size_t					allocated_size();
+
 	/// Returns the name of the proxy allocator
 	const char*				name() const;
 
@@ -74,6 +76,7 @@ private:
 
 	Allocator&				m_allocator;
 	const char*				m_name;
+	size_t					m_total_allocated;
 
 	ProxyAllocator*			m_next;
 };

+ 44 - 0
engine/core/strings/StringUtils.h

@@ -198,6 +198,50 @@ inline void substring(const char* begin, const char* end, char* out, size_t len)
 	out[i] = '\0';
 }
 
+//-----------------------------------------------------------------------------
+inline int32_t parse_int(const char* string)
+{
+	int val;
+	int ok = sscanf(string, "%d", &val);
+
+	CE_ASSERT(ok == 1, "Failed to parse int: %s", string);
+
+	return val;
+}
+
+//-----------------------------------------------------------------------------
+inline uint32_t parse_uint(const char* string)
+{
+	unsigned int val;
+	int ok = sscanf(string, "%u", &val);
+
+	CE_ASSERT(ok == 1, "Failed to parse uint: %s", string);
+
+	return val;
+}
+
+//-----------------------------------------------------------------------------
+inline float parse_float(const char* string)
+{
+	float val;
+	int ok = sscanf(string, "%f", &val);
+
+	CE_ASSERT(ok == 1, "Failed to parse float: %s", string);
+
+	return val;
+}
+
+//-----------------------------------------------------------------------------
+inline float parse_double(const char* string)
+{
+	double val;
+	int ok = sscanf(string, "%lf", &val);
+
+	CE_ASSERT(ok == 1, "Failed to parse float: %s", string);
+
+	return val;
+}
+
 } // namespace string
 } // namespace crown
 

+ 2 - 5
engine/lua/LuaAccelerometer.cpp

@@ -33,14 +33,11 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t accelerometer_orientation(lua_State* L)
+CE_EXPORT int accelerometer_orientation(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* orientation = next_vec3();
-	*orientation = device()->accelerometer()->orientation();
-
-	stack.push_vec3(orientation);
+	stack.push_vec3(device()->accelerometer()->orientation());
 
 	return 1;
 }

+ 21 - 21
engine/lua/LuaCamera.cpp

@@ -33,128 +33,128 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera(lua_State* L)
+CE_EXPORT int camera(lua_State* L)
 {
 	LuaStack stack(L);	
 
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_position(lua_State* L)
+CE_EXPORT int camera_position(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_position(lua_State* L)
+CE_EXPORT int camera_set_position(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_look_at(lua_State* L)
+CE_EXPORT int camera_look_at(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_look_at(lua_State* L)
+CE_EXPORT int camera_set_look_at(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_rotation(lua_State* L)
+CE_EXPORT int camera_set_rotation(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_up(lua_State* L)
+CE_EXPORT int camera_up(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_fov(lua_State* L)
+CE_EXPORT int camera_fov(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_fov(lua_State* L)
+CE_EXPORT int camera_set_fov(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_aspect(lua_State* L)
+CE_EXPORT int camera_aspect(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_aspect(lua_State* L)
+CE_EXPORT int camera_set_aspect(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_near_clip_distance(lua_State* L)
+CE_EXPORT int camera_near_clip_distance(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_near_clip_distance(lua_State* L)
+CE_EXPORT int camera_set_near_clip_distance(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_far_clip_distance(lua_State* L)
+CE_EXPORT int camera_far_clip_distance(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_set_far_clip_distance(lua_State* L)
+CE_EXPORT int camera_set_far_clip_distance(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_projection_matrix(lua_State* L)
+CE_EXPORT int camera_projection_matrix(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_view_matrix(lua_State* L)
+CE_EXPORT int camera_view_matrix(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_move_forward(lua_State* L)
+CE_EXPORT int camera_move_forward(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_move_backward(lua_State* L)
+CE_EXPORT int camera_move_backward(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_strafe_left(lua_State* L)
+CE_EXPORT int camera_strafe_left(lua_State* L)
 {
 	LuaStack stack(L);	
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t camera_strafe_right(lua_State* L)
+CE_EXPORT int camera_strafe_right(lua_State* L)
 {
 	LuaStack stack(L);	
 }

+ 4 - 4
engine/lua/LuaDevice.cpp

@@ -32,7 +32,7 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t device_frame_count(lua_State* L)
+CE_EXPORT int device_frame_count(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -44,7 +44,7 @@ CE_EXPORT int32_t device_frame_count(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t device_last_delta_time(lua_State* L)
+CE_EXPORT int device_last_delta_time(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -56,7 +56,7 @@ CE_EXPORT int32_t device_last_delta_time(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t device_start(lua_State* /*L*/)
+CE_EXPORT int device_start(lua_State* /*L*/)
 {
 	device()->start();
 
@@ -64,7 +64,7 @@ CE_EXPORT int32_t device_start(lua_State* /*L*/)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t device_stop(lua_State* /*L*/)
+CE_EXPORT int device_stop(lua_State* /*L*/)
 {
 	device()->stop();
 

+ 7 - 8
engine/lua/LuaFloatSetting.cpp

@@ -27,13 +27,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "FloatSetting.h"
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
-#include "StringUtils.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t float_setting_value(lua_State* L)
+CE_EXPORT int float_setting_value(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -54,7 +53,7 @@ CE_EXPORT int32_t float_setting_value(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t float_setting_synopsis(lua_State* L)
+CE_EXPORT int float_setting_synopsis(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -64,18 +63,18 @@ CE_EXPORT int32_t float_setting_synopsis(lua_State* L)
 
 	if (setting != NULL)
 	{
-		stack.push_string(setting->synopsis(), string::strlen(setting->synopsis()));
+		stack.push_string(setting->synopsis());
 	}
 	else
 	{
-		stack.push_string("", string::strlen(""));
+		stack.push_string("");
 	}
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t float_setting_min(lua_State* L)
+CE_EXPORT int float_setting_min(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -96,7 +95,7 @@ CE_EXPORT int32_t float_setting_min(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t float_setting_max(lua_State* L)
+CE_EXPORT int float_setting_max(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -117,7 +116,7 @@ CE_EXPORT int32_t float_setting_max(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t float_setting_update(lua_State* L)
+CE_EXPORT int float_setting_update(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 7 - 8
engine/lua/LuaIntSetting.cpp

@@ -27,13 +27,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "IntSetting.h"
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
-#include "StringUtils.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t int_setting_query_value(lua_State* L)
+CE_EXPORT int int_setting_query_value(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -54,7 +53,7 @@ CE_EXPORT int32_t int_setting_query_value(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t int_setting_query_synopsis(lua_State* L)
+CE_EXPORT int int_setting_query_synopsis(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -64,18 +63,18 @@ CE_EXPORT int32_t int_setting_query_synopsis(lua_State* L)
 
 	if (setting != NULL)
 	{
-		stack.push_string(setting->synopsis(), string::strlen(setting->synopsis()));
+		stack.push_string(setting->synopsis());
 	}
 	else
 	{
-		stack.push_string("", string::strlen(""));
+		stack.push_string("");
 	}
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t int_setting_query_min(lua_State* L)
+CE_EXPORT int int_setting_query_min(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -96,7 +95,7 @@ CE_EXPORT int32_t int_setting_query_min(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t int_setting_query_max(lua_State* L)
+CE_EXPORT int int_setting_query_max(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -117,7 +116,7 @@ CE_EXPORT int32_t int_setting_query_max(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t int_setting_update(lua_State* L)
+CE_EXPORT int int_setting_update(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 5 - 5
engine/lua/LuaKeyboard.cpp

@@ -33,7 +33,7 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t keyboard_modifier_pressed(lua_State* L)
+CE_EXPORT int keyboard_modifier_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -45,7 +45,7 @@ CE_EXPORT int32_t keyboard_modifier_pressed(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t keyboard_key_pressed(lua_State* L)
+CE_EXPORT int keyboard_key_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -57,7 +57,7 @@ CE_EXPORT int32_t keyboard_key_pressed(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t keyboard_key_released(lua_State* L)
+CE_EXPORT int keyboard_key_released(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -69,7 +69,7 @@ CE_EXPORT int32_t keyboard_key_released(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t keyboard_any_pressed(lua_State* L)
+CE_EXPORT int keyboard_any_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -79,7 +79,7 @@ CE_EXPORT int32_t keyboard_any_pressed(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t keyboard_any_released(lua_State* L)
+CE_EXPORT int keyboard_any_released(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 139 - 173
engine/lua/LuaMat4.cpp

@@ -34,508 +34,474 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4(lua_State* L)
+CE_EXPORT int mat4(lua_State* L)
 {
 	LuaStack stack(L);
 
 	float m0 = stack.get_float(1);
 	float m1 = stack.get_float(2);
 	float m2 = stack.get_float(3);
-	float m4 = stack.get_float(4);	
-	float m5 = stack.get_float(5);
-	float m6 = stack.get_float(6);	
-	float m8 = stack.get_float(7);
-	float m9 = stack.get_float(8);
-	float m10 = stack.get_float(9);
-
-	Mat4* mat = next_mat4();
-
-	mat->m[0] = m0;
-	mat->m[1] = m1;
-	mat->m[2] = m2;
-	mat->m[4] = m4;
-	mat->m[5] = m5;
-	mat->m[6] = m6;
-	mat->m[8] = m8;
-	mat->m[9] = m9;
-	mat->m[10] = m10;
-
-	stack.push_mat4(mat);
+	float m3 = stack.get_float(4);
+	float m4 = stack.get_float(5);	
+	float m5 = stack.get_float(6);
+	float m6 = stack.get_float(7);
+	float m7 = stack.get_float(8);
+	float m8 = stack.get_float(9);
+	float m9 = stack.get_float(10);
+	float m10 = stack.get_float(11);
+	float m11 = stack.get_float(12);
+	float m12 = stack.get_float(13);
+	float m13 = stack.get_float(14);
+	float m14 = stack.get_float(15);
+	float m15 = stack.get_float(16);
+
+	stack.push_mat4(Mat4(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------					
-CE_EXPORT int32_t mat4_add(lua_State* L)
+CE_EXPORT int mat4_add(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Mat4* b = stack.get_mat4(2);
+	Mat4& a = stack.get_mat4(1);
+	Mat4& b = stack.get_mat4(2);
 
-	*a += *b;
-
-	stack.push_mat4(a);
+	stack.push_mat4(a + b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_subtract(lua_State* L)
+CE_EXPORT int mat4_subtract(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
-	Mat4* b = (Mat4*)stack.get_mat4(2);
-
-	*a -= *b;
+	Mat4& a = stack.get_mat4(1);
+	Mat4& b = stack.get_mat4(2);
 
-	stack.push_mat4(a);
+	stack.push_mat4(a - b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_multiply(lua_State* L)
+CE_EXPORT int mat4_multiply(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Mat4* b = stack.get_mat4(2);
-
-	*a *= *b;
+	Mat4& a = stack.get_mat4(1);
+	Mat4& b = stack.get_mat4(2);
 
-	stack.push_mat4(a);
+	stack.push_mat4(a * b);
 
 	return 1;
 }	
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_multiply_by_scalar(lua_State* L)
+CE_EXPORT int mat4_multiply_by_scalar(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float k = stack.get_float(2);
 
-	*a *= k;
-
-	stack.push_mat4(a);
+	stack.push_mat4(a * k);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_divide_by_scalar(lua_State* L)
+CE_EXPORT int mat4_divide_by_scalar(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float k = stack.get_float(2);
 
-	*a /= k;
-
-	stack.push_mat4(a);
+	stack.push_mat4(a / k);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_rotation_x(lua_State* L)
+CE_EXPORT int mat4_build_rotation_x(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float k = stack.get_float(2);
 
-	a->build_rotation_x(k);
+	a.build_rotation_x(k);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_rotation_y(lua_State* L)
+CE_EXPORT int mat4_build_rotation_y(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float k = stack.get_float(2);
 
-	a->build_rotation_y(k);
+	a.build_rotation_y(k);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_rotation_z(lua_State* L)
+CE_EXPORT int mat4_build_rotation_z(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float k = stack.get_float(2);
 
-	a->build_rotation_z(k);
+	a.build_rotation_z(k);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_rotation(lua_State* L)
+CE_EXPORT int mat4_build_rotation(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = (Mat4*)stack.get_mat4(1);
-	Vec3* d = (Vec3*)stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& d = stack.get_vec3(2);
 	float k = stack.get_float(3);
 
-	a->build_rotation(*d, k);
+	a.build_rotation(d, k);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_projection_perspective_rh(lua_State* L)
+CE_EXPORT int mat4_build_projection_perspective_rh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float fovy = stack.get_float(2);
 	float aspect = stack.get_float(3);
 	float near = stack.get_float(4);
 	float far = stack.get_float(5);
 
-	a->build_projection_perspective_rh(fovy, aspect, near, far);
+	a.build_projection_perspective_rh(fovy, aspect, near, far);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_projection_perspective_lh(lua_State* L)
+CE_EXPORT int mat4_build_projection_perspective_lh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float fovy = stack.get_float(2);
 	float aspect = stack.get_float(3);
 	float near = stack.get_float(4);
 	float far = stack.get_float(5);
 
-	a->build_projection_perspective_lh(fovy, aspect, near, far);
+	a.build_projection_perspective_lh(fovy, aspect, near, far);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_projection_ortho_rh(lua_State* L)
+CE_EXPORT int mat4_build_projection_ortho_rh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float width = stack.get_float(2);
 	float height = stack.get_float(3);
 	float near = stack.get_float(4);
 	float far = stack.get_float(5);
 
-	a->build_projection_ortho_rh(width, height, near, far);
+	a.build_projection_ortho_rh(width, height, near, far);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_projection_ortho_lh(lua_State* L)
+CE_EXPORT int mat4_build_projection_ortho_lh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float width = stack.get_float(2);
 	float height = stack.get_float(3);
 	float near = stack.get_float(4);
 	float far = stack.get_float(5);
 
-	a->build_projection_ortho_lh(width, height, near, far);
+	a.build_projection_ortho_lh(width, height, near, far);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_projection_ortho_2d_rh(lua_State* L)
+CE_EXPORT int mat4_build_projection_ortho_2d_rh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 	float width = stack.get_float(2);
 	float height = stack.get_float(3);
 	float near = stack.get_float(4);
 	float far = stack.get_float(5);
 
-	a->build_projection_ortho_2d_rh(width, height, near, far);
+	a.build_projection_ortho_2d_rh(width, height, near, far);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_look_at_rh(lua_State* L)
+CE_EXPORT int mat4_build_look_at_rh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* pos = stack.get_vec3(2);
-	Vec3* target = stack.get_vec3(3);
-	Vec3* up = stack.get_vec3(4);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& pos = stack.get_vec3(2);
+	Vec3& target = stack.get_vec3(3);
+	Vec3& up = stack.get_vec3(4);
 
-	a->build_look_at_rh(*pos, *target, *up);
+	a.build_look_at_rh(pos, target, up);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_look_at_lh(lua_State* L)
+CE_EXPORT int mat4_build_look_at_lh(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* pos = stack.get_vec3(2);
-	Vec3* target = stack.get_vec3(3);
-	Vec3* up = stack.get_vec3(4);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& pos = stack.get_vec3(2);
+	Vec3& target = stack.get_vec3(3);
+	Vec3& up = stack.get_vec3(4);
 
-	a->build_look_at_lh(*pos, *target, *up);
+	a.build_look_at_lh(pos, target, up);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_viewpoint_billboard(lua_State* L)
+CE_EXPORT int mat4_build_viewpoint_billboard(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* pos = stack.get_vec3(2);
-	Vec3* target = stack.get_vec3(3);
-	Vec3* up = stack.get_vec3(4);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& pos = stack.get_vec3(2);
+	Vec3& target = stack.get_vec3(3);
+	Vec3& up = stack.get_vec3(4);
 
-	a->build_viewpoint_billboard(*pos, *target, *up);
+	a.build_viewpoint_billboard(pos, target, up);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_build_axis_billboard(lua_State* L)
+CE_EXPORT int mat4_build_axis_billboard(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* pos = stack.get_vec3(2);
-	Vec3* target = stack.get_vec3(3);
-	Vec3* up = stack.get_vec3(4);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& pos = stack.get_vec3(2);
+	Vec3& target = stack.get_vec3(3);
+	Vec3& up = stack.get_vec3(4);
 
-	a->build_axis_billboard(*pos, *target, *up);
+	a.build_axis_billboard(pos, target, up);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_transpose(lua_State* L)
+CE_EXPORT int mat4_transpose(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-
-	a->transpose();
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_mat4(a);
+	stack.push_mat4(a.transpose());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_determinant(lua_State* L)
+CE_EXPORT int mat4_determinant(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_float(a->get_determinant());
+	stack.push_float(a.get_determinant());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_invert(lua_State* L)
+CE_EXPORT int mat4_invert(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 
-	a->invert();
-
-	stack.push_mat4(a);
+	stack.push_mat4(a.invert());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_load_identity(lua_State* L)
+CE_EXPORT int mat4_load_identity(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 
-	a->load_identity();
+	a.load_identity();
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_x(lua_State* L)
+CE_EXPORT int mat4_x(lua_State* L)
 {	
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-
-	Vec3* x = next_vec3();
-	*x = a->x();
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_vec3(x);
+	stack.push_vec3(a.x());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_y(lua_State* L)
+CE_EXPORT int mat4_y(lua_State* L)
 {	
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-
-	Vec3* y = next_vec3();
-	*y = a->y();
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_vec3(y);
+	stack.push_vec3(a.y());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_z(lua_State* L)
+CE_EXPORT int mat4_z(lua_State* L)
 {	
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 
-	Vec3* z = next_vec3();
-	*z = a->z();
-
-	stack.push_vec3(z);
+	stack.push_vec3(a.z());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_set_x(lua_State* L)
+CE_EXPORT int mat4_set_x(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* x = stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& x = stack.get_vec3(2);
 
-	a->set_x(*x);
+	a.set_x(x);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_set_y(lua_State* L)
+CE_EXPORT int mat4_set_y(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* y = stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& y = stack.get_vec3(2);
 
-	a->set_y(*y);
+	a.set_y(y);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_set_z(lua_State* L)
+CE_EXPORT int mat4_set_z(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* z = stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& z = stack.get_vec3(2);
 
-	a->set_z(*z);
+	a.set_z(z);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_translation(lua_State* L)
+CE_EXPORT int mat4_translation(lua_State* L)
 {	
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-
-	Vec3* translation = next_vec3();
-	*translation = a->translation();
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_vec3(translation);
+	stack.push_vec3(a.translation());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_set_translation(lua_State* L)
+CE_EXPORT int mat4_set_translation(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* trans = stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& trans = stack.get_vec3(2);
 
-	a->set_translation(*trans);
+	a.set_translation(trans);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_get_scale(lua_State* L)
+CE_EXPORT int mat4_get_scale(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-
-	Vec3* scale = next_vec3();
-	*scale = a->get_scale();
+	Mat4& a = stack.get_mat4(1);
 
-	stack.push_vec3(scale);
+	stack.push_vec3(a.get_scale());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_set_scale(lua_State* L)
+CE_EXPORT int mat4_set_scale(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
-	Vec3* scale = stack.get_vec3(2);
+	Mat4& a = stack.get_mat4(1);
+	Vec3& scale = stack.get_vec3(2);
 
-	a->set_scale(*scale);
+	a.set_scale(scale);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mat4_print(lua_State* L)
+CE_EXPORT int mat4_print(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Mat4* a = stack.get_mat4(1);
+	Mat4& a = stack.get_mat4(1);
 
-	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a->m[0], a->m[4], a->m[8], a->m[12]);
-	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a->m[1], a->m[5], a->m[9], a->m[13]);
-	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a->m[2], a->m[6], a->m[10], a->m[14]);
-	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a->m[3], a->m[7], a->m[11], a->m[15]);
+	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a.m[0], a.m[4], a.m[8], a.m[12]);
+	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a.m[1], a.m[5], a.m[9], a.m[13]);
+	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a.m[2], a.m[6], a.m[10], a.m[14]);
+	os::printf("|%.1f|%.1f|%.1f|%.1f|\n", a.m[3], a.m[7], a.m[11], a.m[15]);
 
 	return 0;
 }

+ 16 - 16
engine/lua/LuaMath.cpp

@@ -32,7 +32,7 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_deg_to_rad(lua_State* L)
+CE_EXPORT int math_deg_to_rad(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -44,7 +44,7 @@ CE_EXPORT int32_t math_deg_to_rad(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_rad_to_deg(lua_State* L)
+CE_EXPORT int math_rad_to_deg(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -56,7 +56,7 @@ CE_EXPORT int32_t math_rad_to_deg(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_next_pow_2(lua_State* L)
+CE_EXPORT int math_next_pow_2(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -68,7 +68,7 @@ CE_EXPORT int32_t math_next_pow_2(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_is_pow_2(lua_State* L)
+CE_EXPORT int math_is_pow_2(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -80,7 +80,7 @@ CE_EXPORT int32_t math_is_pow_2(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_ceil(lua_State* L)
+CE_EXPORT int math_ceil(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -92,7 +92,7 @@ CE_EXPORT int32_t math_ceil(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_floor(lua_State* L)
+CE_EXPORT int math_floor(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -104,7 +104,7 @@ CE_EXPORT int32_t math_floor(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_sqrt(lua_State* L)
+CE_EXPORT int math_sqrt(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -116,7 +116,7 @@ CE_EXPORT int32_t math_sqrt(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_inv_sqrt(lua_State* L)
+CE_EXPORT int math_inv_sqrt(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -128,7 +128,7 @@ CE_EXPORT int32_t math_inv_sqrt(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_sin(lua_State* L)
+CE_EXPORT int math_sin(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -140,7 +140,7 @@ CE_EXPORT int32_t math_sin(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_cos(lua_State* L)
+CE_EXPORT int math_cos(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -152,7 +152,7 @@ CE_EXPORT int32_t math_cos(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_asin(lua_State* L)
+CE_EXPORT int math_asin(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -164,7 +164,7 @@ CE_EXPORT int32_t math_asin(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_acos(lua_State* L)
+CE_EXPORT int math_acos(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -176,7 +176,7 @@ CE_EXPORT int32_t math_acos(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_tan(lua_State* L)
+CE_EXPORT int math_tan(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -188,7 +188,7 @@ CE_EXPORT int32_t math_tan(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_atan2(lua_State* L)
+CE_EXPORT int math_atan2(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -201,7 +201,7 @@ CE_EXPORT int32_t math_atan2(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_abs(lua_State* L)
+CE_EXPORT int math_abs(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -213,7 +213,7 @@ CE_EXPORT int32_t math_abs(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t math_fmod(lua_State* L)
+CE_EXPORT int math_fmod(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 14 - 21
engine/lua/LuaMouse.cpp

@@ -34,7 +34,7 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_button_pressed(lua_State* L)
+CE_EXPORT int mouse_button_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -46,7 +46,7 @@ CE_EXPORT int32_t mouse_button_pressed(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_button_released(lua_State* L)
+CE_EXPORT int mouse_button_released(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -58,7 +58,7 @@ CE_EXPORT int32_t mouse_button_released(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_any_pressed(lua_State* L)
+CE_EXPORT int mouse_any_pressed(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -68,7 +68,7 @@ CE_EXPORT int32_t mouse_any_pressed(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_any_released(lua_State* L)
+CE_EXPORT int mouse_any_released(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -78,52 +78,45 @@ CE_EXPORT int32_t mouse_any_released(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_cursor_xy(lua_State* L)
+CE_EXPORT int mouse_cursor_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* xy = next_vec2();
-
-	*xy = device()->mouse()->cursor_xy();
-
-	stack.push_vec2(xy);
+	stack.push_vec2(device()->mouse()->cursor_xy());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_set_cursor_xy(lua_State* L)
+CE_EXPORT int mouse_set_cursor_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* xy = stack.get_vec2(1);
+	Vec2& xy = stack.get_vec2(1);
 
-	device()->mouse()->set_cursor_xy(*xy);
+	device()->mouse()->set_cursor_xy(xy);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_cursor_relative_xy(lua_State* L)
+CE_EXPORT int mouse_cursor_relative_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* xy = next_vec2();
-	*xy = device()->mouse()->cursor_relative_xy();
-
-	stack.push_vec2(xy);
+	stack.push_vec2(device()->mouse()->cursor_relative_xy());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t mouse_set_cursor_relative_xy(lua_State* L)
+CE_EXPORT int mouse_set_cursor_relative_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* xy = (Vec2*) stack.get_vec2(1);
+	Vec2& xy = stack.get_vec2(1);
 
-	device()->mouse()->set_cursor_relative_xy(*xy);
+	device()->mouse()->set_cursor_relative_xy(xy);
 
 	return 0;
 }

+ 37 - 54
engine/lua/LuaQuat.cpp

@@ -34,130 +34,113 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat(lua_State* L)
+CE_EXPORT int quat(lua_State* L)
 {
 	LuaStack stack(L);
 
 	float w = stack.get_float(1);
-	Vec3* v = stack.get_vec3(2);
+	Vec3& v = stack.get_vec3(2);
 
-	Quat* quat = next_quat();
-
-	quat->w = w;
-	quat->v = *v;
-
-	stack.push_quat(quat);
+	stack.push_quat(Quat(v, w));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_negate(lua_State* L)
+CE_EXPORT int quat_negate(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 
-	q->negate();
+	q.negate();
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_load_identity(lua_State* L)
+CE_EXPORT int quat_load_identity(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 
-	q->load_identity();
+	q.load_identity();
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_length(lua_State* L)
+CE_EXPORT int quat_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 
-	stack.push_float(q->length());
+	stack.push_float(q.length());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_conjugate(lua_State* L)
+CE_EXPORT int quat_conjugate(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 
-	Quat* conjugate = next_quat();
-	*conjugate = q->get_conjugate();
-
-	stack.push_quat(conjugate);
+	stack.push_quat(q.get_conjugate());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_inverse(lua_State* L)
+CE_EXPORT int quat_inverse(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
-
-	Quat* inverse = next_quat();
-	*inverse = q->get_inverse();
+	Quat& q = stack.get_quat(1);
 
-	stack.push_quat(inverse);
+	stack.push_quat(q.get_inverse());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_cross(lua_State* L)
+CE_EXPORT int quat_cross(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q1 = stack.get_quat(1);
-	Quat* q2 = stack.get_quat(2);
+	Quat& q1 = stack.get_quat(1);
+	Quat& q2 = stack.get_quat(2);
 
-	*q1 = (*q1) * (*q2);
-
-	stack.push_quat(q1);
+	stack.push_quat(q1 * q2);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_multiply(lua_State* L)
+CE_EXPORT int quat_multiply(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 	float k = stack.get_float(2);
 
-	*q = (*q) * k;
-
-	stack.push_quat(q);
+	stack.push_quat(q * k);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t quat_power(lua_State* L)
+CE_EXPORT int quat_power(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Quat* q = stack.get_quat(1);
+	Quat& q = stack.get_quat(1);
 	float k = stack.get_float(2);
 
-	q->power(k);
-
-	stack.push_quat(q);
+	stack.push_quat(q.power(k));
 
 	return 1;
 }
@@ -165,15 +148,15 @@ CE_EXPORT int32_t quat_power(lua_State* L)
 //-----------------------------------------------------------------------------
 void load_quat(LuaEnvironment& env)
 {
-	env.load_module_function("Quat", "new", quat);
-	env.load_module_function("Quat", "negate", quat_negate);
-	env.load_module_function("Quat", "load_identity", quat_load_identity);
-	env.load_module_function("Quat", "length", quat_length);
-	env.load_module_function("Quat", "conjugate", quat_conjugate);
-	env.load_module_function("Quat", "inverse", quat_inverse);
-	env.load_module_function("Quat", "cross", quat_cross);
-	env.load_module_function("Quat", "mul", quat_multiply);
-	env.load_module_function("Quat", "pow", quat_power);
+	env.load_module_function("Quat", "new",				quat);
+	env.load_module_function("Quat", "negate",			quat_negate);
+	env.load_module_function("Quat", "load_identity",	quat_load_identity);
+	env.load_module_function("Quat", "length",			quat_length);
+	env.load_module_function("Quat", "conjugate",		quat_conjugate);
+	env.load_module_function("Quat", "inverse",			quat_inverse);
+	env.load_module_function("Quat", "cross",			quat_cross);
+	env.load_module_function("Quat", "mul",				quat_multiply);
+	env.load_module_function("Quat", "pow",				quat_power);
 }
 
 } //namespace crown

+ 60 - 56
engine/lua/LuaStack.cpp

@@ -51,35 +51,35 @@ static Quat 			quat_buffer[LUA_QUAT_BUFFER_SIZE];
 static uint32_t 		quat_used = 0;
 
 //-----------------------------------------------------------------------------
-Vec2* next_vec2()
+static Vec2* next_vec2(const Vec2& v)
 {
 	CE_ASSERT(vec2_used < LUA_VEC2_BUFFER_SIZE, "Maximum number of Vec2 reached");
 
-	return &vec2_buffer[vec2_used++];
+	return &(vec2_buffer[vec2_used++] = v);
 }
 
 //-----------------------------------------------------------------------------
-Vec3* next_vec3()
+static Vec3* next_vec3(const Vec3& v)
 {
 	CE_ASSERT(vec3_used < LUA_VEC3_BUFFER_SIZE, "Maximum number of Vec3 reached");
 
-	return &vec3_buffer[vec3_used++];
+	return &(vec3_buffer[vec3_used++] = v);
 }
 
 //-----------------------------------------------------------------------------
-Mat4* next_mat4()
+static Mat4* next_mat4(const Mat4& m)
 {
 	CE_ASSERT(mat4_used < LUA_MAT4_BUFFER_SIZE, "Maximum number of Mat4 reached");
 
-	return &mat4_buffer[mat4_used++];
+	return &(mat4_buffer[mat4_used++] = m);
 }
 
 //-----------------------------------------------------------------------------
-Quat* next_quat()
+static Quat* next_quat(const Quat& q)
 {
 	CE_ASSERT(quat_used < LUA_QUAT_BUFFER_SIZE, "Maximum number of Quat reached");
 
-	return &quat_buffer[quat_used++];
+	return &(quat_buffer[quat_used++] = q);
 }
 
 //-----------------------------------------------------------------------------	
@@ -94,6 +94,12 @@ lua_State* LuaStack::state()
 	return m_state;
 }
 
+//-----------------------------------------------------------------------------
+int32_t LuaStack::num_args()
+{
+	return lua_gettop(m_state);
+}
+
 //-----------------------------------------------------------------------------
 void LuaStack::push_bool(bool value)
 {
@@ -131,9 +137,15 @@ void LuaStack::push_float(float value)
 }
 
 //-----------------------------------------------------------------------------
-void LuaStack::push_string(const char* str, size_t len)
+void LuaStack::push_string(const char* s)
 {
-	lua_pushlstring(m_state, str, len);
+	lua_pushstring(m_state, s);
+}
+
+//-----------------------------------------------------------------------------
+void LuaStack::push_literal(const char* s, size_t len)
+{
+	lua_pushlstring(m_state, s, len);
 }
 
 //-----------------------------------------------------------------------------
@@ -143,35 +155,27 @@ void LuaStack::push_lightdata(void* data)
 }
 
 //-----------------------------------------------------------------------------
-void LuaStack::push_vec2(Vec2* v)
+void LuaStack::push_vec2(const Vec2& v)
 {
-	CE_ASSERT(v >= &vec2_buffer[0] && v <= &vec2_buffer[LUA_VEC2_BUFFER_SIZE-1], "Vec2 type error");
-
-	lua_pushlightuserdata(m_state, v);
+	lua_pushlightuserdata(m_state, next_vec2(v));
 }
 
 //-----------------------------------------------------------------------------
-void LuaStack::push_vec3(Vec3* v)
+void LuaStack::push_vec3(const Vec3& v)
 {
-	CE_ASSERT(v >= &vec3_buffer[0] && v <= &vec3_buffer[LUA_VEC3_BUFFER_SIZE-1], "Vec3 type error");
-
-	lua_pushlightuserdata(m_state, v);
+	lua_pushlightuserdata(m_state, next_vec3(v));
 }
 
 //-----------------------------------------------------------------------------
-void LuaStack::push_mat4(Mat4* m)
+void LuaStack::push_mat4(const Mat4& m)
 {
-	CE_ASSERT(m >= &mat4_buffer[0] && m <= &mat4_buffer[LUA_MAT4_BUFFER_SIZE-1], "Mat4 type error");
-
-	lua_pushlightuserdata(m_state, m);
+	lua_pushlightuserdata(m_state, next_mat4(m));
 }
 
 //-----------------------------------------------------------------------------
-void LuaStack::push_quat(Quat* q)
+void LuaStack::push_quat(const Quat& q)
 {
-	CE_ASSERT(q >= &quat_buffer[0] && q <= &quat_buffer[LUA_MAT4_BUFFER_SIZE-1], "Quat type error");
-
-	lua_pushlightuserdata(m_state, q);
+	lua_pushlightuserdata(m_state, next_quat(q));
 }
 
 //-----------------------------------------------------------------------------
@@ -201,59 +205,59 @@ const char* LuaStack::get_string(int32_t index)
 //-----------------------------------------------------------------------------
 void* LuaStack::get_lightdata(int32_t index)
 {
-	CE_ASSERT(lua_islightuserdata(m_state, index), "Not a lightuserdata object");
-
-	void* data = lua_touserdata(m_state, index);
-
-	return data;	
+	return lua_touserdata(m_state, index);	
 }
 
 //-----------------------------------------------------------------------------
-Vec2* LuaStack::get_vec2(int32_t index)
+Vec2& LuaStack::get_vec2(int32_t index)
 {
-	CE_ASSERT(lua_islightuserdata(m_state, index), "Not a lightuserdata object");
+	void* v = lua_touserdata(m_state, index);
 
-	Vec2* v = (Vec2*)lua_touserdata(m_state, index);
+	if (v < &vec2_buffer[0] || v > &vec2_buffer[LUA_VEC2_BUFFER_SIZE-1])
+	{
+		luaL_typerror(m_state, index, "Vec2");
+	}
 
-	CE_ASSERT(v >= &vec2_buffer[0] && v <= &vec2_buffer[LUA_VEC2_BUFFER_SIZE-1], "Vec2 type error");
-
-	return v;
+	return *(Vec2*)v;
 }
 
 //-----------------------------------------------------------------------------
-Vec3* LuaStack::get_vec3(int32_t index)
+Vec3& LuaStack::get_vec3(int32_t index)
 {
-	CE_ASSERT(lua_islightuserdata(m_state, index), "Not a lightuserdata object");
-
-	Vec3* v = (Vec3*)lua_touserdata(m_state, index);
+	void* v = lua_touserdata(m_state, index);
 
-	CE_ASSERT(v >= &vec3_buffer[0] && v <= &vec3_buffer[LUA_VEC3_BUFFER_SIZE-1], "Vec3 type error");
+	if (v < &vec3_buffer[0] || v > &vec3_buffer[LUA_VEC3_BUFFER_SIZE-1])
+	{
+		luaL_typerror(m_state, index, "Vec3");
+	}
 
-	return v;
+	return *(Vec3*)v;
 }
 
 //-----------------------------------------------------------------------------
-Mat4* LuaStack::get_mat4(int32_t index)
+Mat4& LuaStack::get_mat4(int32_t index)
 {
-	CE_ASSERT(lua_islightuserdata(m_state, index), "Not a lightuserdata object");
+	void* m = lua_touserdata(m_state, index);
 
-	Mat4* m = (Mat4*)lua_touserdata(m_state, index);
+	if (m < &mat4_buffer[0] || m > &mat4_buffer[LUA_MAT4_BUFFER_SIZE-1])
+	{
+		luaL_typerror(m_state, index, "Mat4");
+	}
 
-	CE_ASSERT(m >= &mat4_buffer[0] && m <= &mat4_buffer[LUA_MAT4_BUFFER_SIZE-1], "Mat4 type error");
-
-	return m;
+	return *(Mat4*)m;
 }
 
 //-----------------------------------------------------------------------------
-Quat* LuaStack::get_quat(int32_t index)
+Quat& LuaStack::get_quat(int32_t index)
 {
-	CE_ASSERT(lua_islightuserdata(m_state, index), "Not a lightuserdata object");
-
-	Quat* q = (Quat*)lua_touserdata(m_state, index);
+	void* q = lua_touserdata(m_state, index);
 
-	CE_ASSERT(q >= &quat_buffer[0] && q <= &quat_buffer[LUA_QUAT_BUFFER_SIZE-1], "Quat type error");
+	if (q < &quat_buffer[0] || q > &quat_buffer[LUA_QUAT_BUFFER_SIZE-1])
+	{
+		luaL_typerror(m_state, index, "Quat");
+	}
 
-	return q;
+	return *(Quat*)q;
 }
 
-} // namespace crown
+} // namespace crown

+ 15 - 18
engine/lua/LuaStack.h

@@ -37,12 +37,6 @@ class Vec3;
 class Mat4;
 class Quat;
 
-Vec2* next_vec2();
-Vec3* next_vec3();
-
-Mat4* next_mat4();
-Quat* next_quat();
-
 class LuaStack
 {
 public:
@@ -51,6 +45,11 @@ public:
 
 	lua_State*				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);
@@ -63,17 +62,18 @@ public:
 
 	void 					push_float(float value);
 
-	void 					push_string(const char* str, size_t len);
+	void 					push_string(const char* s);
+	void					push_literal(const char* s, size_t len);
 
 	void					push_lightdata(void* data);
 
-	void					push_vec2(Vec2* v);
+	void					push_vec2(const Vec2& v);
 
-	void					push_vec3(Vec3* v);
+	void					push_vec3(const Vec3& v);
 
-	void					push_mat4(Mat4* m);
+	void					push_mat4(const Mat4& m);
 
-	void					push_quat(Quat* q);
+	void					push_quat(const Quat& q);
 
 	bool 					get_bool(int32_t index);
 
@@ -85,13 +85,10 @@ public:
 
 	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);
+	Vec2&					get_vec2(int32_t index);
+	Vec3&					get_vec3(int32_t index);
+	Mat4&					get_mat4(int32_t index);
+	Quat&					get_quat(int32_t index);
 
 private:
 

+ 7 - 8
engine/lua/LuaStringSetting.cpp

@@ -27,13 +27,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "StringSetting.h"
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
-#include "StringUtils.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t string_setting_value(lua_State* L)
+CE_EXPORT int string_setting_value(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -43,18 +42,18 @@ CE_EXPORT int32_t string_setting_value(lua_State* L)
 
 	if (setting != NULL)
 	{
-		stack.push_string(setting->value(), string::strlen(setting->value()));
+		stack.push_string(setting->value());
 	}
 	else
 	{
-		stack.push_string("", string::strlen(""));
+		stack.push_string("");
 	}
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t string_setting_synopsis(lua_State* L)
+CE_EXPORT int string_setting_synopsis(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -64,18 +63,18 @@ CE_EXPORT int32_t string_setting_synopsis(lua_State* L)
 
 	if (setting != NULL)
 	{
-		stack.push_string(setting->synopsis(), string::strlen(setting->synopsis()));
+		stack.push_string(setting->synopsis());
 	}
 	else
 	{
-		stack.push_string("", string::strlen(""));
+		stack.push_string("");
 	}
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t string_setting_update(lua_State* L)
+CE_EXPORT int string_setting_update(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 80 - 100
engine/lua/LuaVec2.cpp

@@ -32,250 +32,230 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2(lua_State* L)
+CE_EXPORT int vec2(lua_State* L)
 {
 	LuaStack stack(L);
 
 	float x = stack.get_float(1);
 	float y = stack.get_float(2);
 
-	Vec2* vec = next_vec2();
-
-	vec->x = x;
-	vec->y = y;
-
-	stack.push_vec2(vec);
+	stack.push_vec2(Vec2(x, y));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_values(lua_State* L)
+CE_EXPORT int vec2_values(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*)stack.get_vec2(1);
-
-	float x = a->x;
-	float y = a->y;
+	Vec2& a = stack.get_vec2(1);
 
-	stack.push_float(x);
-	stack.push_float(y);
+	stack.push_float(a.x);
+	stack.push_float(a.y);
 
 	return 2;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_add(lua_State* L)
+CE_EXPORT int vec2_add(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*)stack.get_vec2(1);
-	Vec2* b = (Vec2*)stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	*a += *b;
-
-	stack.push_vec2(a);
+	stack.push_vec2(a + b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_subtract(lua_State* L)
+CE_EXPORT int vec2_subtract(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
-
-	*a -= *b;
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_vec2(a);
+	stack.push_vec2(a - b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_multiply(lua_State* L)
+CE_EXPORT int vec2_multiply(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 	float k = stack.get_float(2);
 
-	*a *= k;
-
-	stack.push_vec2(a);
+	stack.push_vec2(a * k);
 
 	return 1;
 }			
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_divide(lua_State* L)
+CE_EXPORT int vec2_divide(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 	float k = stack.get_float(2);
 
-	*a /= k;
-
-	stack.push_vec2(a);
+	stack.push_vec2(a / k);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_dot(lua_State* L)
+CE_EXPORT int vec2_dot(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_float(a->dot(*b));
+	stack.push_float(a.dot(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_equals(lua_State* L)
+CE_EXPORT int vec2_equals(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_bool(*a == *b);
+	stack.push_bool(a == b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_lower(lua_State* L)
+CE_EXPORT int vec2_lower(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_bool(*a < *b);
+	stack.push_bool(a < b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_greater(lua_State* L)
+CE_EXPORT int vec2_greater(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 	
-	stack.push_bool(*a > *b);
+	stack.push_bool(a > b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_length(lua_State* L)
+CE_EXPORT int vec2_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 
-	stack.push_float(a->length());
+	stack.push_float(a.length());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_squared_length(lua_State* L)
+CE_EXPORT int vec2_squared_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 
-	stack.push_float(a->squared_length());
+	stack.push_float(a.squared_length());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_set_length(lua_State* L)
+CE_EXPORT int vec2_set_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 	float len = stack.get_float(2);
 
-	a->set_length(len);
+	a.set_length(len);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_normalize(lua_State* L)
+CE_EXPORT int vec2_normalize(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 
-	a->normalize();
-
-	stack.push_vec2(a);
+	stack.push_vec2(a.normalize());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_negate(lua_State* L)
+CE_EXPORT int vec2_negate(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-
-	a->negate();
+	Vec2& a = stack.get_vec2(1);
 
-	stack.push_vec2(a);
+	stack.push_vec2(a.negate());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_get_distance_to(lua_State* L)
+CE_EXPORT int vec2_get_distance_to(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_float(a->get_distance_to(*b));
+	stack.push_float(a.get_distance_to(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_get_angle_between(lua_State* L)
+CE_EXPORT int vec2_get_angle_between(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec2* a = (Vec2*) stack.get_vec2(1);
-	Vec2* b = (Vec2*) stack.get_vec2(2);
+	Vec2& a = stack.get_vec2(1);
+	Vec2& b = stack.get_vec2(2);
 
-	stack.push_float(a->get_angle_between(*b));
+	stack.push_float(a.get_angle_between(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec2_zero(lua_State* L)
+CE_EXPORT int vec2_zero(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec2* a = (Vec2*) stack.get_vec2(1);
+	Vec2& a = stack.get_vec2(1);
 
-	a->zero();
+	a.zero();
 
 	return 0;
 }
@@ -283,24 +263,24 @@ CE_EXPORT int32_t vec2_zero(lua_State* L)
 //-----------------------------------------------------------------------------
 void load_vec2(LuaEnvironment& env)
 {
-	env.load_module_function("Vec2", "new", vec2);
-	env.load_module_function("Vec2", "val", vec2_values);
-	env.load_module_function("Vec2", "add", vec2_add);
-	env.load_module_function("Vec2", "sub", vec2_subtract);
-	env.load_module_function("Vec2", "mul", vec2_multiply);
-	env.load_module_function("Vec2", "div", vec2_divide);
-	env.load_module_function("Vec2", "dot", vec2_dot);
-	env.load_module_function("Vec2", "equals", vec2_equals);
-	env.load_module_function("Vec2", "lower", vec2_lower);
-	env.load_module_function("Vec2", "greater", vec2_greater);
-	env.load_module_function("Vec2", "length", vec2_length);
-	env.load_module_function("Vec2", "squared_length", vec2_squared_length);
-	env.load_module_function("Vec2", "set_length", vec2_set_length);
-	env.load_module_function("Vec2", "normalize", vec2_normalize);
-	env.load_module_function("Vec2", "negate", vec2_negate);
-	env.load_module_function("Vec2", "get_distance_to", vec2_get_distance_to);
-	env.load_module_function("Vec2", "get_angle_between", vec2_get_angle_between);
-	env.load_module_function("Vec2", "zero", vec2_zero);
+	env.load_module_function("Vec2", "new",					vec2);
+	env.load_module_function("Vec2", "val",					vec2_values);
+	env.load_module_function("Vec2", "add",					vec2_add);
+	env.load_module_function("Vec2", "sub",					vec2_subtract);
+	env.load_module_function("Vec2", "mul",					vec2_multiply);
+	env.load_module_function("Vec2", "div",					vec2_divide);
+	env.load_module_function("Vec2", "dot",					vec2_dot);
+	env.load_module_function("Vec2", "equals",				vec2_equals);
+	env.load_module_function("Vec2", "lower",				vec2_lower);
+	env.load_module_function("Vec2", "greater",				vec2_greater);
+	env.load_module_function("Vec2", "length",				vec2_length);
+	env.load_module_function("Vec2", "squared_length",		vec2_squared_length);
+	env.load_module_function("Vec2", "set_length",			vec2_set_length);
+	env.load_module_function("Vec2", "normalize",			vec2_normalize);
+	env.load_module_function("Vec2", "negate",				vec2_negate);
+	env.load_module_function("Vec2", "get_distance_to",		vec2_get_distance_to);
+	env.load_module_function("Vec2", "get_angle_between",	vec2_get_angle_between);
+	env.load_module_function("Vec2", "zero",				vec2_zero);
 }
 
 } // namespace crown

+ 67 - 88
engine/lua/LuaVec3.cpp

@@ -32,7 +32,7 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3(lua_State* L)
+CE_EXPORT int vec3(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -40,258 +40,237 @@ CE_EXPORT int32_t vec3(lua_State* L)
 	float y = stack.get_float(2);
 	float z = stack.get_float(3);
 
-	Vec3* vec = next_vec3();
-
-	vec->x = x;
-	vec->y = y;
-	vec->z = z;
-
-	stack.push_vec3(vec);
+	stack.push_vec3(Vec3(x, y, z));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_values(lua_State* L)
+CE_EXPORT int vec3_values(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	float x = a->x;
-	float y = a->y;
-	float z = a->z;
-
-	stack.push_float(x);
-	stack.push_float(y);
-	stack.push_float(z);
+	stack.push_float(a.x);
+	stack.push_float(a.y);
+	stack.push_float(a.z);
 
 	return 3;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_add(lua_State* L)
+CE_EXPORT int vec3_add(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
-
-	*a += *b;
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_vec3(a);
+	stack.push_vec3(a + b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_subtract(lua_State* L)
+CE_EXPORT int vec3_subtract(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	*a -= *b;
-
-	stack.push_vec3(a);
+	stack.push_vec3(a - b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_multiply(lua_State* L)
+CE_EXPORT int vec3_multiply(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 	float b = stack.get_float(2);
 
-	*a *= b;
-
-	stack.push_vec3(a);
+	stack.push_vec3(a * b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_divide(lua_State* L)
+CE_EXPORT int vec3_divide(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 	float b = stack.get_float(2);
 
-	*a /= b;
-
-	stack.push_vec3(a);
+	stack.push_vec3(a / b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_dot(lua_State* L)
+CE_EXPORT int vec3_dot(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_float(a->dot(*b));
+	stack.push_float(a.dot(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_cross(lua_State* L)
+CE_EXPORT int vec3_cross(lua_State* L)
 {
 	LuaStack stack(L);
 	
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
-
-	/// CHECK CHECK CHECK
-	*a = a->cross(*b);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_vec3(a);
+	stack.push_vec3(a.cross(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_equals(lua_State* L)
+CE_EXPORT int vec3_equals(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_bool(*a == *b);
+	stack.push_bool(a == b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_lower(lua_State* L)
+CE_EXPORT int vec3_lower(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_bool(*a < *b);
+	stack.push_bool(a < b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_greater(lua_State* L)
+CE_EXPORT int vec3_greater(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_bool(*a > *b);
+	stack.push_bool(a > b);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_length(lua_State* L)
+CE_EXPORT int vec3_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	stack.push_float(a->length());
+	stack.push_float(a.length());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_squared_length(lua_State* L)
+CE_EXPORT int vec3_squared_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	stack.push_float(a->squared_length());
+	stack.push_float(a.squared_length());
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_set_length(lua_State* L)
+CE_EXPORT int vec3_set_length(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 	float len = stack.get_float(2);
 
-	a->set_length(len);
+	a.set_length(len);
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_normalize(lua_State* L)
+CE_EXPORT int vec3_normalize(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	a->normalize();
+	a.normalize();
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_negate(lua_State* L)
+CE_EXPORT int vec3_negate(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	a->negate();
+	a.negate();
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_get_distance_to(lua_State* L)
+CE_EXPORT int vec3_get_distance_to(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_float(a->get_distance_to(*b));
+	stack.push_float(a.get_distance_to(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_get_angle_between(lua_State* L)
+CE_EXPORT int vec3_get_angle_between(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
-	Vec3* b = stack.get_vec3(2);
+	Vec3& a = stack.get_vec3(1);
+	Vec3& b = stack.get_vec3(2);
 
-	stack.push_float(a->get_angle_between(*b));
+	stack.push_float(a.get_angle_between(b));
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t vec3_zero(lua_State* L)
+CE_EXPORT int vec3_zero(lua_State* L)
 {
 	LuaStack stack(L);
 
-	Vec3* a = stack.get_vec3(1);
+	Vec3& a = stack.get_vec3(1);
 
-	a->zero();
+	a.zero();
 
 	return 0;
 }	

+ 13 - 14
engine/lua/LuaWindow.cpp

@@ -28,13 +28,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "OsWindow.h"
 #include "LuaStack.h"
 #include "LuaEnvironment.h"
-#include "StringUtils.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_show(lua_State* L)
+CE_EXPORT int window_show(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -44,7 +43,7 @@ CE_EXPORT int32_t window_show(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_hide(lua_State* L)
+CE_EXPORT int window_hide(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -54,7 +53,7 @@ CE_EXPORT int32_t window_hide(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_get_size(lua_State* L)
+CE_EXPORT int window_get_size(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -69,7 +68,7 @@ CE_EXPORT int32_t window_get_size(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_get_position(lua_State* L)
+CE_EXPORT int window_get_position(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -84,7 +83,7 @@ CE_EXPORT int32_t window_get_position(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_resize(lua_State* L)
+CE_EXPORT int window_resize(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -97,7 +96,7 @@ CE_EXPORT int32_t window_resize(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_move(lua_State* L)
+CE_EXPORT int window_move(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -110,7 +109,7 @@ CE_EXPORT int32_t window_move(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_show_cursor(lua_State* L)
+CE_EXPORT int window_show_cursor(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -120,7 +119,7 @@ CE_EXPORT int32_t window_show_cursor(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_hide_cursor(lua_State* L)
+CE_EXPORT int window_hide_cursor(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -130,7 +129,7 @@ CE_EXPORT int32_t window_hide_cursor(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_get_cursor_xy(lua_State* L)
+CE_EXPORT int window_get_cursor_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -145,7 +144,7 @@ CE_EXPORT int32_t window_get_cursor_xy(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_set_cursor_xy(lua_State* L)
+CE_EXPORT int window_set_cursor_xy(lua_State* L)
 {
 	LuaStack stack(L);
 
@@ -158,19 +157,19 @@ CE_EXPORT int32_t window_set_cursor_xy(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_title(lua_State* L)
+CE_EXPORT int window_title(lua_State* L)
 {
 	LuaStack stack(L);
 
 	const char* title = device()->window()->title();
 
-	stack.push_string(title, string::strlen(title));
+	stack.push_string(title);
 
 	return 1;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int32_t window_set_title(lua_State* L)
+CE_EXPORT int window_set_title(lua_State* L)
 {
 	LuaStack stack(L);
 

+ 0 - 3
engine/os/posix/Cond.cpp

@@ -30,8 +30,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 //-----------------------------------------------------------------------------
 Cond::Cond()
@@ -59,5 +57,4 @@ void Cond::wait(Mutex& mutex)
 	pthread_cond_wait(&m_cond, &(mutex.m_mutex));
 }
 
-} // namespace os
 } // namespace crown

+ 6 - 3
engine/os/posix/Cond.h

@@ -34,8 +34,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 class Cond
 {
@@ -50,7 +48,12 @@ public:
 private:
 
 	pthread_cond_t	m_cond;
+
+private:
+
+	// Disable copying.
+					Cond(const Cond&);
+	Cond&			operator=(const Cond&);
 };
 
-} // namespace os
 } // namespace crown

+ 0 - 4
engine/os/posix/Mutex.cpp

@@ -30,8 +30,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 //-----------------------------------------------------------------------------
 Mutex::Mutex()
@@ -59,6 +57,4 @@ void Mutex::unlock()
 	pthread_mutex_unlock(&m_mutex);
 }
 
-} // namespace os
 } // namespace crown
-

+ 6 - 3
engine/os/posix/Mutex.h

@@ -33,8 +33,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 class Mutex
 {
@@ -50,8 +48,13 @@ private:
 
 	pthread_mutex_t		m_mutex;
 
+private:
+
+	// Disable copying.
+						Mutex(const Mutex&);
+	Mutex&				operator=(const Mutex&);
+
 	friend class		Cond;
 };
 
-} // namespace os
 } // namespace crown

+ 59 - 13
engine/os/posix/Thread.cpp

@@ -28,17 +28,36 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <string.h>
 
 #include "Thread.h"
+#include "Assert.h"
 
 namespace crown
 {
-namespace os
-{
 
 //-----------------------------------------------------------------------------
-Thread::Thread(os::ThreadFunction f, void* params, const char* name) :
-	m_name(name)
+Thread::Thread(const char* name) :
+	m_name(name),
+	m_is_running(false),
+	m_is_terminating(false),
+	m_thread(0)
 {
 	memset(&m_thread, 0, sizeof(pthread_t));
+}
+
+//-----------------------------------------------------------------------------
+Thread::~Thread()
+{
+}
+
+//-----------------------------------------------------------------------------
+const char* Thread::name() const
+{
+	return m_name;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::start()
+{
+	m_is_terminating = false;
 
 	// Make thread joinable
 	pthread_attr_t attr;
@@ -46,21 +65,49 @@ Thread::Thread(os::ThreadFunction f, void* params, const char* name) :
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 
 	// Create thread
-	int rc = pthread_create(&m_thread, &attr, f, (void*)params);
-
-	if (rc != 0)
-	{
-		os::printf("Unable to create the thread '%s' Error code: %d\n", name, rc);
-		exit(-1);
-	}
+	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;
 }
 
 //-----------------------------------------------------------------------------
-Thread::~Thread()
+bool Thread::is_running() const
+{
+	return m_is_running;
+}
+
+//-----------------------------------------------------------------------------
+bool Thread::is_terminating() const
+{
+	return m_is_terminating;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::stop()
+{
+	m_is_terminating = true;
+}
+
+//-----------------------------------------------------------------------------
+int32_t Thread::run()
 {
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+void* Thread::background_proc(void* thiz)
+{
+	Thread* thread = ((Thread*) thiz);
+
+	thread->run();
+
+	thread->m_is_running = false;
+
+	return NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -75,5 +122,4 @@ void Thread::detach()
 	pthread_detach(m_thread);
 }
 
-} // namespace os
 } // namespace crown

+ 48 - 7
engine/os/posix/Thread.h

@@ -29,12 +29,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <pthread.h>
 
 #include "Types.h"
-#include "OS.h"
 
 namespace crown
 {
-namespace os
-{
 
 typedef void* (*ThreadFunction)(void*);
 
@@ -42,17 +39,61 @@ class Thread
 {
 public:
 
-					Thread(os::ThreadFunction f, void* params, const char* name);
-					~Thread();
+	/// Constructs the thread and gives it a @a name.
+	/// @note
+	/// The actual OS thread creation and execution is
+	/// deferred to the first call to Thread::start().
+					Thread(const char* name);
+
+	/// Does not stop the thread. The user must call
+	/// Thread::stop() to effectively stop the thread. 
+	virtual			~Thread();
+
+	/// Returns the name of the thread.
+	const char*		name() const;
 
 	void			join();
 	void			detach();
 
+	/// Returns whether the thread is currently running.
+	bool			is_running() const;
+
+	/// Returns whether the thread is being asked to stop running.
+	/// @note
+	/// The implementer tipically polls this function to
+	/// determine whether to stop the execution or not.
+	bool			is_terminating() const;
+
+	/// Starts the execution of the thread.
+	/// The function creates the OS thread and starts
+	/// its execution.
+	void			start();
+
+	/// Stops the execution of the thread if it is running.
+	/// The function releases the OS thread causing its
+	/// termination.
+	void			stop();
+
+	/// Executes in background when the thead is running.
+	/// The thread has to be started with Thread::start()
+	virtual int32_t	run();
+
+private:
+
+	static void*	background_proc(void* thiz);
+
 private:
 
-	pthread_t		m_thread;
 	const char*		m_name;
+	bool			m_is_running;
+	bool			m_is_terminating;
+	pthread_t		m_thread;
+
+private:
+
+	// Disable copying
+					Thread(const Thread&);
+	Thread&			operator=(const Thread&);
 };
 
-} // namespace os
 } // namespace crown

+ 4 - 4
engine/os/win/Cond.cpp

@@ -28,28 +28,28 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
+//-----------------------------------------------------------------------------
 Cond::Cond()
 {
 	InitializeConditionVariable(&m_cond);
 }
 
+//-----------------------------------------------------------------------------
 Cond::~Cond()
 {
-	
 }
 
+//-----------------------------------------------------------------------------
 void Cond::signal()
 {
 	WakeConditionVariable(&m_cond);
 }
 
+//-----------------------------------------------------------------------------
 void Cond::wait(Mutex& mutex)
 {
 	SleepConditionVariableCS(&m_cond, &mutex.m_cs, INFINITE);
 }
 
-} // namespace os
 } // namespace crown

+ 10 - 8
engine/os/win/Cond.h

@@ -33,23 +33,25 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 class Cond
 {
 public:
 
-							Cond();
-							~Cond();
+						Cond();
+						~Cond();
+
+	void				signal();
+	void				wait(Mutex& mutex);
+
+private:
 
-	void					signal();
-	void					wait(Mutex& mutex);
+						Cond(const Cond&);
+	Cond&				operator=(const Cond&);
 
 private:
 
-	CONDITION_VARIABLE		m_cond;
+	CONDITION_VARIABLE	m_cond;
 };
 
-} // namespace os
 } // namespace crown

+ 0 - 3
engine/os/win/Mutex.cpp

@@ -29,8 +29,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 //-----------------------------------------------------------------------------
 Mutex::Mutex()
@@ -56,5 +54,4 @@ void Mutex::unlock()
     LeaveCriticalSection(&m_cs);
 }
 
-} // namespace os
 } // namespace crown

+ 5 - 3
engine/os/win/Mutex.h

@@ -32,8 +32,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 namespace crown
 {
-namespace os
-{
 
 class Mutex
 {
@@ -49,8 +47,12 @@ private:
 
 	CRITICAL_SECTION	m_cs;
 
+private:
+
+						Mutex(const Mutex&);
+	Mutex&				operator=(const Mutex&);
+
 	friend class		Cond;
 };
 
-} // namespace os
 } // namespace crown

+ 0 - 1
engine/renderers/VertexFormat.cpp

@@ -56,7 +56,6 @@ size_t Vertex::bytes_per_vertex(VertexFormat format)
 		{
 			return 32;
 		}
-		case VF_UNKNOWN:
 		default:
 		{
 			return 0;

+ 6 - 8
engine/renderers/VertexFormat.h

@@ -32,17 +32,15 @@ namespace crown
 /// Enumerates vertex formats.
 enum VertexFormat
 {
-	VF_XY_FLOAT_32,					///< XY coordinates, 32-bit floating point each
-	VF_XYZ_FLOAT_32,				///< XYZ coordinates, 32-bit floating point each
+	VF_XY_FLOAT_32					= 0,	///< XY coordinates, 32-bit floating point each
+	VF_XYZ_FLOAT_32					= 1,	///< XYZ coordinates, 32-bit floating point each
 
-	VF_UV_FLOAT_32,					///< UV coordinates, 32-bit floating point each
-	VF_UVT_FLOAT_32,				///< UVT coordinates, 32-bit floating point each
+	VF_UV_FLOAT_32					= 2,	///< UV coordinates, 32-bit floating point each
+	VF_UVT_FLOAT_32					= 3,	///< UVT coordinates, 32-bit floating point each
 
-	VF_XYZ_NORMAL_FLOAT_32,			///< XYZ normal coordinates, 32-bit floating point each
+	VF_XYZ_NORMAL_FLOAT_32			= 4, 	///< XYZ normal coordinates, 32-bit floating point each
 
-	VF_XYZ_UV_XYZ_NORMAL_FLOAT_32,	///< XYZ coordinates, UV coordinates, XYZ normal coordinates, 32-bit floating point each
-
-	VF_UNKNOWN
+	VF_XYZ_UV_XYZ_NORMAL_FLOAT_32	= 5		///< XYZ coordinates, UV coordinates, XYZ normal coordinates, 32-bit floating point each
 };
 
 class Vertex

+ 0 - 3
engine/renderers/gl/GLRenderer.cpp

@@ -42,9 +42,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Mat3.h"
 #include "Mat4.h"
 #include "Device.h"
-#include "ResourceManager.h"
-#include "VertexShaderResource.h"
-#include "PixelShaderResource.h"
 
 namespace crown
 {

+ 1 - 1
engine/resource/FontResource.cpp

@@ -49,7 +49,7 @@ void FontResource::unload(Allocator& /*allocator*/, void* /*resource*/)
 }
 
 //-----------------------------------------------------------------------------
-void FontResource::offline()
+void FontResource::offline(void* /*resource*/)
 {
 }
 

+ 2 - 3
engine/resource/FontResource.h

@@ -27,7 +27,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
-#include "Glyph.h"
 #include "Resource.h"
 
 namespace crown
@@ -41,9 +40,9 @@ class FontResource
 public:
 
 	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			online(void* resource);
 	static void			unload(Allocator& allocator, void* resource);
-	static void			offline();
+	static void			online(void* resource);
+	static void			offline(void* resource);
 
 public:
 

+ 1 - 1
engine/resource/MaterialResource.cpp

@@ -51,7 +51,7 @@ void MaterialResource::unload(Allocator& /*allocator*/, void* /*material*/)
 }
 
 //-----------------------------------------------------------------------------
-void MaterialResource::offline()
+void MaterialResource::offline(void* /*resource*/)
 {
 	// TODO
 }

+ 4 - 4
engine/resource/MaterialResource.h

@@ -51,10 +51,10 @@ class MaterialResource
 {
 public:
 
-	static void*	load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void		online(void* resource);
-	static void		unload(Allocator& allocator, void* texture);
-	static void		offline();
+	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
+	static void			unload(Allocator& allocator, void* resource);
+	static void			online(void* resource);
+	static void			offline(void* resource);
 
 private:
 

+ 23 - 23
engine/resource/TextResource.cpp → engine/resource/MeshResource.cpp

@@ -24,57 +24,57 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "TextResource.h"
-#include "DiskFile.h"
+#include "MeshResource.h"
 #include "Bundle.h"
 #include "Log.h"
+#include "DiskFile.h"
+#include "Assert.h"
 #include "Allocator.h"
+#include "Device.h"
+#include "Renderer.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-void* TextResource::load(Allocator& allocator, Bundle& bundle, ResourceId id)
+void* MeshResource::load(Allocator& allocator, Bundle& bundle, ResourceId id)
 {
-	DiskFile* stream = bundle.open(id);
+	DiskFile* file = bundle.open(id);
 
-	CE_ASSERT(stream != NULL, "Resource does not exist: %.8X%.8X", id.name, id.type);
+	CE_ASSERT(file != NULL, "Resource does not exist: %.8X%.8X", id.name, id.type);
 
-	TextResource* resource = (TextResource*)allocator.allocate(sizeof(TextResource));
+	MeshResource* resource = (MeshResource*)allocator.allocate(sizeof(MeshResource));
+	file->read(&resource->m_header, sizeof(MeshHeader));
 
-	stream->read(&resource->length, sizeof(uint32_t));
-	
-	resource->data = (char*)allocator.allocate(sizeof(char) * (resource->length + 1));
+	// Read vertices
+	file->read(&resource->m_vertex_count, sizeof(uint32_t));
+	resource->m_vertices = (float*) allocator.allocate(sizeof(float) * resource->m_vertex_count);
+	file->read(resource->m_vertices, sizeof(float) * resource->m_vertex_count);
 
-	stream->read(resource->data, (size_t)resource->length);
-	
-	resource->data[resource->length] = '\0';
+	// Read triangles
+	file->read(&resource->m_index_count, sizeof(uint32_t));
+	resource->m_indices = (uint16_t*) allocator.allocate(sizeof(uint16_t) * resource->m_index_count);
+	file->read(resource->m_indices, sizeof(uint16_t) * resource->m_index_count);
 
-	bundle.close(stream);
+	bundle.close(file);
 
 	return resource;
 }
 
 //-----------------------------------------------------------------------------
-void TextResource::unload(Allocator& allocator, void* resource)
+void MeshResource::online(void* )
 {
-	CE_ASSERT(resource != NULL, "Resource not loaded");
-
-	((TextResource*)resource)->length = 0;
-
-	allocator.deallocate(((TextResource*)resource)->data);
-	allocator.deallocate(resource);
 }
 
 //-----------------------------------------------------------------------------
-void TextResource::online(void* resource)
+void MeshResource::unload(Allocator& , void* )
 {
-	(void) resource;
 }
 
 //-----------------------------------------------------------------------------
-void TextResource::offline()
+void MeshResource::offline(void* /*resource*/)
 {
+
 }
 
 } // namespace crown

+ 22 - 9
engine/resource/PixelShaderResource.h → engine/resource/MeshResource.h

@@ -28,31 +28,44 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "Resource.h"
-#include "Renderer.h"
+#include "PixelFormat.h"
+#include "Texture.h"
 
 namespace crown
 {
 
+// Bump the version whenever a change in the format is made.
+const uint32_t MESH_VERSION = 1;
+
+struct MeshHeader
+{
+	uint32_t	version;
+	uint32_t	mesh_count;
+	uint32_t	joint_count;
+	uint32_t	padding[16];
+};
+
 class Bundle;
 class Allocator;
 
-class PixelShaderResource
+class MeshResource
 {
 public:
 
 	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			online(void* script);
 	static void			unload(Allocator& allocator, void* resource);
-	static void			offline();
+	static void			online(void* resource);
+	static void			offline(void* resource);
 
-	PixelShaderId		pixel_shader() const { return m_pixel_shader_id; }
+public:
 
-private:
+	MeshHeader			m_header;
 
-	uint32_t			m_program_text_length;
-	char*				m_program_text;
+	size_t				m_vertex_count;
+	float*				m_vertices;
 
-	PixelShaderId		m_pixel_shader_id;
+	size_t				m_index_count;
+	uint16_t*			m_indices;
 };
 
 } // namespace crown

+ 0 - 83
engine/resource/PixelShaderResource.cpp

@@ -1,83 +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 "PixelShaderResource.h"
-#include "DiskFile.h"
-#include "Bundle.h"
-#include "Allocator.h"
-#include "Device.h"
-#include "Log.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-void* PixelShaderResource::load(Allocator& allocator, Bundle& bundle, ResourceId id)
-{
-	DiskFile* stream = bundle.open(id);
-
-	CE_ASSERT(stream != NULL, "Resource does not exist: %.8X%.8X", id.name, id.type);
-
-	PixelShaderResource* resource = (PixelShaderResource*)allocator.allocate(sizeof(PixelShaderResource));
-
-	stream->read(&resource->m_program_text_length, sizeof(uint32_t));
-
-	resource->m_program_text = (char*)allocator.allocate(sizeof(char) * (resource->m_program_text_length + 1));
-
-	stream->read(resource->m_program_text, (size_t)resource->m_program_text_length);
-	
-	resource->m_program_text[resource->m_program_text_length] = '\0';
-
-	bundle.close(stream);
-
-	return resource;
-}
-
-//-----------------------------------------------------------------------------
-void PixelShaderResource::unload(Allocator& allocator, void* resource)
-{
-	CE_ASSERT(resource != NULL, "Resource not loaded");
-
-	((PixelShaderResource*)resource)->m_program_text_length = 0;
-
-	allocator.deallocate(((PixelShaderResource*)resource)->m_program_text);
-	allocator.deallocate(resource);
-}
-
-//-----------------------------------------------------------------------------
-void PixelShaderResource::online(void* resource)
-{
-	Renderer* renderer = device()->renderer();
-	PixelShaderResource* pixel_shader_resource = (PixelShaderResource*) resource;
-
-	pixel_shader_resource->m_pixel_shader_id = renderer->create_pixel_shader(pixel_shader_resource->m_program_text);
-}
-
-//-----------------------------------------------------------------------------
-void PixelShaderResource::offline()
-{
-}
-
-} // namespace crown

+ 24 - 16
engine/resource/Resource.h

@@ -39,8 +39,6 @@ const char* const MESH_EXTENSION			= "dae";
 const char* const SCRIPT_EXTENSION			= "lua";
 const char* const TEXT_EXTENSION			= "txt";
 const char* const MATERIAL_EXTENSION		= "material";
-const char* const VERTEX_SHADER_EXTENSION	= "vs";
-const char* const PIXEL_SHADER_EXTENSION	= "ps";
 const char* const SOUND_EXTENSION			= "wav";
 
 const uint32_t TEXTURE_TYPE					= 0x1410A16A;
@@ -48,17 +46,14 @@ const uint32_t MESH_TYPE					= 0xE8239EEC;
 const uint32_t SCRIPT_TYPE					= 0xD96E7C37;
 const uint32_t TEXT_TYPE					= 0x9000BF0B;
 const uint32_t MATERIAL_TYPE				= 0x46807A92;
-const uint32_t VERTEX_SHADER_TYPE			= 0xDC7F061F;
-const uint32_t PIXEL_SHADER_TYPE			= 0x2A461B45;
 const uint32_t SOUND_TYPE					= 0x8E128AA1;
 
-
 /// Enumerates the loading states of a resource
 enum ResourceState
 {
-	RS_UNLOADED		= 0,		//< The resource is not loaded, so it cannot be used
-	RS_LOADING		= 1,		//< The resource loader started to load the resource but it is yet not ready to use
-	RS_LOADED		= 2			//< The resource loader finished to load the texture meaning it can be used
+	RS_UNLOADED		= 0,		// The resource is not loaded, so it cannot be used
+	RS_LOADING		= 1,		// The resource loader started to load the resource but it is yet not ready to use
+	RS_LOADED		= 2			// The resource loader finished to load the texture meaning it can be used
 };
 
 /// ResourceId uniquely identifies a resource by its name and type.
@@ -66,14 +61,27 @@ enum ResourceState
 /// the index to the resource list where it is stored.
 struct ResourceId
 {
-	uint32_t		name;		// Hashed resource name
-	uint32_t		type;		// Hashed resource type
-	uint32_t		index;		// Index into the ResourceManager internal list
-
-	bool			operator==(const ResourceId& b)
-	{
-		return name == b.name && type == b.type && index == b.index;
-	}
+	bool operator==(const ResourceId& b) const { return name == b.name && type == b.type; }
+
+	uint32_t		name;
+	uint32_t		type;
+};
+
+class Allocator;
+class Bundle;
+
+typedef void*	(*ResourceLoadCallback)(Allocator& a, Bundle& b, ResourceId id);
+typedef void	(*ResourceUnloadCallback)(Allocator& a, void* resource);
+typedef void	(*ResourceOnlineCallback)(void* resource);
+typedef void	(*ResourceOfflineCallback)(void* resource);
+
+struct ResourceCallback
+{
+	uint32_t					type;
+	ResourceLoadCallback		on_load;
+	ResourceUnloadCallback		on_unload;
+	ResourceOnlineCallback		on_online;
+	ResourceOfflineCallback		on_offline;
 };
 
 } // namespace crown

+ 44 - 34
tools/compilers/vs/VSCompiler.cpp → engine/resource/ResourceLoader.cpp

@@ -24,69 +24,79 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "VSCompiler.h"
-#include "DiskFile.h"
-#include "Resource.h"
+#include "ResourceLoader.h"
+#include "ResourceRegistry.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-VSCompiler::VSCompiler(const char* root_path, const char* dest_path) :
-	Compiler(root_path, dest_path, VERTEX_SHADER_TYPE),
-	m_file_size(0),
-	m_file_data(NULL)
+ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
+	Thread("resource-loader"),
+	m_bundle(bundle),
+	m_resource_heap(resource_heap),
+	m_load_queue(default_allocator()),
+	m_done_queue(default_allocator())
 {
 }
 
 //-----------------------------------------------------------------------------
-VSCompiler::~VSCompiler()
+void ResourceLoader::load(ResourceId resource)
 {
-	cleanup_impl();
+	m_load_mutex.lock();
+	m_load_queue.push_back(resource);
+	m_load_requests.signal();
+	m_load_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
-size_t VSCompiler::read_header_impl(DiskFile* in_file)
+uint32_t ResourceLoader::remaining() const
 {
-	(void) in_file;
-	return 0;
+	return m_load_queue.size();
 }
 
 //-----------------------------------------------------------------------------
-size_t VSCompiler::read_resource_impl(DiskFile* in_file)
+uint32_t ResourceLoader::num_loaded() const
 {
-	m_file_size = in_file->size();
-
-	m_file_data = (char*)default_allocator().allocate(m_file_size * sizeof(char));
-	
-	// Copy the entire file into the buffer
-	in_file->read(m_file_data, m_file_size);
-
-	// Return total resource size
-	return m_file_size + sizeof(uint32_t);
+	return m_done_queue.size();
 }
 
 //-----------------------------------------------------------------------------
-void VSCompiler::write_header_impl(DiskFile* out_file)
+void ResourceLoader::get_loaded(List<LoadedResource>& l)
 {
-	out_file->write(&m_file_size, sizeof(uint32_t));
-}
+	m_done_mutex.lock();
+	for (uint32_t i = 0; i < m_done_queue.size(); i++)
+	{
+		l.push_back(m_done_queue[i]);
+	}
 
-//-----------------------------------------------------------------------------
-void VSCompiler::write_resource_impl(DiskFile* out_file)
-{
-	out_file->write(m_file_data, m_file_size);
+	m_done_queue.clear();
+	m_done_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
-void VSCompiler::cleanup_impl()
+int32_t ResourceLoader::run()
 {
-	if (m_file_data)
+	while (!is_terminating())
 	{
-		default_allocator().deallocate(m_file_data);
-		m_file_data = NULL;
+		m_load_mutex.lock();
+		while (m_load_queue.size() == 0)
+		{
+			m_load_requests.wait(m_load_mutex);
+		}
+
+		ResourceId resource = m_load_queue.front();
+		m_load_queue.pop_front();
+		m_load_mutex.unlock();
+
+		void* data = resource_on_load(resource.type, m_resource_heap, m_bundle, resource);
+
+		m_done_mutex.lock();
+		m_done_queue.push_back(LoadedResource(resource, data));
+		m_done_mutex.unlock();
 	}
+
+	return 0;
 }
 
 } // namespace crown
-

+ 43 - 10
engine/resource/VertexShaderResource.h → engine/resource/ResourceLoader.h

@@ -1,4 +1,5 @@
 /*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
 Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
 
 Permission is hereby granted, free of charge, to any person
@@ -27,31 +28,63 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "Resource.h"
-#include "Renderer.h"
+#include "Thread.h"
+#include "Queue.h"
+#include "List.h"
+#include "Mutex.h"
+#include "Cond.h"
 
 namespace crown
 {
 
+struct LoadedResource
+{
+	LoadedResource(ResourceId r, void* d) : resource(r), data(d) {}
+
+	ResourceId	resource;
+	void*		data;
+};
+
 class Bundle;
 class Allocator;
 
-class VertexShaderResource
+/// Loads resources in a background thread.
+class ResourceLoader : public Thread
 {
 public:
 
-	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			online(void* resource);
-	static void			unload(Allocator& allocator, void* resource);
-	static void			offline();
+	/// Reads the resources data from the given @a bundle using
+	/// @a resource_heap to allocate memory for them.
+				ResourceLoader(Bundle& bundle, Allocator& resource_heap);
+
+	/// Loads the @a resource in a background thread.
+	void		load(ResourceId resource);
 
-	VertexShaderId		vertex_shader() const { return m_vertex_shader_id; }
+	/// Returns the number of resources still in the loading queue.
+	uint32_t	remaining() const;
+
+	/// Returns the number of resources already loaded.
+	uint32_t	num_loaded() const;
+
+	/// Returns a list of the last loaded resources.
+	void		get_loaded(List<LoadedResource>& l);
+
+	// Loads resources in the loading queue.
+	int32_t		run();
 
 private:
 
-	uint32_t			m_program_text_length;
-	char*				m_program_text;
+	// Whether to look for resources
+	Bundle&					m_bundle;
+
+	// Used to strore resource memory
+	Allocator&				m_resource_heap;
 
-	VertexShaderId		m_vertex_shader_id;
+	Queue<ResourceId>		m_load_queue;
+	List<LoadedResource>	m_done_queue;
+	Mutex					m_load_mutex;
+	Mutex					m_done_mutex;
+	Cond					m_load_requests;
 };
 
 } // namespace crown

+ 56 - 296
engine/resource/ResourceManager.cpp

@@ -25,147 +25,72 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include <algorithm>
-#include <cstdio>
 
 #include "Types.h"
 #include "ResourceManager.h"
+#include "ResourceRegistry.h"
 #include "StringUtils.h"
 #include "Hash.h"
-#include "Path.h"
-#include "Log.h"
-#include "Device.h"
-#include "Filesystem.h"
-#include "TextReader.h"
-#include "DiskFile.h"
-#include "TextResource.h"
-#include "TextureResource.h"
-#include "VertexShaderResource.h"
-#include "PixelShaderResource.h"
-#include "SoundResource.h"
+#include "TempAllocator.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-ResourceManager::ResourceManager(Bundle& bundle) :
-	m_resource_bundle(bundle),
-	m_resources(m_allocator),
-	m_loading_queue(m_allocator),
-	m_loaded_queue(m_allocator),
-	m_seed(0),
-	m_background_thread_should_run(true),
-	m_thread(ResourceManager::background_thread, (void*)this, "resource-loader-thread")
+ResourceManager::ResourceManager(Bundle& bundle, uint32_t seed) :
+	m_resource_heap("resource", default_allocator()),
+	m_loader(bundle, m_resource_heap),
+	m_seed(seed),
+	m_resources(default_allocator())
 {
-	DiskFile* seed_file = device()->filesystem()->open("seed.ini", FOM_READ);
-	TextReader reader(*seed_file);
-
-	char tmp_buf[32];
-	reader.read_string(tmp_buf, 32);
-
-	device()->filesystem()->close(seed_file);
-
-	sscanf(tmp_buf, "%u", &m_seed);
+	m_loader.start();
 }
 
 //-----------------------------------------------------------------------------
 ResourceManager::~ResourceManager()
 {
-	m_background_thread_should_run = false;
+	m_loader.stop();
 }
 
 //-----------------------------------------------------------------------------
-ResourceId ResourceManager::load(const char* name)
+ResourceId ResourceManager::load(const char* type, const char* name)
 {
-	char basename[512];
-	char extension[512];
-
-	path::filename_without_extension(name, basename, 512);
-	path::extension(name, extension, 512);
-
-	uint32_t name_hash = hash::murmur2_32(basename, string::strlen(basename), m_seed);
-	uint32_t type_hash = hash::murmur2_32(extension, string::strlen(extension), 0);
 
-	Log::i("hash:%8X%.8X", name_hash, type_hash);
-
-	return load(name_hash, type_hash);
+	return load(resource_id(type, name));
 }
 
 //-----------------------------------------------------------------------------
 void ResourceManager::unload(ResourceId name)
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
-	
-	m_resources_mutex.lock();
-
-	ResourceEntry& entry = m_resources[name.index];
-	
-	entry.references--;
-	
-	if (entry.references == 0 && entry.state == RS_LOADED)
-	{
-		unload_by_type(name, entry.resource);
-
-		entry.state = RS_UNLOADED;
-		entry.resource = NULL;
-
-
-	}
 
-	m_resources_mutex.unlock();
-}
-
-//-----------------------------------------------------------------------------
-void ResourceManager::reload(ResourceId name)
-{
-	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
+	ResourceEntry* entry = find(name);
 	
-	m_resources_mutex.lock();
-
-	ResourceEntry& entry = m_resources[name.index];
+	entry->references--;
 	
-	if (entry.state == RS_LOADED)
+	if (entry->references == 0 && entry->state == RS_LOADED)
 	{
-		unload_by_type(name, entry.resource);
-
-		entry.state = RS_UNLOADED;
-		entry.resource = NULL;
+		resource_on_unload(name.type, m_resource_heap, entry->resource);
 
-		entry.resource = load_by_type(name);
-		entry.state = RS_LOADED;
+		entry->state = RS_UNLOADED;
+		entry->resource = NULL;
 	}
-
-	m_resources_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
 bool ResourceManager::has(ResourceId name) const
 {
-	bool has_resource = false;
-
-	m_resources_mutex.lock();
-
-	if (m_resources.size() > name.index)
-	{
-		 has_resource = (m_resources[name.index].id.name == name.name);
-	}
+	ResourceEntry* entry = find(name);
 
-	m_resources_mutex.unlock();
-	
-	return has_resource;
+	return entry != NULL;
 }
 
 //-----------------------------------------------------------------------------
 const void* ResourceManager::data(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
-	
-	m_resources_mutex.lock();
-
-	void* resource = m_resources[name.index].resource;
 
-	m_resources_mutex.unlock();
-
-	return resource;
+	return find(name)->resource;
 }
 
 //-----------------------------------------------------------------------------
@@ -173,13 +98,7 @@ bool ResourceManager::is_loaded(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
-	m_resources_mutex.lock();
-
-	bool loaded = m_resources[name.index].state == RS_LOADED;
-
-	m_resources_mutex.unlock();
-
-	return loaded;
+	return find(name)->state == RS_LOADED;
 }
 
 //-----------------------------------------------------------------------------
@@ -187,50 +106,15 @@ uint32_t ResourceManager::references(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
-	m_resources_mutex.lock();
-
-	bool loaded = m_resources[name.index].references;
-
-	m_resources_mutex.unlock();
-
-	return loaded;
-}
-
-//-----------------------------------------------------------------------------
-uint32_t ResourceManager::remaining() const
-{
-	uint32_t count = 0;
-
-	m_loading_mutex.lock();
-
-	count = m_loading_queue.size();
-
-	m_loading_mutex.unlock();
-
-	return count;
+	return find(name)->references;
 }
 
 //-----------------------------------------------------------------------------
 void ResourceManager::flush()
 {
-	check_load_queue();
+	while (m_loader.remaining() > 0) ;
 
-	while (true)
-	{
-		// Wait for all the resources to be loaded
-		// by the background thread
-		m_loading_mutex.lock();
-		while (m_loading_queue.size() > 0)
-		{
-			m_all_loaded.wait(m_loading_mutex);
-		}
-		m_loading_mutex.unlock();
-
-		// When all loaded, bring them online
-		bring_loaded_online();
-
-		return;
-	}
+	poll_resource_loader();
 }
 
 //-----------------------------------------------------------------------------
@@ -240,63 +124,61 @@ uint32_t ResourceManager::seed() const
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::check_load_queue()
+ResourceId ResourceManager::resource_id(const char* type, const char* name) const
 {
-	m_loading_mutex.lock();
-
-	if (m_loading_queue.size() > 0)
-	{
-		m_loading_requests.signal();
-	}
+	ResourceId id;
+	id.type = hash::murmur2_32(type, string::strlen(type), 0);
+	id.name = hash::murmur2_32(name, string::strlen(name), m_seed);
 
-	m_loading_mutex.unlock();
+	return id;
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::bring_loaded_online()
+ResourceEntry* ResourceManager::find(ResourceId id) const
 {
-	m_loaded_mutex.lock();
+	const ResourceEntry* entry = std::find(m_resources.begin(), m_resources.end(), id);
 
-	while (m_loaded_queue.size() > 0)
+	return entry != m_resources.end() ? const_cast<ResourceEntry*>(entry) : NULL;
+}
+
+//-----------------------------------------------------------------------------
+void ResourceManager::poll_resource_loader()
+{
+	if (m_loader.num_loaded() != 0)
 	{
-		LoadedResource lr = m_loaded_queue.front();
-		m_loaded_queue.pop_front();
+		TempAllocator1024 alloc;
+		List<LoadedResource> loaded(alloc);
+		m_loader.get_loaded(loaded);
 
-		online(lr.resource, lr.data);
+		for (uint32_t i = 0; i < loaded.size(); i++)
+		{
+			online(loaded[i].resource, loaded[i].data);
+		}
 	}
-
-	m_loaded_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
-ResourceId ResourceManager::load(uint32_t name, uint32_t type)
+ResourceId ResourceManager::load(ResourceId name)
 {
-	ResourceId id;
-	id.name = name;
-	id.type = type;
-
 	// Search for an already existent resource
-	ResourceEntry* entry = std::find(m_resources.begin(), m_resources.end(), id);
+	ResourceEntry* entry = find(name);
 
 	// If resource not found, create a new one
-	if (entry == m_resources.end())
+	if (entry == NULL)
 	{
-		id.index = m_resources.size();
-
 		ResourceEntry entry;
 
-		entry.id = id;
+		entry.id = name;
 		entry.state = RS_UNLOADED;
 		entry.references = 1;
 		entry.resource = NULL;
 
 		m_resources.push_back(entry);
 
-		m_loading_mutex.lock();
-		m_loading_queue.push_back(id);
-		m_loading_mutex.unlock();
+		// Issue request to resource loader
+		m_loader.load(name);
 
-		return id;
+		return name;
 	}
 
 	// Else, increment its reference count
@@ -305,136 +187,14 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 	return entry->id;
 }
 
-//-----------------------------------------------------------------------------
-void ResourceManager::background_load()
-{
-	while (m_background_thread_should_run)
-	{
-		m_loading_mutex.lock();
-		while (m_loading_queue.size() == 0)
-		{
-			m_loading_requests.wait(m_loading_mutex);
-		}
-
-		ResourceId resource = m_loading_queue.front();
-		m_loading_queue.pop_front();
-
-		m_loading_mutex.unlock();
-
-		void* data = load_by_type(resource);
-
-		LoadedResource lr;
-		lr.resource = resource;
-		lr.data = data;
-
-		m_loaded_mutex.lock();
-		m_loaded_queue.push_back(lr);
-		m_loaded_mutex.unlock();
-
-		m_loading_mutex.lock();
-		if (m_loading_queue.size() == 0)
-		{
-			m_all_loaded.signal();
-		}
-		m_loading_mutex.unlock();
-	}
-}
-
-//-----------------------------------------------------------------------------
-void* ResourceManager::load_by_type(ResourceId name)
-{
-	if (name.type == TEXTURE_TYPE)
-	{
-		return TextureResource::load(m_resource_allocator, m_resource_bundle, name);
-	}
-	else if (name.type == TEXT_TYPE)
-	{
-		return TextResource::load(m_resource_allocator, m_resource_bundle, name);
-	}
-	else if (name.type == VERTEX_SHADER_TYPE)
-	{
-		return VertexShaderResource::load(m_resource_allocator, m_resource_bundle, name);
-	}
-	else if (name.type == PIXEL_SHADER_TYPE)
-	{
-		return PixelShaderResource::load(m_resource_allocator, m_resource_bundle, name);
-	}
-	else if (name.type == SOUND_TYPE)
-	{
-		return SoundResource::load(m_resource_allocator, m_resource_bundle, name);
-	}
-
-	return NULL;
-}
-
-//-----------------------------------------------------------------------------
-void ResourceManager::unload_by_type(ResourceId name, void* resource)
-{
-	if (name.type == TEXTURE_TYPE)
-	{
-		TextureResource::unload(m_resource_allocator, resource);
-	}
-	else if (name.type == TEXT_TYPE)
-	{
-		TextResource::unload(m_resource_allocator, resource);
-	}
-	else if (name.type == VERTEX_SHADER_TYPE)
-	{
-		VertexShaderResource::unload(m_resource_allocator, resource);
-	}
-	else if (name.type == PIXEL_SHADER_TYPE)
-	{
-		PixelShaderResource::unload(m_resource_allocator, resource);
-	}
-	else if (name.type == SOUND_TYPE)
-	{
-		SoundResource::unload(m_resource_allocator, resource);
-	}
-
-	return;
-}
-
 //-----------------------------------------------------------------------------
 void ResourceManager::online(ResourceId name, void* resource)
 {
-	if (name.type == TEXTURE_TYPE)
-	{
-		TextureResource::online(resource);
-	}
-	else if (name.type == TEXT_TYPE)
-	{
-		TextResource::online(resource);
-	}
-	else if (name.type == VERTEX_SHADER_TYPE)
-	{
-		VertexShaderResource::online(resource);
-	}
-	else if (name.type == PIXEL_SHADER_TYPE)
-	{
-		PixelShaderResource::online(resource);
-	}
-	else if (name.type == SOUND_TYPE)
-	{
-		SoundResource::online(resource);
-	}
-
-	m_resources_mutex.lock();
-
-	ResourceEntry& entry = m_resources[name.index];
-	entry.resource = resource;
-	entry.state = RS_LOADED;
-
-	m_resources_mutex.unlock();
-}
-
-//-----------------------------------------------------------------------------
-void* ResourceManager::background_thread(void* thiz)
-{
-	ResourceManager* mgr = (ResourceManager*)thiz;
-
-	mgr->background_load();
+	resource_on_online(name.type, resource);
 
-	return NULL;
+	ResourceEntry* entry = find(name);
+	entry->resource = resource;
+	entry->state = RS_LOADED;
 }
 
 } // namespace crown

+ 29 - 90
engine/resource/ResourceManager.h

@@ -28,96 +28,63 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "List.h"
-#include "Queue.h"
 #include "Resource.h"
-#include "HeapAllocator.h"
-#include "Thread.h"
-#include "Mutex.h"
-#include "Cond.h"
+#include "ProxyAllocator.h"
+#include "ResourceLoader.h"
 
 namespace crown
 {
 
 struct ResourceEntry
 {
+	bool operator==(const ResourceId& resource) const { return id == resource; }
+	bool operator==(const ResourceEntry& b) const { return id == b.id; }
+
 	ResourceId		id;
 	ResourceState	state;
-
 	uint32_t		references;
-
 	void*			resource;
-
-	bool			operator==(const ResourceId& resource)
-					{
-						return id == resource;
-					}
-
-	bool			operator==(const ResourceEntry& b)
-					{
-						return id == b.id;
-					}
-};
-
-struct LoadedResource
-{
-	ResourceId	resource;
-	void*		data;
 };
 
 class Bundle;
 
-/// Resource manager.
+/// Keeps track and manages resources loaded by ResourceLoader.
 class ResourceManager
 {
 public:
 
-	/// Read resources from @a bundle and store resource data using @a allocator.
-							ResourceManager(Bundle& bundle);
+	/// The resources will be loaded from @a bundle.
+							ResourceManager(Bundle& bundle, uint32_t seed);
 							~ResourceManager();
 
-	/// Loads the resource by @a name and returns its ResourceId.
+	/// Loads the resource by @a type and @a name and returns its ResourceId.
 	/// @note
-	/// The resource data may be not immediately available,
-	/// the resource gets pushed in a queue of load requests and loadead as
-	/// soon as possible by the ResourceLoader.
-	/// You have to explicitly call is_loaded() method to check if the
-	/// loading process is actually completed.
-	ResourceId				load(const char* name);
-
-	/// Unloads the @a resource, freeing up all the memory associated by it
+	/// You have to call is_loaded() to check if the loading process is actually completed.
+	ResourceId				load(const char* type, const char* name);
+
+	/// Unloads the resource @a name, freeing up all the memory associated by it
 	/// and eventually any global object associated with it.
-	/// (Such as texture objects, vertex buffers etc.)
 	void					unload(ResourceId name);
 
-	/// Reloads the @a resource
-	void					reload(ResourceId name);
-
 	/// Returns whether the manager has the @a name resource into
 	/// its list of resources.
-	/// @note
+	/// @warning
 	/// Having a resource does not mean that the resource is
-	/// available for using; instead, you have to check is_loaded() to
-	/// obtain the resource availability status.
+	/// ready to be used; See is_loaded().
 	bool					has(ResourceId name) const;
 
 	/// Returns the data associated with the @a name resource.
-	/// The resource data contains resource-specific metadata
-	/// and the actual resource data. In order to correctly use
-	/// it, you have to know which type of data @a name refers to
-	/// and cast accordingly.
+	/// You will have to cast the returned pointer accordingly.
 	const void*				data(ResourceId name) const;
 	
 	/// Returns whether the @a name resource is loaded (i.e. whether
 	/// you can use the data associated with it).
 	bool					is_loaded(ResourceId name) const;
 
-	/// Returns the number of references to the @a resource
+	/// Returns the number of references to the resource @a name;
 	uint32_t				references(ResourceId name) const;
 
-	/// Returns the number of resources still waiting to load.
-	uint32_t				remaining() const;
-
-	/// Forces all the loading requests to complete before preceeding.
+	/// Forces all of the loading requests to complete before preceeding.
 	void					flush();
 
 	/// Returns the seed used to generate resource name hashes.
@@ -125,54 +92,26 @@ public:
 
 private:
 
-	// Checks the load queue and signal the backgroud about pending
-	// requests. It is normally called only by the Device.
-	void					check_load_queue();
-	// Calls online() on loaded resources. Must be called only
-	// in the main thread and generally only by Device.
-	void					bring_loaded_online();
+	ResourceId				resource_id(const char* type, const char* name) const;
 
-	// Loads the resource by name and type and returns its ResourceId.
-	ResourceId				load(uint32_t name, uint32_t type);
+	// Returns the entry of the given id.
+	ResourceEntry*			find(ResourceId id) const;
 
-	void					background_load();
+	// Polls the resource loader for loaded resources.
+	void					poll_resource_loader();
 
-	void*					load_by_type(ResourceId name);
-	void					unload_by_type(ResourceId name, void* resource);
+	// Loads the resource by name and type and returns its ResourceId.
+	ResourceId				load(ResourceId name);
 	void					online(ResourceId name, void* resource);
 
 private:
 
-	static void*			background_thread(void* thiz);
-
-private:
-
-	// Archive whether to look for resources
-	Bundle&					m_resource_bundle;
-	// Used to strore resource memory
-	HeapAllocator			m_resource_allocator;
-
-	HeapAllocator			m_allocator;
-	// The master lookup table
-	List<ResourceEntry>		m_resources;
-
-	// Resources waiting for loading
-	Queue<ResourceId>		m_loading_queue;
-	// Resources already loaded, ready to bring online
-	Queue<LoadedResource>	m_loaded_queue;
-
+	ProxyAllocator			m_resource_heap;
+	ResourceLoader			m_loader;
 	uint32_t				m_seed;
+	List<ResourceEntry>		m_resources;
 
-	// Background loading thread
-	bool 					m_background_thread_should_run;
-	os::Thread				m_thread;
-
-	mutable os::Mutex		m_loading_mutex;
-	os::Cond 				m_loading_requests;
-	os::Cond 				m_all_loaded;
-
-	os::Mutex				m_loaded_mutex;
-	mutable os::Mutex		m_resources_mutex;
+private:
 
 	friend class			Device;
 };

+ 45 - 36
tools/compilers/ps/PSCompiler.cpp → engine/resource/ResourceRegistry.cpp

@@ -24,69 +24,78 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "PSCompiler.h"
-#include "DiskFile.h"
-#include "Resource.h"
+#include "ResourceRegistry.h"
+#include "TextureResource.h"
+#include "MeshResource.h"
+#include "SoundResource.h"
 
 namespace crown
 {
 
-//-----------------------------------------------------------------------------
-PSCompiler::PSCompiler(const char* root_path, const char* dest_path) :
-	Compiler(root_path, dest_path, PIXEL_SHADER_TYPE),
-	m_file_size(0),
-	m_file_data(NULL)
+static const ResourceCallback RESOURCE_CALLBACK_REGISTRY[] =
 {
-}
+	{ TEXTURE_TYPE, TextureResource::load, TextureResource::unload, TextureResource::online, TextureResource::offline },
+	{ MESH_TYPE, MeshResource::load, MeshResource::unload, MeshResource::online, MeshResource::offline },
+	{ SOUND_TYPE, SoundResource::load, SoundResource::unload, SoundResource::online, SoundResource::offline },
+	{ 0, NULL, NULL, NULL, NULL }
+};
 
 //-----------------------------------------------------------------------------
-PSCompiler::~PSCompiler()
+static const ResourceCallback* find_callback(uint32_t type)
 {
-	cleanup_impl();
-}
+	const ResourceCallback* c = RESOURCE_CALLBACK_REGISTRY;
 
-//-----------------------------------------------------------------------------
-size_t PSCompiler::read_header_impl(DiskFile* in_file)
-{
-	(void) in_file;
-	return 0;
+	while (c->type != 0)
+	{
+		if (c->type == type)
+		{
+			return c;
+		}
+
+		c++;
+	}
+
+	return NULL;
 }
 
 //-----------------------------------------------------------------------------
-size_t PSCompiler::read_resource_impl(DiskFile* in_file)
+void* resource_on_load(uint32_t type, Allocator& allocator, Bundle& bundle, ResourceId id)
 {
-	m_file_size = in_file->size();
+	const ResourceCallback* c = find_callback(type);
 
-	m_file_data = (char*)default_allocator().allocate(m_file_size * sizeof(char));
-	
-	// Copy the entire file into the buffer
-	in_file->read(m_file_data, m_file_size);
+	CE_ASSERT_NOT_NULL(c);
 
-	// Return total resource size
-	return m_file_size + sizeof(uint32_t);
+	return c->on_load(allocator, bundle, id);
 }
 
 //-----------------------------------------------------------------------------
-void PSCompiler::write_header_impl(DiskFile* out_file)
+void resource_on_unload(uint32_t type, Allocator& allocator, void* resource)
 {
-	out_file->write(&m_file_size, sizeof(uint32_t));
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_unload(allocator, resource);
 }
 
 //-----------------------------------------------------------------------------
-void PSCompiler::write_resource_impl(DiskFile* out_file)
+void resource_on_online(uint32_t type, void* resource)
 {
-	out_file->write(m_file_data, m_file_size);
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_online(resource);
 }
 
 //-----------------------------------------------------------------------------
-void PSCompiler::cleanup_impl()
+void resource_on_offline(uint32_t type, void* resource)
 {
-	if (m_file_data)
-	{
-		default_allocator().deallocate(m_file_data);
-		m_file_data = NULL;
-	}
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_offline(resource);
 }
 
 } // namespace crown
-

+ 4 - 16
engine/resource/TextResource.h → engine/resource/ResourceRegistry.h

@@ -26,26 +26,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
 #include "Resource.h"
 
 namespace crown
 {
 
-class Bundle;
-class Allocator;
-
-class TextResource
-{
-public:
-
-	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			unload(Allocator& allocator, void* resource);
-	static void			online(void* resource);
-	static void			offline();
-
-	uint32_t			length;
-	char*				data;
-};
+void* resource_on_load(uint32_t type, Allocator& allocator, Bundle& bundle, ResourceId id);
+void resource_on_online(uint32_t type, void* resource);
+void resource_on_offline(uint32_t type, void* resource);
+void resource_on_unload(uint32_t type, Allocator& allocator, void* resource);
 
 } // namespace crown

+ 1 - 1
engine/resource/SoundResource.cpp

@@ -73,7 +73,7 @@ void SoundResource::unload(Allocator& allocator, void* resource)
 }
 
 //-----------------------------------------------------------------------------
-void SoundResource::offline()
+void SoundResource::offline(void* /*resource*/)
 {
 
 }

+ 2 - 2
engine/resource/SoundResource.h

@@ -51,9 +51,9 @@ class SoundResource
 public:
 
 	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			online(void* resource);
 	static void			unload(Allocator& allocator, void* resource);
-	static void			offline();
+	static void			online(void* resource);
+	static void			offline(void* resource);
 
 public:
 

+ 1 - 1
engine/resource/TextureResource.cpp

@@ -74,7 +74,7 @@ void TextureResource::unload(Allocator& allocator, void* resource)
 }
 
 //-----------------------------------------------------------------------------
-void TextureResource::offline()
+void TextureResource::offline(void* /*resource*/)
 {
 
 }

+ 2 - 2
engine/resource/TextureResource.h

@@ -53,9 +53,9 @@ class TextureResource
 public:
 
 	static void*		load(Allocator& allocator, Bundle& bundle, ResourceId id);
-	static void			online(void* resource);
 	static void			unload(Allocator& allocator, void* resource);
-	static void			offline();
+	static void			online(void* resource);
+	static void			offline(void* resource);
 
 public:
 

+ 0 - 83
engine/resource/VertexShaderResource.cpp

@@ -1,83 +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 "VertexShaderResource.h"
-#include "DiskFile.h"
-#include "Bundle.h"
-#include "Allocator.h"
-#include "Device.h"
-#include "Log.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-void* VertexShaderResource::load(Allocator& allocator, Bundle& bundle, ResourceId id)
-{
-	DiskFile* stream = bundle.open(id);
-
-	CE_ASSERT(stream != NULL, "Resource does not exist: %.8X%.8X", id.name, id.type);
-
-	VertexShaderResource* resource = (VertexShaderResource*)allocator.allocate(sizeof(VertexShaderResource));
-
-	stream->read(&resource->m_program_text_length, sizeof(uint32_t));
-
-	resource->m_program_text = (char*)allocator.allocate(sizeof(char) * (resource->m_program_text_length + 1));
-
-	stream->read(resource->m_program_text, (size_t)resource->m_program_text_length);
-	
-	resource->m_program_text[resource->m_program_text_length] = '\0';
-
-	bundle.close(stream);
-
-	return resource;
-}
-
-//-----------------------------------------------------------------------------
-void VertexShaderResource::unload(Allocator& allocator, void* resource)
-{
-	CE_ASSERT(resource != NULL, "Resource not loaded");
-
-	((VertexShaderResource*)resource)->m_program_text_length = 0;
-
-	allocator.deallocate(((VertexShaderResource*)resource)->m_program_text);
-	allocator.deallocate(resource);
-}
-
-//-----------------------------------------------------------------------------
-void VertexShaderResource::online(void* resource)
-{
-	Renderer* renderer = device()->renderer();
-	VertexShaderResource* vertex_shader_resource = (VertexShaderResource*) resource;
-
-	vertex_shader_resource->m_vertex_shader_id = renderer->create_vertex_shader(vertex_shader_resource->m_program_text);
-}
-
-//-----------------------------------------------------------------------------
-void VertexShaderResource::offline()
-{
-}
-
-} // namespace crown

+ 0 - 2
tests/CMakeLists.txt → engine/tests/CMakeLists.txt

@@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 2.8)
 
 project(crown-tests)
 
-link_directories(${CROWN_BINARY_DIR})
-
 enable_testing()
 
 add_executable(allocators allocators.cpp)

+ 0 - 0
tests/allocators.cpp → engine/tests/allocators.cpp


+ 1 - 1
tests/compressors.cpp → engine/tests/compressors.cpp

@@ -5,7 +5,7 @@
 
 using namespace crown;
 
-int main(int argc, char** argv)
+int main()
 {
 	
 	HeapAllocator allocator;

+ 0 - 0
tests/containers.cpp → engine/tests/containers.cpp


+ 0 - 0
tests/messages.cpp → engine/tests/messages.cpp


+ 0 - 0
tests/paths.cpp → engine/tests/paths.cpp


+ 0 - 0
tests/strings.cpp → engine/tests/strings.cpp


+ 21 - 19
samples/CMakeLists.txt

@@ -4,21 +4,23 @@ project(crown-samples)
 
 # platform independent includes
 set (CROWN_INCLUDES
-	${CMAKE_SOURCE_DIR}/src
-	${CMAKE_SOURCE_DIR}/src/core
-	${CMAKE_SOURCE_DIR}/src/core/bv
-	${CMAKE_SOURCE_DIR}/src/core/containers
-	${CMAKE_SOURCE_DIR}/src/core/math
-	${CMAKE_SOURCE_DIR}/src/core/mem
-	${CMAKE_SOURCE_DIR}/src/core/compressors
-	${CMAKE_SOURCE_DIR}/src/core/filesystem
-	${CMAKE_SOURCE_DIR}/src/core/strings
-	${CMAKE_SOURCE_DIR}/src/core/settings
-	${CMAKE_SOURCE_DIR}/src/os
-	${CMAKE_SOURCE_DIR}/src/input
-	${CMAKE_SOURCE_DIR}/src/renderers
-	${CMAKE_SOURCE_DIR}/src/network
-	${CMAKE_SOURCE_DIR}/src/lua
+	${CMAKE_SOURCE_DIR}/engine
+	${CMAKE_SOURCE_DIR}/engine/core
+	${CMAKE_SOURCE_DIR}/engine/core/bv
+	${CMAKE_SOURCE_DIR}/engine/core/containers
+	${CMAKE_SOURCE_DIR}/engine/core/math
+	${CMAKE_SOURCE_DIR}/engine/core/mem
+	${CMAKE_SOURCE_DIR}/engine/core/compressors
+	${CMAKE_SOURCE_DIR}/engine/core/filesystem
+	${CMAKE_SOURCE_DIR}/engine/core/json
+	${CMAKE_SOURCE_DIR}/engine/core/strings
+	${CMAKE_SOURCE_DIR}/engine/core/settings
+	${CMAKE_SOURCE_DIR}/engine/os
+	${CMAKE_SOURCE_DIR}/engine/input
+	${CMAKE_SOURCE_DIR}/engine/renderers
+	${CMAKE_SOURCE_DIR}/engine/resource
+	${CMAKE_SOURCE_DIR}/engine/network
+	${CMAKE_SOURCE_DIR}/engine/lua
 )
 
 # detect operating system
@@ -26,8 +28,8 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
 	set (LINUX 1)
 
 	list (APPEND CROWN_INCLUDES
-		${CMAKE_SOURCE_DIR}/src/os/linux
-		${CMAKE_SOURCE_DIR}/src/renderers/glx
+		${CMAKE_SOURCE_DIR}/engine/os/linux
+		${CMAKE_SOURCE_DIR}/engine/renderers/glx
 	)
 endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
 
@@ -35,8 +37,8 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
 	set(WINDOWS 1)
 
 	list (APPEND CROWN_INCLUDES
-		${CMAKE_SOURCE_DIR}/src/os/win
-		${CMAKE_SOURCE_DIR}/src/renderers/gl/wgl
+		${CMAKE_SOURCE_DIR}/engine/os/win
+		${CMAKE_SOURCE_DIR}/engine/renderers/gl/wgl
 	)
 endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
 

+ 5 - 4
tools/CMakeLists.txt

@@ -10,6 +10,7 @@ set (INCLUDES
 	${CMAKE_SOURCE_DIR}/tools/compilers
 	${CMAKE_SOURCE_DIR}/tools/compilers/tga
 	${CMAKE_SOURCE_DIR}/tools/compilers/wav
+	${CMAKE_SOURCE_DIR}/tools/compilers/dae
 )
 
 set (CORE_SRC
@@ -35,16 +36,16 @@ set (COMPILERS_SRC
 	compilers/Compiler.cpp
 	compilers/tga/TGACompiler.cpp
 	compilers/wav/WAVCompiler.cpp
-#	compilers/ps/PSCompiler.cpp
-#	compilers/vs/VSCompiler.cpp
+	compilers/dae/DAECompiler.cpp
+	compilers/dae/tinyxml2.cpp
 )
 
 set (COMPILER_HEADERS
 	compilers/Compiler.h
 	compilers/tga/TGACompiler.h
 	compilers/wav/WAVCompiler.h
-#	compilers/ps/PSCompiler.h
-#	compilers/vs/VSCompiler.h
+	compilers/dae/DAECompiler.h
+	compilers/dae/tinyxml2.h
 )
 
 set (TOOLS_SRC

+ 80 - 68
tools/cli/resource-compiler.cpp

@@ -24,7 +24,9 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <cstdio>
+#include <iostream>
+#include <string>
+#include <map>
 
 #include "Args.h"
 #include "Path.h"
@@ -32,71 +34,35 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Hash.h"
 #include "TGACompiler.h"
 #include "WAVCompiler.h"
+#include "DAECompiler.h"
 
 using namespace crown;
+using std::cout;
+using std::endl;
+using std::ofstream;
+using std::map;
 
 // Max number of requests per run
-const uint32_t MAX_COMPILE_REQUESTS = 512;
-
+const uint32_t	MAX_COMPILE_REQUESTS = 512;
 const char*		root_path = NULL;
 const char*		dest_path = NULL;
 uint32_t		hash_seed = 0;
 
-// Help functions
-int32_t			parse_command_line(int argc, char* argv[]);
-void			print_help_message(const char* program_name);
-void			check_arguments(const char* root_path, const char* dest_path);
-void			compile_by_type(const char* resource);
-
 //-----------------------------------------------------------------------------
-int main(int argc, char** argv)
+static void print_help_message(const char* program_name)
 {
-	int32_t first_resource = parse_command_line(argc, argv);
-
-	// Check if all the mandatory options are set
-	check_arguments(root_path, dest_path);
-
-	// If there are no resources
-	if (first_resource >= argc)
-	{
-		printf("you have to specify at least one resource.");
-		exit(EXIT_FAILURE);
-	}
-
-
-	TGACompiler tga;
-	WAVCompiler wav;
-
-	char out_name[1024];
-	char resource_name[1024];
-	char resource_type[1024];
-
-	for (int32_t i = 0; i < argc - first_resource; i++)
-	{
-		path::filename_without_extension(argv[first_resource + i], resource_name, 1024);
-		path::extension(argv[first_resource + i], resource_type, 1024);
-
-		snprintf(out_name, 1024, "%.8X%.8X",
-			hash::murmur2_32(resource_name, string::strlen(resource_name), hash_seed),
-			hash::murmur2_32(resource_type, string::strlen(resource_type), 0));
-
-		printf("%s <= %s\n", out_name, argv[first_resource + i]);
-
-		if (string::strcmp(resource_type, "tga") == 0)
-		{
-			tga.compile(root_path, dest_path, argv[first_resource + i], out_name);
-		}
-		else if (string::strcmp(resource_type, "wav") == 0)
-		{
-			wav.compile(root_path, dest_path, argv[first_resource + i], out_name);
-		}
-	}
+	cout << "Usage: " << program_name << " [options] [resources]" << endl;
+	cout <<
+		"Options:\n\n"
 
-	return 0;
+		"  --help                  Show this help.\n"
+		"  --root-path <path>      The absolute <path> whether to look for the input resources.\n"
+		"  --dest-path <path>      The absolute <path> whether to put the compiled resources.\n"
+		"  --seed <value>          The seed to use for generating output resource hashes.\n";
 }
 
 //-----------------------------------------------------------------------------
-int32_t parse_command_line(int argc, char* argv[])
+static int32_t parse_command_line(int argc, char* argv[])
 {
 	// Parse arguments
 	static ArgsOption options[] = 
@@ -147,32 +113,78 @@ int32_t parse_command_line(int argc, char* argv[])
 }
 
 //-----------------------------------------------------------------------------
-void print_help_message(const char* program_name)
+static void check_arguments(const char* root_path, const char* dest_path)
 {
-	printf("Usage: %s [options] [resources]\n", program_name);
-	printf
-	(
-		"Options:\n\n"
+	if (root_path == NULL)
+	{
+		cout << "you have to specify the root path with `--root-path`" << endl;
+		exit(EXIT_FAILURE);
+	}
 
-		"  --help                  Show this help.\n"
-		"  --root-path <path>      The absolute <path> whether to look for the input resources.\n"
-		"  --dest-path <path>      The absolute <path> whether to put the compiled resources.\n"
-		"  --seed <value>          The seed to use for generating output resource hashes.\n"
-	);
+	if (dest_path == NULL)
+	{
+		cout << "you have to specify the destination path with `--dest-path`" << endl;
+		exit(EXIT_FAILURE);
+	}
 }
 
 //-----------------------------------------------------------------------------
-void check_arguments(const char* root_path, const char* dest_path)
+int main(int argc, char** argv)
 {
-	if (root_path == NULL)
+	int32_t first_resource = parse_command_line(argc, argv);
+
+	// Check if all the mandatory options are set
+	check_arguments(root_path, dest_path);
+
+	// If there are no resources
+	if (first_resource >= argc)
 	{
-		printf("you have to specify the root path with `--root-path`\n");
+		cout << "You have to specify at least one resource." << endl;
 		exit(EXIT_FAILURE);
 	}
 
-	if (dest_path == NULL)
+	// Register compilers
+	TGACompiler tga;
+	WAVCompiler wav;
+	DAECompiler dae;
+
+	map<std::string, Compiler*> compilers;
+	compilers["tga"] = &tga;
+	compilers["wav"] = &wav;
+	compilers["dae"] = &dae;
+
+	for (int32_t i = 0; i < argc - first_resource; i++)
 	{
-		printf("you have to specify the destination path with `--dest-path`\n");
-		exit(EXIT_FAILURE);
+		const char* resource = argv[first_resource + i];
+
+		char resource_name[1024];
+		char resource_type[1024];
+		path::filename_without_extension(resource, resource_name, 1024);
+		path::extension(resource, resource_type, 1024);
+
+		uint32_t resource_name_hash = hash::murmur2_32(resource_name, string::strlen(resource_name), hash_seed);
+		uint32_t resource_type_hash = hash::murmur2_32(resource_type, string::strlen(resource_type), 0);
+
+		char out_name[1024];
+		snprintf(out_name, 1024, "%.8X%.8X", resource_name_hash, resource_type_hash);
+
+		cout << out_name << " <= " << resource << endl;
+
+		map<std::string, Compiler*>::iterator it = compilers.find(resource_type);
+		if (it != compilers.end())
+		{
+			if (!it->second->compile(root_path, dest_path, resource, out_name))
+			{
+				cout << "Exiting." << endl;
+				exit(EXIT_FAILURE);
+			}
+		}
+		else
+		{
+			cout << "No compilers found for type '" << resource_type << "'." << endl;
+			exit(EXIT_FAILURE);
+		}
 	}
+
+	return 0;
 }

+ 17 - 14
tools/compilers/Compiler.cpp

@@ -31,11 +31,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Compiler.h"
 #include "ResourceFormat.h"
 
+using std::cout;
+using std::endl;
+
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-size_t Compiler::compile(const char* root_path, const char* dest_path, const char* name_in, const char* name_out)
+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);
@@ -44,8 +47,8 @@ size_t Compiler::compile(const char* root_path, const char* dest_path, const cha
 	size_t resource_size = 0;
 	if ((resource_size = compile_impl(path_in.c_str())) == 0)
 	{
-		std::cout << "Compilation failed." << std::endl;
-		return 0;
+		cout << "Compilation failed." << endl;
+		return false;
 	}
 
 	// Setup resource header
@@ -58,21 +61,21 @@ size_t Compiler::compile(const char* root_path, const char* dest_path, const cha
 	std::fstream out_file;
 	out_file.open(path_out.c_str(), std::fstream::out | std::fstream::binary);
 
-	if (!out_file.is_open())
+	if (out_file.is_open())
 	{
-		std::cout << "Unable to write compiled file." << std::endl;
-		return 0;
-	}
+		// 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();
 
-	// Write resource-specific data
-	write_impl(out_file);
-
-	out_file.close();
+		cleanup();
+		return true;
+	}
 
-	// Cleanup
-	cleanup();
+	cout << "Unable to write compiled file." << endl;
+	return false;
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 1
tools/compilers/Compiler.h

@@ -43,7 +43,7 @@ public:
 
 	virtual					~Compiler() {}
 
-	size_t					compile(const char* root_path, const char* dest_path, const char* name_in, const char* name_out);
+	bool					compile(const char* root_path, const char* dest_path, const char* name_in, const char* name_out);
 	void					cleanup();
 
 protected:

+ 633 - 0
tools/compilers/dae/DAECompiler.cpp

@@ -0,0 +1,633 @@
+/*
+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 <iostream>
+#include <sstream>
+#include "DAECompiler.h"
+
+using tinyxml2::XMLDocument;
+using tinyxml2::XMLElement;
+using tinyxml2::XML_NO_ERROR;
+using tinyxml2::XML_NO_ATTRIBUTE;
+using std::vector;
+using std::cout;
+using std::endl;
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+DAECompiler::DAECompiler()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+DAECompiler::~DAECompiler()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+size_t DAECompiler::compile_impl(const char* resource_path)
+{
+	DAEModel model;
+
+	if (!parse_collada(resource_path, model))
+	{
+		return 0;
+	}
+
+	// Check that polylist is composed of triangles
+	const vector<uint32_t>& vcount = model.geometries[0].mesh.polylist.vcount;
+	for (uint32_t i = 0; i < vcount.size(); i++)
+	{
+		if (vcount[i] != 3)
+		{
+			cout << "Bad polylist: only triangle primitives allowed." << endl;
+			return false;
+		}
+	}
+
+	// Find vertices
+	DAESource vertex_source;
+	if (!find_vertices(model.geometries[0].mesh, vertex_source))
+	{
+		return false;
+	}
+
+	const vector<float>& vertex_vertices = vertex_source.float_array.array;
+	m_vertex_vertices = vertex_vertices;
+
+	vector<uint16_t> vertex_indices;
+	if (!extract_vertex_indices(model.geometries[0].mesh, vertex_indices))
+	{
+		return false;
+	}
+
+	m_vertex_indices = vertex_indices;
+
+	// cout << "Vertices: " << vertex_vertices.size() << endl;
+	// cout << "Indices: " << vertex_indices.size() << endl;
+
+	m_mesh_header.version = MESH_VERSION;
+	m_mesh_header.mesh_count = 1;
+	m_mesh_header.joint_count = 0;
+	//m_mesh_header.padding[0] = 0xCECECECE;
+
+	return sizeof(MeshHeader) +
+			sizeof(uint32_t) + vertex_vertices.size() * sizeof(float) +
+			sizeof(uint32_t) + vertex_indices.size() * sizeof(uint16_t);
+}
+
+//-----------------------------------------------------------------------------
+void DAECompiler::write_impl(std::fstream& out_file)
+{
+	out_file.write((char*) &m_mesh_header, sizeof(MeshHeader));
+
+	uint32_t vertex_count = m_vertex_vertices.size();
+	out_file.write((char*)&vertex_count, sizeof(uint32_t));
+	out_file.write((char*) m_vertex_vertices.data(), m_vertex_vertices.size() * sizeof(float));
+
+	uint32_t triangle_count = m_vertex_indices.size();
+	out_file.write((char*)&triangle_count, sizeof(uint32_t));
+	out_file.write((char*) m_vertex_indices.data(), m_vertex_indices.size() * sizeof(uint16_t));
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_collada(const char* path, DAEModel& m)
+{
+	XMLDocument doc;
+
+	if (doc.LoadFile(path) != XML_NO_ERROR)
+	{
+		cout << "Unable to open '" << path << "'." << endl;
+		return false;
+	}
+
+	// Read root
+	XMLElement* root_node = doc.FirstChildElement("COLLADA");
+	if (root_node == NULL)
+	{
+		cout << "Bad document: missing COLLADA root element." << endl;
+		return false;
+	}
+
+	// Read geometries
+	XMLElement* library_geometries = root_node->FirstChildElement("library_geometries");
+	if (library_geometries == NULL)
+	{
+		cout << "Bad document: missing geometries library." << endl;
+		return false;
+	}
+
+	XMLElement* geometry = library_geometries->FirstChildElement("geometry");
+	if (geometry == NULL)
+	{
+		cout << "Bad document: no geometries found." << endl;
+		return false;
+	}
+
+	for (; geometry != NULL; geometry = geometry->NextSiblingElement("geometry"))
+	{
+		DAEGeometry g;
+		if (parse_geometry(geometry, g))
+		{
+			m.geometries.push_back(g);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
+{
+	// Read geometry id
+	const char* geom_id = geometry->Attribute("id");
+	if (geom_id == NULL)
+	{
+		cout << "Bad geometry: missing 'id' attribute." << endl;
+		return false;
+	}
+
+	g.id = geom_id;
+
+	// Read geometry name
+	const char* geom_name = geometry->Attribute("name");
+	if (geom_name == NULL)
+	{
+		cout << "Bad geometry: missing 'name' attribute." << endl;
+		return false;
+	}
+
+	g.name = geom_name;
+
+	// Read geometry mesh
+	XMLElement* mesh = geometry->FirstChildElement("mesh");
+	if (mesh == NULL)
+	{
+		cout << "Bad geometry: no meshes found." << endl;
+		return false;
+	}
+
+	// Actually, there is more stuff to parse
+	return parse_mesh(mesh, g.mesh);
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
+{
+	/// Read sources
+	XMLElement* source = mesh->FirstChildElement("source");
+	if (source == NULL)
+	{
+		cout << "Bad mesh: no sources found." << endl;
+		return false;
+	}
+
+	for (; source != NULL; source = source->NextSiblingElement("source"))
+	{
+		DAESource s;
+		if (parse_source(source, s))
+		{
+			m.sources.push_back(s);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	// Read vertices
+	XMLElement* vertices = mesh->FirstChildElement("vertices");
+	if (vertices == NULL)
+	{
+		cout << "Bad mesh: no vertices found." << endl;
+		return false;
+	}
+
+	if (!parse_vertices(vertices, m.vertices))
+	{
+		return false;
+	}
+
+	// Read polylist
+	XMLElement* polylist = mesh->FirstChildElement("polylist");
+	if (polylist == NULL)
+	{
+		cout << "Bad mesh: no polylist found." << endl;
+		return false;
+	}
+
+	return parse_polylist(polylist, m.polylist);
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_source(XMLElement* source, DAESource& s)
+{
+	// Read source id
+	const char* source_id = source->Attribute("id");
+	if (source_id == NULL)
+	{
+		cout << "Bad source: missing 'id' attribute." << endl;
+		return false;
+	}
+
+	s.id = source_id;
+
+	// Read float array
+	XMLElement* float_array = source->FirstChildElement("float_array");
+	if (float_array == NULL)
+	{
+		cout << "Bad source: no 'float_array' found." << endl;
+		return false;
+	}
+
+	if (!parse_float_array(float_array, s.float_array))
+	{
+		return false;
+	}
+
+	// Read technique
+	XMLElement* technique_common = source->FirstChildElement("technique_common");
+	if (technique_common == NULL)
+	{
+		cout << "Bad source: no 'technique_common' found." << endl;
+		return false;
+	}
+
+	if (!parse_technique_common(technique_common, s.technique_common))
+	{
+		return false;
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
+{
+	// Read float array id
+	const char* float_array_id = array->Attribute("id");
+	if (float_array_id == NULL)
+	{
+		cout << "Bad float array: missing 'id' attribute." << endl;
+		return false;
+	}
+
+	a.id = float_array_id;
+
+	// Read number of floats
+	uint32_t count = 0;
+	if (array->QueryUnsignedAttribute("count", &count) != XML_NO_ERROR)
+	{
+		cout << "Bad float array: missing 'count' attribute." << endl;
+		return false;
+	}
+
+	std::istringstream floats(array->GetText());
+	for (uint32_t i = 0; i < count; i++)
+	{
+		float out = 0.0f;
+		floats >> out;
+		a.array.push_back(out);
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
+{
+	// Read accessor
+	XMLElement* accessor = technique->FirstChildElement("accessor");
+	if (accessor == NULL)
+	{
+		cout << "Bad technique: no accessors found." << endl;
+		return false;
+	}
+
+	return parse_accessor(accessor, t.accessor);
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
+{
+	// Read accessor source
+	const char* accessor_source = accessor->Attribute("source");
+	if (accessor_source == NULL)
+	{
+		cout << "Bad accessor: missing 'source' attribute." << endl;
+		return false;
+	}
+
+	// First char is '#'
+	a.source = &accessor_source[1];
+
+	// Read accessor count
+	if (accessor->QueryUnsignedAttribute("count", &a.count) != XML_NO_ERROR)
+	{
+		cout << "Bad accessor: missing 'count' attribute." << endl;
+		return false;
+	}
+
+	// Read accessor stride
+	if (accessor->QueryUnsignedAttribute("stride", &a.stride) != XML_NO_ERROR)
+	{
+		cout << "Bad accessor: missing 'stride' attribute." << endl;
+		return false;
+	}
+
+	// Read params
+	XMLElement* param = accessor->FirstChildElement("param");
+	if (param == NULL)
+	{
+		cout << "Bad accessor: no params found." << endl;
+		return false;
+	}
+
+	for (; param != NULL; param = param->NextSiblingElement("param"))
+	{
+		DAEParam p;
+		if (parse_param(param, p))
+		{
+			a.params.push_back(p);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_param(XMLElement* param, DAEParam& p)
+{
+	// Read param name
+	const char* param_name = param->Attribute("name");
+	if (param_name == NULL)
+	{
+		cout << "Bad param: missing 'name' attribute." << endl;
+		return false;
+	}
+
+	p.name = param_name;
+
+	// Read param type
+	const char* param_type = param->Attribute("type");
+	if (param_type == NULL)
+	{
+		cout << "Bad param: missing 'type' attribute." << endl;
+		return false;
+	}
+
+	p.type = param_type;
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
+{
+	// Read vertices id
+	const char* vertices_id = vertices->Attribute("id");
+	if (vertices_id == NULL)
+	{
+		cout << "Bad vertices: missing 'id' attribute." << endl;
+		return false;
+	}
+
+	v.id = vertices_id;
+
+	// Read inputs
+	XMLElement* input = vertices->FirstChildElement("input");
+	if (input == NULL)
+	{
+		cout << "Bad vertices: no inputs found." << endl;
+		return false;
+	}
+
+	for (; input != NULL; input = input->NextSiblingElement("input"))
+	{
+		DAEInput i;
+		if (parse_input(input, i))
+		{
+			v.inputs.push_back(i);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_input(XMLElement* input, DAEInput& i)
+{
+	// Read input semantic
+	const char* input_semantic = input->Attribute("semantic");
+	if (input_semantic == NULL)
+	{
+		cout << "Bad input: missing 'semantic' attribute." << endl;
+		return false;
+	}
+
+	i.semantic = input_semantic;
+
+	// Read input source
+	const char* input_source = input->Attribute("source");
+	if (input_source == NULL)
+	{
+		cout << "Bad input: missing 'source' attribute." << endl;
+		return false;
+	}
+
+	// First char is '#'
+	i.source = &input_source[1];
+
+	if (input->QueryUnsignedAttribute("offset", &i.offset) == XML_NO_ATTRIBUTE)
+	{
+		i.offset = 0;
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
+{
+	// Read polylist count
+	if (polylist->QueryUnsignedAttribute("count", &p.count) != XML_NO_ERROR)
+	{
+		cout << "Bad polylist: missing 'count' attribute." << endl;
+		return false;
+	}
+
+	// Read inputs
+	XMLElement* input = polylist->FirstChildElement("input");
+	if (input == NULL)
+	{
+		cout << "Bad polylist: no inputs found." << endl;
+		return false;
+	}
+
+	for (; input != NULL; input = input->NextSiblingElement("input"))
+	{
+		DAEInput i;
+		if (parse_input(input, i))
+		{
+			p.inputs.push_back(i);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	// Read vcount
+	XMLElement* vcount = polylist->FirstChildElement("vcount");
+	if (vcount == NULL)
+	{
+		cout << "Bad polylist: no vcount found." << endl;
+		return false;
+	}
+
+	std::istringstream vcount_text(vcount->GetText());
+	uint32_t vcount_item = 0;
+	while (vcount_text >> vcount_item)
+	{
+		p.vcount.push_back(vcount_item);
+	}
+
+	// Read p
+	XMLElement* p_element = polylist->FirstChildElement("p");
+	if (p_element == NULL)
+	{
+		cout << "Bad polylist: no p found." << endl;
+		return false;
+	}
+
+	std::istringstream p_text(p_element->GetText());
+	uint32_t p_item = 0;
+	while (p_text >> p_item)
+	{
+		p.p.push_back(p_item);
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
+{
+	const vector<DAESource>& sources = mesh.sources;
+	const vector<DAEInput>& inputs = mesh.vertices.inputs;
+
+	for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
+	{
+		const DAEInput& input = inputs[input_i];
+
+		for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
+		{
+			const DAESource& source = sources[source_i];
+
+			if (input.semantic == "POSITION" && input.source == source.id)
+			{
+				source_out = source;
+				return true;
+			}
+		}
+	}
+
+	cout << "Failed to find 'POSITION' source." << endl;
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
+{
+	const vector<DAESource>& sources = mesh.sources;
+	const vector<DAEInput>& inputs = mesh.polylist.inputs;
+
+	for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
+	{
+		const DAEInput& input = inputs[input_i];
+
+		for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
+		{
+			const DAESource& source = sources[source_i];
+
+			cout << input.semantic << " " << input.source << " " << source.id << endl;
+			if (input.semantic == "NORMAL" && input.source == source.id)
+			{
+				source_out = source;
+				return true;
+			}
+		}
+	}
+
+	cout << "Failed to find 'NORMAL' source." << endl;
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+bool DAECompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
+{
+	// Find vertices
+	DAESource vertex_source;
+	if (!find_vertices(mesh, vertex_source))
+	{
+		return false;
+	}
+
+	// Read vertices
+	const vector<uint32_t>& primitives = mesh.polylist.p;
+	const vector<float>& vertices = vertex_source.float_array.array;
+
+	// FIXME FIXME FIXME
+	uint32_t offset = 0;
+	uint32_t attribs = mesh.polylist.inputs.size();
+
+	uint32_t prims = 0;
+	while(prims < primitives.size())
+	{
+		indices_out.push_back((uint16_t) primitives[prims]);
+		prims += attribs;
+	}
+
+	return true;
+}
+
+} // namespace crown

+ 165 - 0
tools/compilers/dae/DAECompiler.h

@@ -0,0 +1,165 @@
+/*
+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 <map>
+#include <string>
+#include <vector>
+
+#include "Compiler.h"
+#include "MeshFormat.h"
+#include "tinyxml2.h"
+
+using tinyxml2::XMLElement;
+using std::vector;
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+struct DAEFloatArray
+{
+	std::string				id;		// UUID of the array
+	std::vector<float>		array;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEParam
+{
+	std::string				name;
+	std::string				type;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEAccessor
+{
+	std::string				source;
+	uint32_t				count;
+	uint32_t				stride;
+	std::vector<DAEParam>	params;	
+};
+
+//-----------------------------------------------------------------------------
+struct DAETechniqueCommon
+{
+	DAEAccessor				accessor;
+};
+
+//-----------------------------------------------------------------------------
+struct DAESource
+{
+	std::string 			id;					// UUID of the source
+	DAEFloatArray			float_array;		// Array of floats
+	DAETechniqueCommon		technique_common;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEInput
+{
+	std::string				semantic;
+	std::string				source;
+	uint32_t				offset;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEVertices
+{
+	std::string				id;
+	std::vector<DAEInput>	inputs;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEPolylist
+{
+	uint32_t				count;
+	std::vector<DAEInput>	inputs;
+	std::vector<uint32_t>	vcount;
+	std::vector<uint32_t>	p;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEMesh
+{
+	std::vector<DAESource>	sources;
+	DAEVertices				vertices;
+	DAEPolylist				polylist;
+};
+
+//-----------------------------------------------------------------------------
+struct DAEGeometry
+{
+	std::string				id;		// UUID of the geometry
+	std::string				name;	// Name of the geometry
+	DAEMesh					mesh;	// The mesh
+};
+
+//-----------------------------------------------------------------------------
+struct DAEModel
+{
+	std::vector<DAEGeometry>	geometries;
+};
+
+class DAECompiler : public Compiler
+{
+public:
+
+						DAECompiler();
+						~DAECompiler();
+
+	size_t				compile_impl(const char* resource_path);
+	void				write_impl(std::fstream& out_file);
+
+private:
+
+	// The following functions return false if parsing fails, true otherwise
+	static bool			parse_collada(const char* path, DAEModel& m);
+	static bool			parse_geometry(XMLElement* geometry, DAEGeometry& g);
+	static bool			parse_mesh(XMLElement* mesh, DAEMesh& m);
+	static bool			parse_source(XMLElement* source, DAESource& s);
+	static bool			parse_float_array(XMLElement* array, DAEFloatArray& a);
+	static bool			parse_technique_common(XMLElement* technique, DAETechniqueCommon& t);
+	static bool			parse_accessor(XMLElement* accessor, DAEAccessor& a);
+	static bool			parse_param(XMLElement* param, DAEParam& p);
+	static bool			parse_vertices(XMLElement* vertices, DAEVertices& v);
+	static bool			parse_input(XMLElement* input, DAEInput& i);
+	static bool			parse_polylist(XMLElement* polylist, DAEPolylist& p);
+
+	bool				find_vertices(const DAEMesh& mesh, DAESource& source_out);
+	bool				find_normals(const DAEMesh& mesh, DAESource& source_out);
+
+	bool				extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out);
+	bool				extract_vertex_normals(const DAEMesh& mesh, vector<uint32_t>& indices_out);
+
+private:
+
+	MeshHeader			m_mesh_header;
+
+	vector<float>		m_vertex_vertices;
+	vector<uint16_t>	m_vertex_indices;
+};
+
+} // namespace crown

+ 2099 - 0
tools/compilers/dae/tinyxml2.cpp

@@ -0,0 +1,2099 @@
+/*
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml2.h"
+
+#include <new>		// yes, this one new style header, is in the Android SDK.
+#   ifdef ANDROID_NDK
+#   include <stddef.h>
+#else
+#   include <cstddef>
+#endif
+
+static const char LINE_FEED				= (char)0x0a;			// all line endings are normalized to LF
+static const char LF = LINE_FEED;
+static const char CARRIAGE_RETURN		= (char)0x0d;			// CR gets filtered out
+static const char CR = CARRIAGE_RETURN;
+static const char SINGLE_QUOTE			= '\'';
+static const char DOUBLE_QUOTE			= '\"';
+
+// Bunch of unicode info at:
+//		http://www.unicode.org/faq/utf_bom.html
+//	ef bb bf (Microsoft "lead bytes") - designates UTF-8
+
+static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+
+#define DELETE_NODE( node )	{			\
+        if ( node ) {						\
+            MemPool* pool = node->_memPool;	\
+            node->~XMLNode();				\
+            pool->Free( node );				\
+        }									\
+    }
+#define DELETE_ATTRIBUTE( attrib ) {		\
+        if ( attrib ) {							\
+            MemPool* pool = attrib->_memPool;	\
+            attrib->~XMLAttribute();			\
+            pool->Free( attrib );				\
+        }										\
+    }
+
+namespace tinyxml2
+{
+
+struct Entity {
+    const char* pattern;
+    int length;
+    char value;
+};
+
+static const int NUM_ENTITIES = 5;
+static const Entity entities[NUM_ENTITIES] = {
+    { "quot", 4,	DOUBLE_QUOTE },
+    { "amp", 3,		'&'  },
+    { "apos", 4,	SINGLE_QUOTE },
+    { "lt",	2, 		'<'	 },
+    { "gt",	2,		'>'	 }
+};
+
+
+StrPair::~StrPair()
+{
+    Reset();
+}
+
+
+void StrPair::Reset()
+{
+    if ( _flags & NEEDS_DELETE ) {
+        delete [] _start;
+    }
+    _flags = 0;
+    _start = 0;
+    _end = 0;
+}
+
+
+void StrPair::SetStr( const char* str, int flags )
+{
+    Reset();
+    size_t len = strlen( str );
+    _start = new char[ len+1 ];
+    memcpy( _start, str, len+1 );
+    _end = _start + len;
+    _flags = flags | NEEDS_DELETE;
+}
+
+
+char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
+{
+    TIXMLASSERT( endTag && *endTag );
+
+    char* start = p;	// fixme: hides a member
+    char  endChar = *endTag;
+    size_t length = strlen( endTag );
+
+    // Inner loop of text parsing.
+    while ( *p ) {
+        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
+            Set( start, p, strFlags );
+            return p + length;
+        }
+        ++p;
+    }
+    return 0;
+}
+
+
+char* StrPair::ParseName( char* p )
+{
+    char* start = p;
+
+    if ( !start || !(*start) ) {
+        return 0;
+    }
+
+    while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) {
+        ++p;
+    }
+
+    if ( p > start ) {
+        Set( start, p, 0 );
+        return p;
+    }
+    return 0;
+}
+
+
+void StrPair::CollapseWhitespace()
+{
+    // Trim leading space.
+    _start = XMLUtil::SkipWhiteSpace( _start );
+
+    if ( _start && *_start ) {
+        char* p = _start;	// the read pointer
+        char* q = _start;	// the write pointer
+
+        while( *p ) {
+            if ( XMLUtil::IsWhiteSpace( *p )) {
+                p = XMLUtil::SkipWhiteSpace( p );
+                if ( *p == 0 ) {
+                    break;    // don't write to q; this trims the trailing space.
+                }
+                *q = ' ';
+                ++q;
+            }
+            *q = *p;
+            ++q;
+            ++p;
+        }
+        *q = 0;
+    }
+}
+
+
+const char* StrPair::GetStr()
+{
+    if ( _flags & NEEDS_FLUSH ) {
+        *_end = 0;
+        _flags ^= NEEDS_FLUSH;
+
+        if ( _flags ) {
+            char* p = _start;	// the read pointer
+            char* q = _start;	// the write pointer
+
+            while( p < _end ) {
+                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
+                    // CR-LF pair becomes LF
+                    // CR alone becomes LF
+                    // LF-CR becomes LF
+                    if ( *(p+1) == LF ) {
+                        p += 2;
+                    }
+                    else {
+                        ++p;
+                    }
+                    *q++ = LF;
+                }
+                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
+                    if ( *(p+1) == CR ) {
+                        p += 2;
+                    }
+                    else {
+                        ++p;
+                    }
+                    *q++ = LF;
+                }
+                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
+                    // Entities handled by tinyXML2:
+                    // - special entities in the entity table [in/out]
+                    // - numeric character reference [in]
+                    //   &#20013; or &#x4e2d;
+
+                    if ( *(p+1) == '#' ) {
+                        char buf[10] = { 0 };
+                        int len;
+                        p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
+                        for( int i=0; i<len; ++i ) {
+                            *q++ = buf[i];
+                        }
+                        TIXMLASSERT( q <= p );
+                    }
+                    else {
+                        int i=0;
+                        for(; i<NUM_ENTITIES; ++i ) {
+                            if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
+                                    && *(p+entities[i].length+1) == ';' ) {
+                                // Found an entity convert;
+                                *q = entities[i].value;
+                                ++q;
+                                p += entities[i].length + 2;
+                                break;
+                            }
+                        }
+                        if ( i == NUM_ENTITIES ) {
+                            // fixme: treat as error?
+                            ++p;
+                            ++q;
+                        }
+                    }
+                }
+                else {
+                    *q = *p;
+                    ++p;
+                    ++q;
+                }
+            }
+            *q = 0;
+        }
+        // The loop below has plenty going on, and this
+        // is a less useful mode. Break it out.
+        if ( _flags & COLLAPSE_WHITESPACE ) {
+            CollapseWhitespace();
+        }
+        _flags = (_flags & NEEDS_DELETE);
+    }
+    return _start;
+}
+
+
+
+
+// --------- XMLUtil ----------- //
+
+const char* XMLUtil::ReadBOM( const char* p, bool* bom )
+{
+    *bom = false;
+    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
+    // Check for BOM:
+    if (    *(pu+0) == TIXML_UTF_LEAD_0
+            && *(pu+1) == TIXML_UTF_LEAD_1
+            && *(pu+2) == TIXML_UTF_LEAD_2 ) {
+        *bom = true;
+        p += 3;
+    }
+    return p;
+}
+
+
+void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+    const unsigned long BYTE_MASK = 0xBF;
+    const unsigned long BYTE_MARK = 0x80;
+    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+    if (input < 0x80) {
+        *length = 1;
+    }
+    else if ( input < 0x800 ) {
+        *length = 2;
+    }
+    else if ( input < 0x10000 ) {
+        *length = 3;
+    }
+    else if ( input < 0x200000 ) {
+        *length = 4;
+    }
+    else {
+        *length = 0;    // This code won't covert this correctly anyway.
+        return;
+    }
+
+    output += *length;
+
+    // Scary scary fall throughs.
+    switch (*length) {
+        case 4:
+            --output;
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+            input >>= 6;
+        case 3:
+            --output;
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+            input >>= 6;
+        case 2:
+            --output;
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+            input >>= 6;
+        case 1:
+            --output;
+            *output = (char)(input | FIRST_BYTE_MARK[*length]);
+        default:
+            break;
+    }
+}
+
+
+const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
+{
+    // Presume an entity, and pull it out.
+    *length = 0;
+
+    if ( *(p+1) == '#' && *(p+2) ) {
+        unsigned long ucs = 0;
+        ptrdiff_t delta = 0;
+        unsigned mult = 1;
+
+        if ( *(p+2) == 'x' ) {
+            // Hexadecimal.
+            if ( !*(p+3) ) {
+                return 0;
+            }
+
+            const char* q = p+3;
+            q = strchr( q, ';' );
+
+            if ( !q || !*q ) {
+                return 0;
+            }
+
+            delta = q-p;
+            --q;
+
+            while ( *q != 'x' ) {
+                if ( *q >= '0' && *q <= '9' ) {
+                    ucs += mult * (*q - '0');
+                }
+                else if ( *q >= 'a' && *q <= 'f' ) {
+                    ucs += mult * (*q - 'a' + 10);
+                }
+                else if ( *q >= 'A' && *q <= 'F' ) {
+                    ucs += mult * (*q - 'A' + 10 );
+                }
+                else {
+                    return 0;
+                }
+                mult *= 16;
+                --q;
+            }
+        }
+        else {
+            // Decimal.
+            if ( !*(p+2) ) {
+                return 0;
+            }
+
+            const char* q = p+2;
+            q = strchr( q, ';' );
+
+            if ( !q || !*q ) {
+                return 0;
+            }
+
+            delta = q-p;
+            --q;
+
+            while ( *q != '#' ) {
+                if ( *q >= '0' && *q <= '9' ) {
+                    ucs += mult * (*q - '0');
+                }
+                else {
+                    return 0;
+                }
+                mult *= 10;
+                --q;
+            }
+        }
+        // convert the UCS to UTF-8
+        ConvertUTF32ToUTF8( ucs, value, length );
+        return p + delta + 1;
+    }
+    return p+1;
+}
+
+
+void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
+{
+    TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
+}
+
+
+void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
+{
+    TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
+}
+
+
+void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
+{
+    TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
+}
+
+
+void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
+{
+    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
+}
+
+
+void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
+{
+    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
+}
+
+
+bool XMLUtil::ToInt( const char* str, int* value )
+{
+    if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
+        return true;
+    }
+    return false;
+}
+
+bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
+{
+    if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
+        return true;
+    }
+    return false;
+}
+
+bool XMLUtil::ToBool( const char* str, bool* value )
+{
+    int ival = 0;
+    if ( ToInt( str, &ival )) {
+        *value = (ival==0) ? false : true;
+        return true;
+    }
+    if ( StringEqual( str, "true" ) ) {
+        *value = true;
+        return true;
+    }
+    else if ( StringEqual( str, "false" ) ) {
+        *value = false;
+        return true;
+    }
+    return false;
+}
+
+
+bool XMLUtil::ToFloat( const char* str, float* value )
+{
+    if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
+        return true;
+    }
+    return false;
+}
+
+bool XMLUtil::ToDouble( const char* str, double* value )
+{
+    if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
+        return true;
+    }
+    return false;
+}
+
+
+char* XMLDocument::Identify( char* p, XMLNode** node )
+{
+    XMLNode* returnNode = 0;
+    char* start = p;
+    p = XMLUtil::SkipWhiteSpace( p );
+    if( !p || !*p ) {
+        return p;
+    }
+
+    // What is this thing?
+    // - Elements start with a letter or underscore, but xml is reserved.
+    // - Comments: <!--
+    // - Declaration: <?
+    // - Everything else is unknown to tinyxml.
+    //
+
+    static const char* xmlHeader		= { "<?" };
+    static const char* commentHeader	= { "<!--" };
+    static const char* dtdHeader		= { "<!" };
+    static const char* cdataHeader		= { "<![CDATA[" };
+    static const char* elementHeader	= { "<" };	// and a header for everything else; check last.
+
+    static const int xmlHeaderLen		= 2;
+    static const int commentHeaderLen	= 4;
+    static const int dtdHeaderLen		= 2;
+    static const int cdataHeaderLen		= 9;
+    static const int elementHeaderLen	= 1;
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable : 4127 )
+#endif
+    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
+    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
+        returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
+        returnNode->_memPool = &_commentPool;
+        p += xmlHeaderLen;
+    }
+    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
+        returnNode = new (_commentPool.Alloc()) XMLComment( this );
+        returnNode->_memPool = &_commentPool;
+        p += commentHeaderLen;
+    }
+    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
+        XMLText* text = new (_textPool.Alloc()) XMLText( this );
+        returnNode = text;
+        returnNode->_memPool = &_textPool;
+        p += cdataHeaderLen;
+        text->SetCData( true );
+    }
+    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
+        returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
+        returnNode->_memPool = &_commentPool;
+        p += dtdHeaderLen;
+    }
+    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
+        returnNode = new (_elementPool.Alloc()) XMLElement( this );
+        returnNode->_memPool = &_elementPool;
+        p += elementHeaderLen;
+    }
+    else {
+        returnNode = new (_textPool.Alloc()) XMLText( this );
+        returnNode->_memPool = &_textPool;
+        p = start;	// Back it up, all the text counts.
+    }
+
+    *node = returnNode;
+    return p;
+}
+
+
+bool XMLDocument::Accept( XMLVisitor* visitor ) const
+{
+    if ( visitor->VisitEnter( *this ) ) {
+        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
+            if ( !node->Accept( visitor ) ) {
+                break;
+            }
+        }
+    }
+    return visitor->VisitExit( *this );
+}
+
+
+// --------- XMLNode ----------- //
+
+XMLNode::XMLNode( XMLDocument* doc ) :
+    _document( doc ),
+    _parent( 0 ),
+    _firstChild( 0 ), _lastChild( 0 ),
+    _prev( 0 ), _next( 0 ),
+    _memPool( 0 )
+{
+}
+
+
+XMLNode::~XMLNode()
+{
+    DeleteChildren();
+    if ( _parent ) {
+        _parent->Unlink( this );
+    }
+}
+
+
+void XMLNode::SetValue( const char* str, bool staticMem )
+{
+    if ( staticMem ) {
+        _value.SetInternedStr( str );
+    }
+    else {
+        _value.SetStr( str );
+    }
+}
+
+
+void XMLNode::DeleteChildren()
+{
+    while( _firstChild ) {
+        XMLNode* node = _firstChild;
+        Unlink( node );
+
+        DELETE_NODE( node );
+    }
+    _firstChild = _lastChild = 0;
+}
+
+
+void XMLNode::Unlink( XMLNode* child )
+{
+    TIXMLASSERT( child->_parent == this );
+    if ( child == _firstChild ) {
+        _firstChild = _firstChild->_next;
+    }
+    if ( child == _lastChild ) {
+        _lastChild = _lastChild->_prev;
+    }
+
+    if ( child->_prev ) {
+        child->_prev->_next = child->_next;
+    }
+    if ( child->_next ) {
+        child->_next->_prev = child->_prev;
+    }
+    child->_parent = 0;
+}
+
+
+void XMLNode::DeleteChild( XMLNode* node )
+{
+    TIXMLASSERT( node->_parent == this );
+    DELETE_NODE( node );
+}
+
+
+XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
+{
+    if ( _lastChild ) {
+        TIXMLASSERT( _firstChild );
+        TIXMLASSERT( _lastChild->_next == 0 );
+        _lastChild->_next = addThis;
+        addThis->_prev = _lastChild;
+        _lastChild = addThis;
+
+        addThis->_next = 0;
+    }
+    else {
+        TIXMLASSERT( _firstChild == 0 );
+        _firstChild = _lastChild = addThis;
+
+        addThis->_prev = 0;
+        addThis->_next = 0;
+    }
+    addThis->_parent = this;
+    addThis->_memPool->SetTracked();
+    return addThis;
+}
+
+
+XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
+{
+    if ( _firstChild ) {
+        TIXMLASSERT( _lastChild );
+        TIXMLASSERT( _firstChild->_prev == 0 );
+
+        _firstChild->_prev = addThis;
+        addThis->_next = _firstChild;
+        _firstChild = addThis;
+
+        addThis->_prev = 0;
+    }
+    else {
+        TIXMLASSERT( _lastChild == 0 );
+        _firstChild = _lastChild = addThis;
+
+        addThis->_prev = 0;
+        addThis->_next = 0;
+    }
+    addThis->_parent = this;
+    addThis->_memPool->SetTracked();
+    return addThis;
+}
+
+
+XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
+{
+    TIXMLASSERT( afterThis->_parent == this );
+    if ( afterThis->_parent != this ) {
+        return 0;
+    }
+
+    if ( afterThis->_next == 0 ) {
+        // The last node or the only node.
+        return InsertEndChild( addThis );
+    }
+    addThis->_prev = afterThis;
+    addThis->_next = afterThis->_next;
+    afterThis->_next->_prev = addThis;
+    afterThis->_next = addThis;
+    addThis->_parent = this;
+    addThis->_memPool->SetTracked();
+    return addThis;
+}
+
+
+
+
+const XMLElement* XMLNode::FirstChildElement( const char* value ) const
+{
+    for( XMLNode* node=_firstChild; node; node=node->_next ) {
+        XMLElement* element = node->ToElement();
+        if ( element ) {
+            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
+                return element;
+            }
+        }
+    }
+    return 0;
+}
+
+
+const XMLElement* XMLNode::LastChildElement( const char* value ) const
+{
+    for( XMLNode* node=_lastChild; node; node=node->_prev ) {
+        XMLElement* element = node->ToElement();
+        if ( element ) {
+            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
+                return element;
+            }
+        }
+    }
+    return 0;
+}
+
+
+const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
+{
+    for( XMLNode* element=this->_next; element; element = element->_next ) {
+        if (    element->ToElement()
+                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
+            return element->ToElement();
+        }
+    }
+    return 0;
+}
+
+
+const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
+{
+    for( XMLNode* element=_prev; element; element = element->_prev ) {
+        if (    element->ToElement()
+                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
+            return element->ToElement();
+        }
+    }
+    return 0;
+}
+
+
+char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
+{
+    // This is a recursive method, but thinking about it "at the current level"
+    // it is a pretty simple flat list:
+    //		<foo/>
+    //		<!-- comment -->
+    //
+    // With a special case:
+    //		<foo>
+    //		</foo>
+    //		<!-- comment -->
+    //
+    // Where the closing element (/foo) *must* be the next thing after the opening
+    // element, and the names must match. BUT the tricky bit is that the closing
+    // element will be read by the child.
+    //
+    // 'endTag' is the end tag for this node, it is returned by a call to a child.
+    // 'parentEnd' is the end tag for the parent, which is filled in and returned.
+
+    while( p && *p ) {
+        XMLNode* node = 0;
+
+        p = _document->Identify( p, &node );
+        if ( p == 0 || node == 0 ) {
+            break;
+        }
+
+        StrPair endTag;
+        p = node->ParseDeep( p, &endTag );
+        if ( !p ) {
+            DELETE_NODE( node );
+            node = 0;
+            if ( !_document->Error() ) {
+                _document->SetError( XML_ERROR_PARSING, 0, 0 );
+            }
+            break;
+        }
+
+        // We read the end tag. Return it to the parent.
+        if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
+            if ( parentEnd ) {
+                *parentEnd = static_cast<XMLElement*>(node)->_value;
+            }
+			node->_memPool->SetTracked();	// created and then immediately deleted.
+            DELETE_NODE( node );
+            return p;
+        }
+
+        // Handle an end tag returned to this level.
+        // And handle a bunch of annoying errors.
+        XMLElement* ele = node->ToElement();
+        if ( ele ) {
+            if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
+                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+                p = 0;
+            }
+            else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
+                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+                p = 0;
+            }
+            else if ( !endTag.Empty() ) {
+                if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
+                    _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+                    p = 0;
+                }
+            }
+        }
+        if ( p == 0 ) {
+            DELETE_NODE( node );
+            node = 0;
+        }
+        if ( node ) {
+            this->InsertEndChild( node );
+        }
+    }
+    return 0;
+}
+
+// --------- XMLText ---------- //
+char* XMLText::ParseDeep( char* p, StrPair* )
+{
+    const char* start = p;
+    if ( this->CData() ) {
+        p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
+        if ( !p ) {
+            _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
+        }
+        return p;
+    }
+    else {
+        int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
+        if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
+            flags |= StrPair::COLLAPSE_WHITESPACE;
+        }
+
+        p = _value.ParseText( p, "<", flags );
+        if ( !p ) {
+            _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
+        }
+        if ( p && *p ) {
+            return p-1;
+        }
+    }
+    return 0;
+}
+
+
+XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
+{
+    if ( !doc ) {
+        doc = _document;
+    }
+    XMLText* text = doc->NewText( Value() );	// fixme: this will always allocate memory. Intern?
+    text->SetCData( this->CData() );
+    return text;
+}
+
+
+bool XMLText::ShallowEqual( const XMLNode* compare ) const
+{
+    return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
+}
+
+
+bool XMLText::Accept( XMLVisitor* visitor ) const
+{
+    return visitor->Visit( *this );
+}
+
+
+// --------- XMLComment ---------- //
+
+XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
+{
+}
+
+
+XMLComment::~XMLComment()
+{
+}
+
+
+char* XMLComment::ParseDeep( char* p, StrPair* )
+{
+    // Comment parses as text.
+    const char* start = p;
+    p = _value.ParseText( p, "-->", StrPair::COMMENT );
+    if ( p == 0 ) {
+        _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
+    }
+    return p;
+}
+
+
+XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
+{
+    if ( !doc ) {
+        doc = _document;
+    }
+    XMLComment* comment = doc->NewComment( Value() );	// fixme: this will always allocate memory. Intern?
+    return comment;
+}
+
+
+bool XMLComment::ShallowEqual( const XMLNode* compare ) const
+{
+    return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
+}
+
+
+bool XMLComment::Accept( XMLVisitor* visitor ) const
+{
+    return visitor->Visit( *this );
+}
+
+
+// --------- XMLDeclaration ---------- //
+
+XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
+{
+}
+
+
+XMLDeclaration::~XMLDeclaration()
+{
+    //printf( "~XMLDeclaration\n" );
+}
+
+
+char* XMLDeclaration::ParseDeep( char* p, StrPair* )
+{
+    // Declaration parses as text.
+    const char* start = p;
+    p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
+    if ( p == 0 ) {
+        _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
+    }
+    return p;
+}
+
+
+XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
+{
+    if ( !doc ) {
+        doc = _document;
+    }
+    XMLDeclaration* dec = doc->NewDeclaration( Value() );	// fixme: this will always allocate memory. Intern?
+    return dec;
+}
+
+
+bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
+{
+    return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
+}
+
+
+
+bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
+{
+    return visitor->Visit( *this );
+}
+
+// --------- XMLUnknown ---------- //
+
+XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
+{
+}
+
+
+XMLUnknown::~XMLUnknown()
+{
+}
+
+
+char* XMLUnknown::ParseDeep( char* p, StrPair* )
+{
+    // Unknown parses as text.
+    const char* start = p;
+
+    p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
+    if ( !p ) {
+        _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
+    }
+    return p;
+}
+
+
+XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
+{
+    if ( !doc ) {
+        doc = _document;
+    }
+    XMLUnknown* text = doc->NewUnknown( Value() );	// fixme: this will always allocate memory. Intern?
+    return text;
+}
+
+
+bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
+{
+    return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
+}
+
+
+bool XMLUnknown::Accept( XMLVisitor* visitor ) const
+{
+    return visitor->Visit( *this );
+}
+
+// --------- XMLAttribute ---------- //
+char* XMLAttribute::ParseDeep( char* p, bool processEntities )
+{
+    // Parse using the name rules: bug fix, was using ParseText before
+    p = _name.ParseName( p );
+    if ( !p || !*p ) {
+        return 0;
+    }
+
+    // Skip white space before =
+    p = XMLUtil::SkipWhiteSpace( p );
+    if ( !p || *p != '=' ) {
+        return 0;
+    }
+
+    ++p;	// move up to opening quote
+    p = XMLUtil::SkipWhiteSpace( p );
+    if ( *p != '\"' && *p != '\'' ) {
+        return 0;
+    }
+
+    char endTag[2] = { *p, 0 };
+    ++p;	// move past opening quote
+
+    p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
+    return p;
+}
+
+
+void XMLAttribute::SetName( const char* n )
+{
+    _name.SetStr( n );
+}
+
+
+XMLError XMLAttribute::QueryIntValue( int* value ) const
+{
+    if ( XMLUtil::ToInt( Value(), value )) {
+        return XML_NO_ERROR;
+    }
+    return XML_WRONG_ATTRIBUTE_TYPE;
+}
+
+
+XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
+{
+    if ( XMLUtil::ToUnsigned( Value(), value )) {
+        return XML_NO_ERROR;
+    }
+    return XML_WRONG_ATTRIBUTE_TYPE;
+}
+
+
+XMLError XMLAttribute::QueryBoolValue( bool* value ) const
+{
+    if ( XMLUtil::ToBool( Value(), value )) {
+        return XML_NO_ERROR;
+    }
+    return XML_WRONG_ATTRIBUTE_TYPE;
+}
+
+
+XMLError XMLAttribute::QueryFloatValue( float* value ) const
+{
+    if ( XMLUtil::ToFloat( Value(), value )) {
+        return XML_NO_ERROR;
+    }
+    return XML_WRONG_ATTRIBUTE_TYPE;
+}
+
+
+XMLError XMLAttribute::QueryDoubleValue( double* value ) const
+{
+    if ( XMLUtil::ToDouble( Value(), value )) {
+        return XML_NO_ERROR;
+    }
+    return XML_WRONG_ATTRIBUTE_TYPE;
+}
+
+
+void XMLAttribute::SetAttribute( const char* v )
+{
+    _value.SetStr( v );
+}
+
+
+void XMLAttribute::SetAttribute( int v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    _value.SetStr( buf );
+}
+
+
+void XMLAttribute::SetAttribute( unsigned v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    _value.SetStr( buf );
+}
+
+
+void XMLAttribute::SetAttribute( bool v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    _value.SetStr( buf );
+}
+
+void XMLAttribute::SetAttribute( double v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    _value.SetStr( buf );
+}
+
+void XMLAttribute::SetAttribute( float v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    _value.SetStr( buf );
+}
+
+
+// --------- XMLElement ---------- //
+XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
+    _closingType( 0 ),
+    _rootAttribute( 0 )
+{
+}
+
+
+XMLElement::~XMLElement()
+{
+    while( _rootAttribute ) {
+        XMLAttribute* next = _rootAttribute->_next;
+        DELETE_ATTRIBUTE( _rootAttribute );
+        _rootAttribute = next;
+    }
+}
+
+
+XMLAttribute* XMLElement::FindAttribute( const char* name )
+{
+    XMLAttribute* a = 0;
+    for( a=_rootAttribute; a; a = a->_next ) {
+        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
+            return a;
+        }
+    }
+    return 0;
+}
+
+
+const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
+{
+    XMLAttribute* a = 0;
+    for( a=_rootAttribute; a; a = a->_next ) {
+        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
+            return a;
+        }
+    }
+    return 0;
+}
+
+
+const char* XMLElement::Attribute( const char* name, const char* value ) const
+{
+    const XMLAttribute* a = FindAttribute( name );
+    if ( !a ) {
+        return 0;
+    }
+    if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
+        return a->Value();
+    }
+    return 0;
+}
+
+
+const char* XMLElement::GetText() const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        return FirstChild()->ToText()->Value();
+    }
+    return 0;
+}
+
+
+XMLError XMLElement::QueryIntText( int* ival ) const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        const char* t = FirstChild()->ToText()->Value();
+        if ( XMLUtil::ToInt( t, ival ) ) {
+            return XML_SUCCESS;
+        }
+        return XML_CAN_NOT_CONVERT_TEXT;
+    }
+    return XML_NO_TEXT_NODE;
+}
+
+
+XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        const char* t = FirstChild()->ToText()->Value();
+        if ( XMLUtil::ToUnsigned( t, uval ) ) {
+            return XML_SUCCESS;
+        }
+        return XML_CAN_NOT_CONVERT_TEXT;
+    }
+    return XML_NO_TEXT_NODE;
+}
+
+
+XMLError XMLElement::QueryBoolText( bool* bval ) const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        const char* t = FirstChild()->ToText()->Value();
+        if ( XMLUtil::ToBool( t, bval ) ) {
+            return XML_SUCCESS;
+        }
+        return XML_CAN_NOT_CONVERT_TEXT;
+    }
+    return XML_NO_TEXT_NODE;
+}
+
+
+XMLError XMLElement::QueryDoubleText( double* dval ) const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        const char* t = FirstChild()->ToText()->Value();
+        if ( XMLUtil::ToDouble( t, dval ) ) {
+            return XML_SUCCESS;
+        }
+        return XML_CAN_NOT_CONVERT_TEXT;
+    }
+    return XML_NO_TEXT_NODE;
+}
+
+
+XMLError XMLElement::QueryFloatText( float* fval ) const
+{
+    if ( FirstChild() && FirstChild()->ToText() ) {
+        const char* t = FirstChild()->ToText()->Value();
+        if ( XMLUtil::ToFloat( t, fval ) ) {
+            return XML_SUCCESS;
+        }
+        return XML_CAN_NOT_CONVERT_TEXT;
+    }
+    return XML_NO_TEXT_NODE;
+}
+
+
+
+XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
+{
+    XMLAttribute* last = 0;
+    XMLAttribute* attrib = 0;
+    for( attrib = _rootAttribute;
+            attrib;
+            last = attrib, attrib = attrib->_next ) {
+        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
+            break;
+        }
+    }
+    if ( !attrib ) {
+        attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
+        attrib->_memPool = &_document->_attributePool;
+        if ( last ) {
+            last->_next = attrib;
+        }
+        else {
+            _rootAttribute = attrib;
+        }
+        attrib->SetName( name );
+        attrib->_memPool->SetTracked(); // always created and linked.
+    }
+    return attrib;
+}
+
+
+void XMLElement::DeleteAttribute( const char* name )
+{
+    XMLAttribute* prev = 0;
+    for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
+        if ( XMLUtil::StringEqual( name, a->Name() ) ) {
+            if ( prev ) {
+                prev->_next = a->_next;
+            }
+            else {
+                _rootAttribute = a->_next;
+            }
+            DELETE_ATTRIBUTE( a );
+            break;
+        }
+        prev = a;
+    }
+}
+
+
+char* XMLElement::ParseAttributes( char* p )
+{
+    const char* start = p;
+    XMLAttribute* prevAttribute = 0;
+
+    // Read the attributes.
+    while( p ) {
+        p = XMLUtil::SkipWhiteSpace( p );
+        if ( !p || !(*p) ) {
+            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
+            return 0;
+        }
+
+        // attribute.
+        if (XMLUtil::IsNameStartChar( *p ) ) {
+            XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
+            attrib->_memPool = &_document->_attributePool;
+			attrib->_memPool->SetTracked();
+
+            p = attrib->ParseDeep( p, _document->ProcessEntities() );
+            if ( !p || Attribute( attrib->Name() ) ) {
+                DELETE_ATTRIBUTE( attrib );
+                _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
+                return 0;
+            }
+            // There is a minor bug here: if the attribute in the source xml
+            // document is duplicated, it will not be detected and the
+            // attribute will be doubly added. However, tracking the 'prevAttribute'
+            // avoids re-scanning the attribute list. Preferring performance for
+            // now, may reconsider in the future.
+            if ( prevAttribute ) {
+                prevAttribute->_next = attrib;
+            }
+            else {
+                _rootAttribute = attrib;
+            }
+            prevAttribute = attrib;
+        }
+        // end of the tag
+        else if ( *p == '/' && *(p+1) == '>' ) {
+            _closingType = CLOSED;
+            return p+2;	// done; sealed element.
+        }
+        // end of the tag
+        else if ( *p == '>' ) {
+            ++p;
+            break;
+        }
+        else {
+            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
+            return 0;
+        }
+    }
+    return p;
+}
+
+
+//
+//	<ele></ele>
+//	<ele>foo<b>bar</b></ele>
+//
+char* XMLElement::ParseDeep( char* p, StrPair* strPair )
+{
+    // Read the element name.
+    p = XMLUtil::SkipWhiteSpace( p );
+    if ( !p ) {
+        return 0;
+    }
+
+    // The closing element is the </element> form. It is
+    // parsed just like a regular element then deleted from
+    // the DOM.
+    if ( *p == '/' ) {
+        _closingType = CLOSING;
+        ++p;
+    }
+
+    p = _value.ParseName( p );
+    if ( _value.Empty() ) {
+        return 0;
+    }
+
+    p = ParseAttributes( p );
+    if ( !p || !*p || _closingType ) {
+        return p;
+    }
+
+    p = XMLNode::ParseDeep( p, strPair );
+    return p;
+}
+
+
+
+XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
+{
+    if ( !doc ) {
+        doc = _document;
+    }
+    XMLElement* element = doc->NewElement( Value() );					// fixme: this will always allocate memory. Intern?
+    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
+        element->SetAttribute( a->Name(), a->Value() );					// fixme: this will always allocate memory. Intern?
+    }
+    return element;
+}
+
+
+bool XMLElement::ShallowEqual( const XMLNode* compare ) const
+{
+    const XMLElement* other = compare->ToElement();
+    if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
+
+        const XMLAttribute* a=FirstAttribute();
+        const XMLAttribute* b=other->FirstAttribute();
+
+        while ( a && b ) {
+            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
+                return false;
+            }
+            a = a->Next();
+            b = b->Next();
+        }
+        if ( a || b ) {
+            // different count
+            return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+
+bool XMLElement::Accept( XMLVisitor* visitor ) const
+{
+    if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
+        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
+            if ( !node->Accept( visitor ) ) {
+                break;
+            }
+        }
+    }
+    return visitor->VisitExit( *this );
+}
+
+
+// --------- XMLDocument ----------- //
+XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
+    XMLNode( 0 ),
+    _writeBOM( false ),
+    _processEntities( processEntities ),
+    _errorID( XML_NO_ERROR ),
+    _whitespace( whitespace ),
+    _errorStr1( 0 ),
+    _errorStr2( 0 ),
+    _charBuffer( 0 )
+{
+    _document = this;	// avoid warning about 'this' in initializer list
+}
+
+
+XMLDocument::~XMLDocument()
+{
+    DeleteChildren();
+    delete [] _charBuffer;
+
+#if 0
+    _textPool.Trace( "text" );
+    _elementPool.Trace( "element" );
+    _commentPool.Trace( "comment" );
+    _attributePool.Trace( "attribute" );
+#endif
+
+#ifdef DEBUG
+	if ( Error() == false ) {
+		TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );
+		TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
+		TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );
+		TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );
+	}
+#endif
+}
+
+
+void XMLDocument::Clear()
+{
+    DeleteChildren();
+
+    _errorID = XML_NO_ERROR;
+    _errorStr1 = 0;
+    _errorStr2 = 0;
+
+    delete [] _charBuffer;
+    _charBuffer = 0;
+}
+
+
+XMLElement* XMLDocument::NewElement( const char* name )
+{
+    XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
+    ele->_memPool = &_elementPool;
+    ele->SetName( name );
+    return ele;
+}
+
+
+XMLComment* XMLDocument::NewComment( const char* str )
+{
+    XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
+    comment->_memPool = &_commentPool;
+    comment->SetValue( str );
+    return comment;
+}
+
+
+XMLText* XMLDocument::NewText( const char* str )
+{
+    XMLText* text = new (_textPool.Alloc()) XMLText( this );
+    text->_memPool = &_textPool;
+    text->SetValue( str );
+    return text;
+}
+
+
+XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
+{
+    XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
+    dec->_memPool = &_commentPool;
+    dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
+    return dec;
+}
+
+
+XMLUnknown* XMLDocument::NewUnknown( const char* str )
+{
+    XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
+    unk->_memPool = &_commentPool;
+    unk->SetValue( str );
+    return unk;
+}
+
+
+XMLError XMLDocument::LoadFile( const char* filename )
+{
+    Clear();
+    FILE* fp = 0;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+    errno_t err = fopen_s(&fp, filename, "rb" );
+    if ( !fp || err) {
+#else
+    fp = fopen( filename, "rb" );
+    if ( !fp) {
+#endif
+        SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
+        return _errorID;
+    }
+    LoadFile( fp );
+    fclose( fp );
+    return _errorID;
+}
+
+
+XMLError XMLDocument::LoadFile( FILE* fp )
+{
+    Clear();
+
+    fseek( fp, 0, SEEK_END );
+    size_t size = ftell( fp );
+    fseek( fp, 0, SEEK_SET );
+
+    if ( size == 0 ) {
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
+        return _errorID;
+    }
+
+    _charBuffer = new char[size+1];
+    size_t read = fread( _charBuffer, 1, size, fp );
+    if ( read != size ) {
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
+        return _errorID;
+    }
+
+    _charBuffer[size] = 0;
+
+    const char* p = _charBuffer;
+    p = XMLUtil::SkipWhiteSpace( p );
+    p = XMLUtil::ReadBOM( p, &_writeBOM );
+    if ( !p || !*p ) {
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
+        return _errorID;
+    }
+
+    ParseDeep( _charBuffer + (p-_charBuffer), 0 );
+    return _errorID;
+}
+
+
+XMLError XMLDocument::SaveFile( const char* filename, bool compact )
+{
+    FILE* fp = 0;
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+    errno_t err = fopen_s(&fp, filename, "w" );
+    if ( !fp || err) {
+#else
+    fp = fopen( filename, "w" );
+    if ( !fp) {
+#endif
+        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
+        return _errorID;
+    }
+    SaveFile(fp, compact);
+    fclose( fp );
+    return _errorID;
+}
+
+
+XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
+{
+    XMLPrinter stream( fp, compact );
+    Print( &stream );
+    return _errorID;
+}
+
+
+XMLError XMLDocument::Parse( const char* p, size_t len )
+{
+	const char* start = p;
+    Clear();
+
+    if ( !p || !*p ) {
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
+        return _errorID;
+    }
+    if ( len == (size_t)(-1) ) {
+        len = strlen( p );
+    }
+    _charBuffer = new char[ len+1 ];
+    memcpy( _charBuffer, p, len );
+    _charBuffer[len] = 0;
+
+    p = XMLUtil::SkipWhiteSpace( p );
+    p = XMLUtil::ReadBOM( p, &_writeBOM );
+    if ( !p || !*p ) {
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
+        return _errorID;
+    }
+
+    ptrdiff_t delta = p - start;	// skip initial whitespace, BOM, etc.
+    ParseDeep( _charBuffer+delta, 0 );
+    return _errorID;
+}
+
+
+void XMLDocument::Print( XMLPrinter* streamer ) const
+{
+    XMLPrinter stdStreamer( stdout );
+    if ( !streamer ) {
+        streamer = &stdStreamer;
+    }
+    Accept( streamer );
+}
+
+
+void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
+{
+    _errorID = error;
+    _errorStr1 = str1;
+    _errorStr2 = str2;
+}
+
+
+void XMLDocument::PrintError() const
+{
+    if ( _errorID ) {
+        static const int LEN = 20;
+        char buf1[LEN] = { 0 };
+        char buf2[LEN] = { 0 };
+
+        if ( _errorStr1 ) {
+            TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
+        }
+        if ( _errorStr2 ) {
+            TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
+        }
+
+        printf( "XMLDocument error id=%d str1=%s str2=%s\n",
+                _errorID, buf1, buf2 );
+    }
+}
+
+
+XMLPrinter::XMLPrinter( FILE* file, bool compact ) :
+    _elementJustOpened( false ),
+    _firstElement( true ),
+    _fp( file ),
+    _depth( 0 ),
+    _textDepth( -1 ),
+    _processEntities( true ),
+    _compactMode( compact )
+{
+    for( int i=0; i<ENTITY_RANGE; ++i ) {
+        _entityFlag[i] = false;
+        _restrictedEntityFlag[i] = false;
+    }
+    for( int i=0; i<NUM_ENTITIES; ++i ) {
+        TIXMLASSERT( entities[i].value < ENTITY_RANGE );
+        if ( entities[i].value < ENTITY_RANGE ) {
+            _entityFlag[ (int)entities[i].value ] = true;
+        }
+    }
+    _restrictedEntityFlag[(int)'&'] = true;
+    _restrictedEntityFlag[(int)'<'] = true;
+    _restrictedEntityFlag[(int)'>'] = true;	// not required, but consistency is nice
+    _buffer.Push( 0 );
+}
+
+
+void XMLPrinter::Print( const char* format, ... )
+{
+    va_list     va;
+    va_start( va, format );
+
+    if ( _fp ) {
+        vfprintf( _fp, format, va );
+    }
+    else {
+        // This seems brutally complex. Haven't figured out a better
+        // way on windows.
+#ifdef _MSC_VER
+        int len = -1;
+        int expand = 1000;
+        while ( len < 0 ) {
+            len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
+            if ( len < 0 ) {
+                expand *= 3/2;
+                _accumulator.PushArr( expand );
+            }
+        }
+        char* p = _buffer.PushArr( len ) - 1;
+        memcpy( p, _accumulator.Mem(), len+1 );
+#else
+        int len = vsnprintf( 0, 0, format, va );
+        // Close out and re-start the va-args
+        va_end( va );
+        va_start( va, format );
+        char* p = _buffer.PushArr( len ) - 1;
+        vsnprintf( p, len+1, format, va );
+#endif
+    }
+    va_end( va );
+}
+
+
+void XMLPrinter::PrintSpace( int depth )
+{
+    for( int i=0; i<depth; ++i ) {
+        Print( "    " );
+    }
+}
+
+
+void XMLPrinter::PrintString( const char* p, bool restricted )
+{
+    // Look for runs of bytes between entities to print.
+    const char* q = p;
+    const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
+
+    if ( _processEntities ) {
+        while ( *q ) {
+            // Remember, char is sometimes signed. (How many times has that bitten me?)
+            if ( *q > 0 && *q < ENTITY_RANGE ) {
+                // Check for entities. If one is found, flush
+                // the stream up until the entity, write the
+                // entity, and keep looking.
+                if ( flag[(unsigned)(*q)] ) {
+                    while ( p < q ) {
+                        Print( "%c", *p );
+                        ++p;
+                    }
+                    for( int i=0; i<NUM_ENTITIES; ++i ) {
+                        if ( entities[i].value == *q ) {
+                            Print( "&%s;", entities[i].pattern );
+                            break;
+                        }
+                    }
+                    ++p;
+                }
+            }
+            ++q;
+        }
+    }
+    // Flush the remaining string. This will be the entire
+    // string if an entity wasn't found.
+    if ( !_processEntities || (q-p > 0) ) {
+        Print( "%s", p );
+    }
+}
+
+
+void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
+{
+    if ( writeBOM ) {
+		static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
+        Print( "%s", bom );
+    }
+    if ( writeDec ) {
+        PushDeclaration( "xml version=\"1.0\"" );
+    }
+}
+
+
+void XMLPrinter::OpenElement( const char* name )
+{
+    if ( _elementJustOpened ) {
+        SealElement();
+    }
+    _stack.Push( name );
+
+    if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
+        Print( "\n" );
+        PrintSpace( _depth );
+    }
+
+    Print( "<%s", name );
+    _elementJustOpened = true;
+    _firstElement = false;
+    ++_depth;
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, const char* value )
+{
+    TIXMLASSERT( _elementJustOpened );
+    Print( " %s=\"", name );
+    PrintString( value, false );
+    Print( "\"" );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, int v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, unsigned v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, bool v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::PushAttribute( const char* name, double v )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    PushAttribute( name, buf );
+}
+
+
+void XMLPrinter::CloseElement()
+{
+    --_depth;
+    const char* name = _stack.Pop();
+
+    if ( _elementJustOpened ) {
+        Print( "/>" );
+    }
+    else {
+        if ( _textDepth < 0 && !_compactMode) {
+            Print( "\n" );
+            PrintSpace( _depth );
+        }
+        Print( "</%s>", name );
+    }
+
+    if ( _textDepth == _depth ) {
+        _textDepth = -1;
+    }
+    if ( _depth == 0 && !_compactMode) {
+        Print( "\n" );
+    }
+    _elementJustOpened = false;
+}
+
+
+void XMLPrinter::SealElement()
+{
+    _elementJustOpened = false;
+    Print( ">" );
+}
+
+
+void XMLPrinter::PushText( const char* text, bool cdata )
+{
+    _textDepth = _depth-1;
+
+    if ( _elementJustOpened ) {
+        SealElement();
+    }
+    if ( cdata ) {
+        Print( "<![CDATA[" );
+        Print( "%s", text );
+        Print( "]]>" );
+    }
+    else {
+        PrintString( text, true );
+    }
+}
+
+void XMLPrinter::PushText( int value )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( value, buf, BUF_SIZE );
+    PushText( buf, false );
+}
+
+
+void XMLPrinter::PushText( unsigned value )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( value, buf, BUF_SIZE );
+    PushText( buf, false );
+}
+
+
+void XMLPrinter::PushText( bool value )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( value, buf, BUF_SIZE );
+    PushText( buf, false );
+}
+
+
+void XMLPrinter::PushText( float value )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( value, buf, BUF_SIZE );
+    PushText( buf, false );
+}
+
+
+void XMLPrinter::PushText( double value )
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( value, buf, BUF_SIZE );
+    PushText( buf, false );
+}
+
+
+void XMLPrinter::PushComment( const char* comment )
+{
+    if ( _elementJustOpened ) {
+        SealElement();
+    }
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
+        Print( "\n" );
+        PrintSpace( _depth );
+    }
+    _firstElement = false;
+    Print( "<!--%s-->", comment );
+}
+
+
+void XMLPrinter::PushDeclaration( const char* value )
+{
+    if ( _elementJustOpened ) {
+        SealElement();
+    }
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
+        Print( "\n" );
+        PrintSpace( _depth );
+    }
+    _firstElement = false;
+    Print( "<?%s?>", value );
+}
+
+
+void XMLPrinter::PushUnknown( const char* value )
+{
+    if ( _elementJustOpened ) {
+        SealElement();
+    }
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
+        Print( "\n" );
+        PrintSpace( _depth );
+    }
+    _firstElement = false;
+    Print( "<!%s>", value );
+}
+
+
+bool XMLPrinter::VisitEnter( const XMLDocument& doc )
+{
+    _processEntities = doc.ProcessEntities();
+    if ( doc.HasBOM() ) {
+        PushHeader( true, false );
+    }
+    return true;
+}
+
+
+bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
+{
+    OpenElement( element.Name() );
+    while ( attribute ) {
+        PushAttribute( attribute->Name(), attribute->Value() );
+        attribute = attribute->Next();
+    }
+    return true;
+}
+
+
+bool XMLPrinter::VisitExit( const XMLElement& )
+{
+    CloseElement();
+    return true;
+}
+
+
+bool XMLPrinter::Visit( const XMLText& text )
+{
+    PushText( text.Value(), text.CData() );
+    return true;
+}
+
+
+bool XMLPrinter::Visit( const XMLComment& comment )
+{
+    PushComment( comment.Value() );
+    return true;
+}
+
+bool XMLPrinter::Visit( const XMLDeclaration& declaration )
+{
+    PushDeclaration( declaration.Value() );
+    return true;
+}
+
+
+bool XMLPrinter::Visit( const XMLUnknown& unknown )
+{
+    PushUnknown( unknown.Value() );
+    return true;
+}
+
+}   // namespace tinyxml2
+

+ 1968 - 0
tools/compilers/dae/tinyxml2.h

@@ -0,0 +1,1968 @@
+/*
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#ifndef TINYXML2_INCLUDED
+#define TINYXML2_INCLUDED
+
+#if defined(ANDROID_NDK) || defined(__BORLANDC__)
+#   include <ctype.h>
+#   include <limits.h>
+#   include <stdio.h>
+#   include <stdlib.h>
+#   include <string.h>
+#   include <stdarg.h>
+#else
+#   include <cctype>
+#   include <climits>
+#   include <cstdio>
+#   include <cstdlib>
+#   include <cstring>
+#   include <cstdarg>
+#endif
+
+/*
+   TODO: intern strings instead of allocation.
+*/
+/*
+	gcc:
+        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
+
+    Formatting, Artistic Style:
+        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
+*/
+
+#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
+#   ifndef DEBUG
+#       define DEBUG
+#   endif
+#endif
+
+
+#if defined(DEBUG)
+#   if defined(_MSC_VER)
+#       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
+#   elif defined (ANDROID_NDK)
+#       include <android/log.h>
+#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
+#   else
+#       include <assert.h>
+#       define TIXMLASSERT                assert
+#   endif
+#   else
+#       define TIXMLASSERT( x )           {}
+#endif
+
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+// Microsoft visual studio, version 2005 and higher.
+/*int _snprintf_s(
+   char *buffer,
+   size_t sizeOfBuffer,
+   size_t count,
+   const char *format [,
+	  argument] ...
+);*/
+inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
+{
+    va_list va;
+    va_start( va, format );
+    int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
+    va_end( va );
+    return result;
+}
+#define TIXML_SSCANF   sscanf_s
+#else
+// GCC version 3 and higher
+//#warning( "Using sn* functions." )
+#define TIXML_SNPRINTF snprintf
+#define TIXML_SSCANF   sscanf
+#endif
+
+static const int TIXML2_MAJOR_VERSION = 1;
+static const int TIXML2_MINOR_VERSION = 0;
+static const int TIXML2_PATCH_VERSION = 11;
+
+namespace tinyxml2
+{
+class XMLDocument;
+class XMLElement;
+class XMLAttribute;
+class XMLComment;
+class XMLNode;
+class XMLText;
+class XMLDeclaration;
+class XMLUnknown;
+
+class XMLPrinter;
+
+/*
+	A class that wraps strings. Normally stores the start and end
+	pointers into the XML file itself, and will apply normalization
+	and entity translation if actually read. Can also store (and memory
+	manage) a traditional char[]
+*/
+class StrPair
+{
+public:
+    enum {
+        NEEDS_ENTITY_PROCESSING			= 0x01,
+        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
+        COLLAPSE_WHITESPACE	                = 0x04,
+
+        TEXT_ELEMENT		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
+        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
+        ATTRIBUTE_NAME		            	= 0,
+        ATTRIBUTE_VALUE		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
+        ATTRIBUTE_VALUE_LEAVE_ENTITIES  	= NEEDS_NEWLINE_NORMALIZATION,
+        COMMENT				        = NEEDS_NEWLINE_NORMALIZATION
+    };
+
+    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
+    ~StrPair();
+
+    void Set( char* start, char* end, int flags ) {
+        Reset();
+        _start  = start;
+        _end    = end;
+        _flags  = flags | NEEDS_FLUSH;
+    }
+
+    const char* GetStr();
+
+    bool Empty() const {
+        return _start == _end;
+    }
+
+    void SetInternedStr( const char* str ) {
+        Reset();
+        _start = const_cast<char*>(str);
+    }
+
+    void SetStr( const char* str, int flags=0 );
+
+    char* ParseText( char* in, const char* endTag, int strFlags );
+    char* ParseName( char* in );
+
+private:
+    void Reset();
+    void CollapseWhitespace();
+
+    enum {
+        NEEDS_FLUSH = 0x100,
+        NEEDS_DELETE = 0x200
+    };
+
+    // After parsing, if *_end != 0, it can be set to zero.
+    int     _flags;
+    char*   _start;
+    char*   _end;
+};
+
+
+/*
+	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
+	Has a small initial memory pool, so that low or no usage will not
+	cause a call to new/delete
+*/
+template <class T, int INIT>
+class DynArray
+{
+public:
+    DynArray< T, INIT >() {
+        _mem = _pool;
+        _allocated = INIT;
+        _size = 0;
+    }
+
+    ~DynArray() {
+        if ( _mem != _pool ) {
+            delete [] _mem;
+        }
+    }
+
+    void Push( T t ) {
+        EnsureCapacity( _size+1 );
+        _mem[_size++] = t;
+    }
+
+    T* PushArr( int count ) {
+        EnsureCapacity( _size+count );
+        T* ret = &_mem[_size];
+        _size += count;
+        return ret;
+    }
+
+    T Pop() {
+        return _mem[--_size];
+    }
+
+    void PopArr( int count ) {
+        TIXMLASSERT( _size >= count );
+        _size -= count;
+    }
+
+    bool Empty() const					{
+        return _size == 0;
+    }
+
+    T& operator[](int i)				{
+        TIXMLASSERT( i>= 0 && i < _size );
+        return _mem[i];
+    }
+
+    const T& operator[](int i) const	{
+        TIXMLASSERT( i>= 0 && i < _size );
+        return _mem[i];
+    }
+
+    int Size() const					{
+        return _size;
+    }
+
+    int Capacity() const				{
+        return _allocated;
+    }
+
+    const T* Mem() const				{
+        return _mem;
+    }
+
+    T* Mem()							{
+        return _mem;
+    }
+
+private:
+    void EnsureCapacity( int cap ) {
+        if ( cap > _allocated ) {
+            int newAllocated = cap * 2;
+            T* newMem = new T[newAllocated];
+            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
+            if ( _mem != _pool ) {
+                delete [] _mem;
+            }
+            _mem = newMem;
+            _allocated = newAllocated;
+        }
+    }
+
+    T*  _mem;
+    T   _pool[INIT];
+    int _allocated;		// objects allocated
+    int _size;			// number objects in use
+};
+
+
+/*
+	Parent virtual class of a pool for fast allocation
+	and deallocation of objects.
+*/
+class MemPool
+{
+public:
+    MemPool() {}
+    virtual ~MemPool() {}
+
+    virtual int ItemSize() const = 0;
+    virtual void* Alloc() = 0;
+    virtual void Free( void* ) = 0;
+    virtual void SetTracked() = 0;
+};
+
+
+/*
+	Template child class to create pools of the correct type.
+*/
+template< int SIZE >
+class MemPoolT : public MemPool
+{
+public:
+    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
+    ~MemPoolT() {
+        // Delete the blocks.
+        for( int i=0; i<_blockPtrs.Size(); ++i ) {
+            delete _blockPtrs[i];
+        }
+    }
+
+    virtual int ItemSize() const	{
+        return SIZE;
+    }
+    int CurrentAllocs() const		{
+        return _currentAllocs;
+    }
+
+    virtual void* Alloc() {
+        if ( !_root ) {
+            // Need a new block.
+            Block* block = new Block();
+            _blockPtrs.Push( block );
+
+            for( int i=0; i<COUNT-1; ++i ) {
+                block->chunk[i].next = &block->chunk[i+1];
+            }
+            block->chunk[COUNT-1].next = 0;
+            _root = block->chunk;
+        }
+        void* result = _root;
+        _root = _root->next;
+
+        ++_currentAllocs;
+        if ( _currentAllocs > _maxAllocs ) {
+            _maxAllocs = _currentAllocs;
+        }
+        _nAllocs++;
+        _nUntracked++;
+        return result;
+    }
+    virtual void Free( void* mem ) {
+        if ( !mem ) {
+            return;
+        }
+        --_currentAllocs;
+        Chunk* chunk = (Chunk*)mem;
+#ifdef DEBUG
+        memset( chunk, 0xfe, sizeof(Chunk) );
+#endif
+        chunk->next = _root;
+        _root = chunk;
+    }
+    void Trace( const char* name ) {
+        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
+                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
+    }
+
+    void SetTracked() {
+        _nUntracked--;
+    }
+
+    int Untracked() const {
+        return _nUntracked;
+    }
+
+	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
+	// The test file is large, 170k.
+	// Release:		VS2010 gcc(no opt)
+	//		1k:		4000
+	//		2k:		4000
+	//		4k:		3900	21000
+	//		16k:	5200
+	//		32k:	4300
+	//		64k:	4000	21000
+    enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
+
+private:
+    union Chunk {
+        Chunk*  next;
+        char    mem[SIZE];
+    };
+    struct Block {
+        Chunk chunk[COUNT];
+    };
+    DynArray< Block*, 10 > _blockPtrs;
+    Chunk* _root;
+
+    int _currentAllocs;
+    int _nAllocs;
+    int _maxAllocs;
+    int _nUntracked;
+};
+
+
+
+/**
+	Implements the interface to the "Visitor pattern" (see the Accept() method.)
+	If you call the Accept() method, it requires being passed a XMLVisitor
+	class to handle callbacks. For nodes that contain other nodes (Document, Element)
+	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
+	are simply called with Visit().
+
+	If you return 'true' from a Visit method, recursive parsing will continue. If you return
+	false, <b>no children of this node or its siblings</b> will be visited.
+
+	All flavors of Visit methods have a default implementation that returns 'true' (continue
+	visiting). You need to only override methods that are interesting to you.
+
+	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
+
+	You should never change the document from a callback.
+
+	@sa XMLNode::Accept()
+*/
+class XMLVisitor
+{
+public:
+    virtual ~XMLVisitor() {}
+
+    /// Visit a document.
+    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
+        return true;
+    }
+    /// Visit a document.
+    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
+        return true;
+    }
+
+    /// Visit an element.
+    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
+        return true;
+    }
+    /// Visit an element.
+    virtual bool VisitExit( const XMLElement& /*element*/ )			{
+        return true;
+    }
+
+    /// Visit a declaration.
+    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
+        return true;
+    }
+    /// Visit a text node.
+    virtual bool Visit( const XMLText& /*text*/ )					{
+        return true;
+    }
+    /// Visit a comment node.
+    virtual bool Visit( const XMLComment& /*comment*/ )				{
+        return true;
+    }
+    /// Visit an unknown node.
+    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
+        return true;
+    }
+};
+
+
+/*
+	Utility functionality.
+*/
+class XMLUtil
+{
+public:
+    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
+    // correct, but simple, and usually works.
+    static const char* SkipWhiteSpace( const char* p )	{
+        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
+            ++p;
+        }
+        return p;
+    }
+    static char* SkipWhiteSpace( char* p )				{
+        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
+            ++p;
+        }
+        return p;
+    }
+    static bool IsWhiteSpace( char p )					{
+        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
+    }
+    
+    inline static bool IsNameStartChar( unsigned char ch ) {
+        return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
+               || ch == ':'
+               || ch == '_';
+    }
+    
+    inline static bool IsNameChar( unsigned char ch ) {
+        return IsNameStartChar( ch )
+               || isdigit( ch )
+               || ch == '.'
+               || ch == '-';
+    }
+
+    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
+        int n = 0;
+        if ( p == q ) {
+            return true;
+        }
+        while( *p && *q && *p == *q && n<nChar ) {
+            ++p;
+            ++q;
+            ++n;
+        }
+        if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
+            return true;
+        }
+        return false;
+    }
+    
+    inline static int IsUTF8Continuation( const char p ) {
+        return p & 0x80;
+    }
+
+    static const char* ReadBOM( const char* p, bool* hasBOM );
+    // p is the starting location,
+    // the UTF-8 value of the entity will be placed in value, and length filled in.
+    static const char* GetCharacterRef( const char* p, char* value, int* length );
+    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+    // converts primitive types to strings
+    static void ToStr( int v, char* buffer, int bufferSize );
+    static void ToStr( unsigned v, char* buffer, int bufferSize );
+    static void ToStr( bool v, char* buffer, int bufferSize );
+    static void ToStr( float v, char* buffer, int bufferSize );
+    static void ToStr( double v, char* buffer, int bufferSize );
+
+    // converts strings to primitive types
+    static bool	ToInt( const char* str, int* value );
+    static bool ToUnsigned( const char* str, unsigned* value );
+    static bool	ToBool( const char* str, bool* value );
+    static bool	ToFloat( const char* str, float* value );
+    static bool ToDouble( const char* str, double* value );
+};
+
+
+/** XMLNode is a base class for every object that is in the
+	XML Document Object Model (DOM), except XMLAttributes.
+	Nodes have siblings, a parent, and children which can
+	be navigated. A node is always in a XMLDocument.
+	The type of a XMLNode can be queried, and it can
+	be cast to its more defined type.
+
+	A XMLDocument allocates memory for all its Nodes.
+	When the XMLDocument gets deleted, all its Nodes
+	will also be deleted.
+
+	@verbatim
+	A Document can contain:	Element	(container or leaf)
+							Comment (leaf)
+							Unknown (leaf)
+							Declaration( leaf )
+
+	An Element can contain:	Element (container or leaf)
+							Text	(leaf)
+							Attributes (not on tree)
+							Comment (leaf)
+							Unknown (leaf)
+
+	@endverbatim
+*/
+class XMLNode
+{
+    friend class XMLDocument;
+    friend class XMLElement;
+public:
+
+    /// Get the XMLDocument that owns this XMLNode.
+    const XMLDocument* GetDocument() const	{
+        return _document;
+    }
+    /// Get the XMLDocument that owns this XMLNode.
+    XMLDocument* GetDocument()				{
+        return _document;
+    }
+
+    /// Safely cast to an Element, or null.
+    virtual XMLElement*		ToElement()		{
+        return 0;
+    }
+    /// Safely cast to Text, or null.
+    virtual XMLText*		ToText()		{
+        return 0;
+    }
+    /// Safely cast to a Comment, or null.
+    virtual XMLComment*		ToComment()		{
+        return 0;
+    }
+    /// Safely cast to a Document, or null.
+    virtual XMLDocument*	ToDocument()	{
+        return 0;
+    }
+    /// Safely cast to a Declaration, or null.
+    virtual XMLDeclaration*	ToDeclaration()	{
+        return 0;
+    }
+    /// Safely cast to an Unknown, or null.
+    virtual XMLUnknown*		ToUnknown()		{
+        return 0;
+    }
+
+    virtual const XMLElement*		ToElement() const		{
+        return 0;
+    }
+    virtual const XMLText*			ToText() const			{
+        return 0;
+    }
+    virtual const XMLComment*		ToComment() const		{
+        return 0;
+    }
+    virtual const XMLDocument*		ToDocument() const		{
+        return 0;
+    }
+    virtual const XMLDeclaration*	ToDeclaration() const	{
+        return 0;
+    }
+    virtual const XMLUnknown*		ToUnknown() const		{
+        return 0;
+    }
+
+    /** The meaning of 'value' changes for the specific type.
+    	@verbatim
+    	Document:	empty
+    	Element:	name of the element
+    	Comment:	the comment text
+    	Unknown:	the tag contents
+    	Text:		the text string
+    	@endverbatim
+    */
+    const char* Value() const			{
+        return _value.GetStr();
+    }
+
+    /** Set the Value of an XML node.
+    	@sa Value()
+    */
+    void SetValue( const char* val, bool staticMem=false );
+
+    /// Get the parent of this node on the DOM.
+    const XMLNode*	Parent() const			{
+        return _parent;
+    }
+
+    XMLNode* Parent()						{
+        return _parent;
+    }
+
+    /// Returns true if this node has no children.
+    bool NoChildren() const					{
+        return !_firstChild;
+    }
+
+    /// Get the first child node, or null if none exists.
+    const XMLNode*  FirstChild() const		{
+        return _firstChild;
+    }
+
+    XMLNode*		FirstChild()			{
+        return _firstChild;
+    }
+
+    /** Get the first child element, or optionally the first child
+        element with the specified name.
+    */
+    const XMLElement* FirstChildElement( const char* value=0 ) const;
+
+    XMLElement* FirstChildElement( const char* value=0 )	{
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
+    }
+
+    /// Get the last child node, or null if none exists.
+    const XMLNode*	LastChild() const						{
+        return _lastChild;
+    }
+
+    XMLNode*		LastChild()								{
+        return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
+    }
+
+    /** Get the last child element or optionally the last child
+        element with the specified name.
+    */
+    const XMLElement* LastChildElement( const char* value=0 ) const;
+
+    XMLElement* LastChildElement( const char* value=0 )	{
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
+    }
+
+    /// Get the previous (left) sibling node of this node.
+    const XMLNode*	PreviousSibling() const					{
+        return _prev;
+    }
+
+    XMLNode*	PreviousSibling()							{
+        return _prev;
+    }
+
+    /// Get the previous (left) sibling element of this node, with an optionally supplied name.
+    const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
+
+    XMLElement*	PreviousSiblingElement( const char* value=0 ) {
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
+    }
+
+    /// Get the next (right) sibling node of this node.
+    const XMLNode*	NextSibling() const						{
+        return _next;
+    }
+
+    XMLNode*	NextSibling()								{
+        return _next;
+    }
+
+    /// Get the next (right) sibling element of this node, with an optionally supplied name.
+    const XMLElement*	NextSiblingElement( const char* value=0 ) const;
+
+    XMLElement*	NextSiblingElement( const char* value=0 )	{
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
+    }
+
+    /**
+    	Add a child node as the last (right) child.
+    */
+    XMLNode* InsertEndChild( XMLNode* addThis );
+
+    XMLNode* LinkEndChild( XMLNode* addThis )	{
+        return InsertEndChild( addThis );
+    }
+    /**
+    	Add a child node as the first (left) child.
+    */
+    XMLNode* InsertFirstChild( XMLNode* addThis );
+    /**
+    	Add a node after the specified child node.
+    */
+    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
+
+    /**
+    	Delete all the children of this node.
+    */
+    void DeleteChildren();
+
+    /**
+    	Delete a child of this node.
+    */
+    void DeleteChild( XMLNode* node );
+
+    /**
+    	Make a copy of this node, but not its children.
+    	You may pass in a Document pointer that will be
+    	the owner of the new Node. If the 'document' is
+    	null, then the node returned will be allocated
+    	from the current Document. (this->GetDocument())
+
+    	Note: if called on a XMLDocument, this will return null.
+    */
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
+
+    /**
+    	Test if 2 nodes are the same, but don't test children.
+    	The 2 nodes do not need to be in the same Document.
+
+    	Note: if called on a XMLDocument, this will return false.
+    */
+    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
+
+    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
+    	XML tree will be conditionally visited and the host will be called back
+    	via the XMLVisitor interface.
+
+    	This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
+    	the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
+    	interface versus any other.)
+
+    	The interface has been based on ideas from:
+
+    	- http://www.saxproject.org/
+    	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+
+    	Which are both good references for "visiting".
+
+    	An example of using Accept():
+    	@verbatim
+    	XMLPrinter printer;
+    	tinyxmlDoc.Accept( &printer );
+    	const char* xmlcstr = printer.CStr();
+    	@endverbatim
+    */
+    virtual bool Accept( XMLVisitor* visitor ) const = 0;
+
+    // internal
+    virtual char* ParseDeep( char*, StrPair* );
+
+protected:
+    XMLNode( XMLDocument* );
+    virtual ~XMLNode();
+    XMLNode( const XMLNode& );	// not supported
+    XMLNode& operator=( const XMLNode& );	// not supported
+
+    XMLDocument*	_document;
+    XMLNode*		_parent;
+    mutable StrPair	_value;
+
+    XMLNode*		_firstChild;
+    XMLNode*		_lastChild;
+
+    XMLNode*		_prev;
+    XMLNode*		_next;
+
+private:
+    MemPool*		_memPool;
+    void Unlink( XMLNode* child );
+};
+
+
+/** XML text.
+
+	Note that a text node can have child element nodes, for example:
+	@verbatim
+	<root>This is <b>bold</b></root>
+	@endverbatim
+
+	A text node can have 2 ways to output the next. "normal" output
+	and CDATA. It will default to the mode it was parsed from the XML file and
+	you generally want to leave it alone, but you can change the output mode with
+	SetCData() and query it with CData().
+*/
+class XMLText : public XMLNode
+{
+    friend class XMLBase;
+    friend class XMLDocument;
+public:
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    virtual XMLText* ToText()			{
+        return this;
+    }
+    virtual const XMLText* ToText() const	{
+        return this;
+    }
+
+    /// Declare whether this should be CDATA or standard text.
+    void SetCData( bool isCData )			{
+        _isCData = isCData;
+    }
+    /// Returns true if this is a CDATA text element.
+    bool CData() const						{
+        return _isCData;
+    }
+
+    char* ParseDeep( char*, StrPair* endTag );
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+    virtual bool ShallowEqual( const XMLNode* compare ) const;
+
+protected:
+    XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
+    virtual ~XMLText()												{}
+    XMLText( const XMLText& );	// not supported
+    XMLText& operator=( const XMLText& );	// not supported
+
+private:
+    bool _isCData;
+};
+
+
+/** An XML Comment. */
+class XMLComment : public XMLNode
+{
+    friend class XMLDocument;
+public:
+    virtual XMLComment*	ToComment()					{
+        return this;
+    }
+    virtual const XMLComment* ToComment() const		{
+        return this;
+    }
+
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    char* ParseDeep( char*, StrPair* endTag );
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+    virtual bool ShallowEqual( const XMLNode* compare ) const;
+
+protected:
+    XMLComment( XMLDocument* doc );
+    virtual ~XMLComment();
+    XMLComment( const XMLComment& );	// not supported
+    XMLComment& operator=( const XMLComment& );	// not supported
+
+private:
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+	@verbatim
+		<?xml version="1.0" standalone="yes"?>
+	@endverbatim
+
+	TinyXML-2 will happily read or write files without a declaration,
+	however.
+
+	The text of the declaration isn't interpreted. It is parsed
+	and written as a string.
+*/
+class XMLDeclaration : public XMLNode
+{
+    friend class XMLDocument;
+public:
+    virtual XMLDeclaration*	ToDeclaration()					{
+        return this;
+    }
+    virtual const XMLDeclaration* ToDeclaration() const		{
+        return this;
+    }
+
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    char* ParseDeep( char*, StrPair* endTag );
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+    virtual bool ShallowEqual( const XMLNode* compare ) const;
+
+protected:
+    XMLDeclaration( XMLDocument* doc );
+    virtual ~XMLDeclaration();
+    XMLDeclaration( const XMLDeclaration& );	// not supported
+    XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
+};
+
+
+/** Any tag that TinyXML-2 doesn't recognize is saved as an
+	unknown. It is a tag of text, but should not be modified.
+	It will be written back to the XML, unchanged, when the file
+	is saved.
+
+	DTD tags get thrown into XMLUnknowns.
+*/
+class XMLUnknown : public XMLNode
+{
+    friend class XMLDocument;
+public:
+    virtual XMLUnknown*	ToUnknown()					{
+        return this;
+    }
+    virtual const XMLUnknown* ToUnknown() const		{
+        return this;
+    }
+
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    char* ParseDeep( char*, StrPair* endTag );
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+    virtual bool ShallowEqual( const XMLNode* compare ) const;
+
+protected:
+    XMLUnknown( XMLDocument* doc );
+    virtual ~XMLUnknown();
+    XMLUnknown( const XMLUnknown& );	// not supported
+    XMLUnknown& operator=( const XMLUnknown& );	// not supported
+};
+
+
+enum XMLError {
+    XML_NO_ERROR = 0,
+    XML_SUCCESS = 0,
+
+    XML_NO_ATTRIBUTE,
+    XML_WRONG_ATTRIBUTE_TYPE,
+
+    XML_ERROR_FILE_NOT_FOUND,
+    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
+    XML_ERROR_FILE_READ_ERROR,
+    XML_ERROR_ELEMENT_MISMATCH,
+    XML_ERROR_PARSING_ELEMENT,
+    XML_ERROR_PARSING_ATTRIBUTE,
+    XML_ERROR_IDENTIFYING_TAG,
+    XML_ERROR_PARSING_TEXT,
+    XML_ERROR_PARSING_CDATA,
+    XML_ERROR_PARSING_COMMENT,
+    XML_ERROR_PARSING_DECLARATION,
+    XML_ERROR_PARSING_UNKNOWN,
+    XML_ERROR_EMPTY_DOCUMENT,
+    XML_ERROR_MISMATCHED_ELEMENT,
+    XML_ERROR_PARSING,
+
+    XML_CAN_NOT_CONVERT_TEXT,
+    XML_NO_TEXT_NODE
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+	number of attributes, each with a unique name.
+
+	@note The attributes are not XMLNodes. You may only query the
+	Next() attribute in a list.
+*/
+class XMLAttribute
+{
+    friend class XMLElement;
+public:
+    /// The name of the attribute.
+    const char* Name() const {
+        return _name.GetStr();
+    }
+    /// The value of the attribute.
+    const char* Value() const {
+        return _value.GetStr();
+    }
+    /// The next attribute in the list.
+    const XMLAttribute* Next() const {
+        return _next;
+    }
+
+    /** IntValue interprets the attribute as an integer, and returns the value.
+        If the value isn't an integer, 0 will be returned. There is no error checking;
+    	use QueryIntValue() if you need error checking.
+    */
+    int		 IntValue() const				{
+        int i=0;
+        QueryIntValue( &i );
+        return i;
+    }
+    /// Query as an unsigned integer. See IntValue()
+    unsigned UnsignedValue() const			{
+        unsigned i=0;
+        QueryUnsignedValue( &i );
+        return i;
+    }
+    /// Query as a boolean. See IntValue()
+    bool	 BoolValue() const				{
+        bool b=false;
+        QueryBoolValue( &b );
+        return b;
+    }
+    /// Query as a double. See IntValue()
+    double 	 DoubleValue() const			{
+        double d=0;
+        QueryDoubleValue( &d );
+        return d;
+    }
+    /// Query as a float. See IntValue()
+    float	 FloatValue() const				{
+        float f=0;
+        QueryFloatValue( &f );
+        return f;
+    }
+
+    /** QueryIntValue interprets the attribute as an integer, and returns the value
+    	in the provided parameter. The function will return XML_NO_ERROR on success,
+    	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
+    */
+    XMLError QueryIntValue( int* value ) const;
+    /// See QueryIntValue
+    XMLError QueryUnsignedValue( unsigned int* value ) const;
+    /// See QueryIntValue
+    XMLError QueryBoolValue( bool* value ) const;
+    /// See QueryIntValue
+    XMLError QueryDoubleValue( double* value ) const;
+    /// See QueryIntValue
+    XMLError QueryFloatValue( float* value ) const;
+
+    /// Set the attribute to a string value.
+    void SetAttribute( const char* value );
+    /// Set the attribute to value.
+    void SetAttribute( int value );
+    /// Set the attribute to value.
+    void SetAttribute( unsigned value );
+    /// Set the attribute to value.
+    void SetAttribute( bool value );
+    /// Set the attribute to value.
+    void SetAttribute( double value );
+    /// Set the attribute to value.
+    void SetAttribute( float value );
+
+private:
+    enum { BUF_SIZE = 200 };
+
+    XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
+    virtual ~XMLAttribute()	{}
+
+    XMLAttribute( const XMLAttribute& );	// not supported
+    void operator=( const XMLAttribute& );	// not supported
+    void SetName( const char* name );
+
+    char* ParseDeep( char* p, bool processEntities );
+
+    mutable StrPair _name;
+    mutable StrPair _value;
+    XMLAttribute*   _next;
+    MemPool*        _memPool;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+	and can contain other elements, text, comments, and unknowns.
+	Elements also contain an arbitrary number of attributes.
+*/
+class XMLElement : public XMLNode
+{
+    friend class XMLBase;
+    friend class XMLDocument;
+public:
+    /// Get the name of an element (which is the Value() of the node.)
+    const char* Name() const		{
+        return Value();
+    }
+    /// Set the name of the element.
+    void SetName( const char* str, bool staticMem=false )	{
+        SetValue( str, staticMem );
+    }
+
+    virtual XMLElement* ToElement()				{
+        return this;
+    }
+    virtual const XMLElement* ToElement() const {
+        return this;
+    }
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    /** Given an attribute name, Attribute() returns the value
+    	for the attribute of that name, or null if none
+    	exists. For example:
+
+    	@verbatim
+    	const char* value = ele->Attribute( "foo" );
+    	@endverbatim
+
+    	The 'value' parameter is normally null. However, if specified,
+    	the attribute will only be returned if the 'name' and 'value'
+    	match. This allow you to write code:
+
+    	@verbatim
+    	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
+    	@endverbatim
+
+    	rather than:
+    	@verbatim
+    	if ( ele->Attribute( "foo" ) ) {
+    		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
+    	}
+    	@endverbatim
+    */
+    const char* Attribute( const char* name, const char* value=0 ) const;
+
+    /** Given an attribute name, IntAttribute() returns the value
+    	of the attribute interpreted as an integer. 0 will be
+    	returned if there is an error. For a method with error
+    	checking, see QueryIntAttribute()
+    */
+    int		 IntAttribute( const char* name ) const		{
+        int i=0;
+        QueryIntAttribute( name, &i );
+        return i;
+    }
+    /// See IntAttribute()
+    unsigned UnsignedAttribute( const char* name ) const {
+        unsigned i=0;
+        QueryUnsignedAttribute( name, &i );
+        return i;
+    }
+    /// See IntAttribute()
+    bool	 BoolAttribute( const char* name ) const	{
+        bool b=false;
+        QueryBoolAttribute( name, &b );
+        return b;
+    }
+    /// See IntAttribute()
+    double 	 DoubleAttribute( const char* name ) const	{
+        double d=0;
+        QueryDoubleAttribute( name, &d );
+        return d;
+    }
+    /// See IntAttribute()
+    float	 FloatAttribute( const char* name ) const	{
+        float f=0;
+        QueryFloatAttribute( name, &f );
+        return f;
+    }
+
+    /** Given an attribute name, QueryIntAttribute() returns
+    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
+    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
+    	doesn't exist. If successful, the result of the conversion
+    	will be written to 'value'. If not successful, nothing will
+    	be written to 'value'. This allows you to provide default
+    	value:
+
+    	@verbatim
+    	int value = 10;
+    	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
+    	@endverbatim
+    */
+    XMLError QueryIntAttribute( const char* name, int* value ) const				{
+        const XMLAttribute* a = FindAttribute( name );
+        if ( !a ) {
+            return XML_NO_ATTRIBUTE;
+        }
+        return a->QueryIntValue( value );
+    }
+    /// See QueryIntAttribute()
+    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
+        const XMLAttribute* a = FindAttribute( name );
+        if ( !a ) {
+            return XML_NO_ATTRIBUTE;
+        }
+        return a->QueryUnsignedValue( value );
+    }
+    /// See QueryIntAttribute()
+    XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
+        const XMLAttribute* a = FindAttribute( name );
+        if ( !a ) {
+            return XML_NO_ATTRIBUTE;
+        }
+        return a->QueryBoolValue( value );
+    }
+    /// See QueryIntAttribute()
+    XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
+        const XMLAttribute* a = FindAttribute( name );
+        if ( !a ) {
+            return XML_NO_ATTRIBUTE;
+        }
+        return a->QueryDoubleValue( value );
+    }
+    /// See QueryIntAttribute()
+    XMLError QueryFloatAttribute( const char* name, float* value ) const			{
+        const XMLAttribute* a = FindAttribute( name );
+        if ( !a ) {
+            return XML_NO_ATTRIBUTE;
+        }
+        return a->QueryFloatValue( value );
+    }
+
+	
+    /** Given an attribute name, QueryAttribute() returns
+    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
+    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
+    	doesn't exist. It is overloaded for the primitive types,
+		and is a generally more convenient replacement of
+		QueryIntAttribute() and related functions.
+		
+		If successful, the result of the conversion
+    	will be written to 'value'. If not successful, nothing will
+    	be written to 'value'. This allows you to provide default
+    	value:
+
+    	@verbatim
+    	int value = 10;
+    	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
+    	@endverbatim
+    */
+	int QueryAttribute( const char* name, int* value ) const {
+		return QueryIntAttribute( name, value );
+	}
+
+	int QueryAttribute( const char* name, unsigned int* value ) const {
+		return QueryUnsignedAttribute( name, value );
+	}
+
+	int QueryAttribute( const char* name, bool* value ) const {
+		return QueryBoolAttribute( name, value );
+	}
+
+	int QueryAttribute( const char* name, double* value ) const {
+		return QueryDoubleAttribute( name, value );
+	}
+
+	int QueryAttribute( const char* name, float* value ) const {
+		return QueryFloatAttribute( name, value );
+	}
+
+	/// Sets the named attribute to value.
+    void SetAttribute( const char* name, const char* value )	{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
+    /// Sets the named attribute to value.
+    void SetAttribute( const char* name, int value )			{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
+    /// Sets the named attribute to value.
+    void SetAttribute( const char* name, unsigned value )		{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
+    /// Sets the named attribute to value.
+    void SetAttribute( const char* name, bool value )			{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
+    /// Sets the named attribute to value.
+    void SetAttribute( const char* name, double value )		{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
+
+    /**
+    	Delete an attribute.
+    */
+    void DeleteAttribute( const char* name );
+
+    /// Return the first attribute in the list.
+    const XMLAttribute* FirstAttribute() const {
+        return _rootAttribute;
+    }
+    /// Query a specific attribute in the list.
+    const XMLAttribute* FindAttribute( const char* name ) const;
+
+    /** Convenience function for easy access to the text inside an element. Although easy
+    	and concise, GetText() is limited compared to getting the XMLText child
+    	and accessing it directly.
+
+    	If the first child of 'this' is a XMLText, the GetText()
+    	returns the character string of the Text node, else null is returned.
+
+    	This is a convenient method for getting the text of simple contained text:
+    	@verbatim
+    	<foo>This is text</foo>
+    		const char* str = fooElement->GetText();
+    	@endverbatim
+
+    	'str' will be a pointer to "This is text".
+
+    	Note that this function can be misleading. If the element foo was created from
+    	this XML:
+    	@verbatim
+    		<foo><b>This is text</b></foo>
+    	@endverbatim
+
+    	then the value of str would be null. The first child node isn't a text node, it is
+    	another element. From this XML:
+    	@verbatim
+    		<foo>This is <b>text</b></foo>
+    	@endverbatim
+    	GetText() will return "This is ".
+    */
+    const char* GetText() const;
+
+    /**
+    	Convenience method to query the value of a child text node. This is probably best
+    	shown by example. Given you have a document is this form:
+    	@verbatim
+    		<point>
+    			<x>1</x>
+    			<y>1.4</y>
+    		</point>
+    	@endverbatim
+
+    	The QueryIntText() and similar functions provide a safe and easier way to get to the
+    	"value" of x and y.
+
+    	@verbatim
+    		int x = 0;
+    		float y = 0;	// types of x and y are contrived for example
+    		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
+    		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
+    		xElement->QueryIntText( &x );
+    		yElement->QueryFloatText( &y );
+    	@endverbatim
+
+    	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
+    			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
+
+    */
+    XMLError QueryIntText( int* ival ) const;
+    /// See QueryIntText()
+    XMLError QueryUnsignedText( unsigned* uval ) const;
+    /// See QueryIntText()
+    XMLError QueryBoolText( bool* bval ) const;
+    /// See QueryIntText()
+    XMLError QueryDoubleText( double* dval ) const;
+    /// See QueryIntText()
+    XMLError QueryFloatText( float* fval ) const;
+
+    // internal:
+    enum {
+        OPEN,		// <foo>
+        CLOSED,		// <foo/>
+        CLOSING		// </foo>
+    };
+    int ClosingType() const {
+        return _closingType;
+    }
+    char* ParseDeep( char* p, StrPair* endTag );
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
+    virtual bool ShallowEqual( const XMLNode* compare ) const;
+
+private:
+    XMLElement( XMLDocument* doc );
+    virtual ~XMLElement();
+    XMLElement( const XMLElement& );	// not supported
+    void operator=( const XMLElement& );	// not supported
+
+    XMLAttribute* FindAttribute( const char* name );
+    XMLAttribute* FindOrCreateAttribute( const char* name );
+    //void LinkAttribute( XMLAttribute* attrib );
+    char* ParseAttributes( char* p );
+
+    int _closingType;
+    // The attribute list is ordered; there is no 'lastAttribute'
+    // because the list needs to be scanned for dupes before adding
+    // a new attribute.
+    XMLAttribute* _rootAttribute;
+};
+
+
+enum Whitespace {
+    PRESERVE_WHITESPACE,
+    COLLAPSE_WHITESPACE
+};
+
+
+/** A Document binds together all the functionality.
+	It can be saved, loaded, and printed to the screen.
+	All Nodes are connected and allocated to a Document.
+	If the Document is deleted, all its Nodes are also deleted.
+*/
+class XMLDocument : public XMLNode
+{
+    friend class XMLElement;
+public:
+    /// constructor
+    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
+    ~XMLDocument();
+
+    virtual XMLDocument* ToDocument()				{
+        return this;
+    }
+    virtual const XMLDocument* ToDocument() const	{
+        return this;
+    }
+
+    /**
+    	Parse an XML file from a character string.
+    	Returns XML_NO_ERROR (0) on success, or
+    	an errorID.
+
+    	You may optionally pass in the 'nBytes', which is
+    	the number of bytes which will be parsed. If not
+    	specified, TinyXML-2 will assume 'xml' points to a
+    	null terminated string.
+    */
+    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
+
+    /**
+    	Load an XML file from disk.
+    	Returns XML_NO_ERROR (0) on success, or
+    	an errorID.
+    */
+    XMLError LoadFile( const char* filename );
+
+    /**
+    	Load an XML file from disk. You are responsible
+    	for providing and closing the FILE*.
+
+    	Returns XML_NO_ERROR (0) on success, or
+    	an errorID.
+    */
+    XMLError LoadFile( FILE* );
+
+    /**
+    	Save the XML file to disk.
+    	Returns XML_NO_ERROR (0) on success, or
+    	an errorID.
+    */
+    XMLError SaveFile( const char* filename, bool compact = false );
+
+    /**
+    	Save the XML file to disk. You are responsible
+    	for providing and closing the FILE*.
+
+    	Returns XML_NO_ERROR (0) on success, or
+    	an errorID.
+    */
+    XMLError SaveFile( FILE* fp, bool compact = false );
+
+    bool ProcessEntities() const		{
+        return _processEntities;
+    }
+    Whitespace WhitespaceMode() const	{
+        return _whitespace;
+    }
+
+    /**
+    	Returns true if this document has a leading Byte Order Mark of UTF8.
+    */
+    bool HasBOM() const {
+        return _writeBOM;
+    }
+    /** Sets whether to write the BOM when writing the file.
+    */
+    void SetBOM( bool useBOM ) {
+        _writeBOM = useBOM;
+    }
+
+    /** Return the root element of DOM. Equivalent to FirstChildElement().
+        To get the first node, use FirstChild().
+    */
+    XMLElement* RootElement()				{
+        return FirstChildElement();
+    }
+    const XMLElement* RootElement() const	{
+        return FirstChildElement();
+    }
+
+    /** Print the Document. If the Printer is not provided, it will
+        print to stdout. If you provide Printer, this can print to a file:
+    	@verbatim
+    	XMLPrinter printer( fp );
+    	doc.Print( &printer );
+    	@endverbatim
+
+    	Or you can use a printer to print to memory:
+    	@verbatim
+    	XMLPrinter printer;
+    	doc.Print( &printer );
+    	// printer.CStr() has a const char* to the XML
+    	@endverbatim
+    */
+    void Print( XMLPrinter* streamer=0 ) const;
+    virtual bool Accept( XMLVisitor* visitor ) const;
+
+    /**
+    	Create a new Element associated with
+    	this Document. The memory for the Element
+    	is managed by the Document.
+    */
+    XMLElement* NewElement( const char* name );
+    /**
+    	Create a new Comment associated with
+    	this Document. The memory for the Comment
+    	is managed by the Document.
+    */
+    XMLComment* NewComment( const char* comment );
+    /**
+    	Create a new Text associated with
+    	this Document. The memory for the Text
+    	is managed by the Document.
+    */
+    XMLText* NewText( const char* text );
+    /**
+    	Create a new Declaration associated with
+    	this Document. The memory for the object
+    	is managed by the Document.
+
+    	If the 'text' param is null, the standard
+    	declaration is used.:
+    	@verbatim
+    		<?xml version="1.0" encoding="UTF-8"?>
+    	@endverbatim
+    */
+    XMLDeclaration* NewDeclaration( const char* text=0 );
+    /**
+    	Create a new Unknown associated with
+    	this Document. The memory for the object
+    	is managed by the Document.
+    */
+    XMLUnknown* NewUnknown( const char* text );
+
+    /**
+    	Delete a node associated with this document.
+    	It will be unlinked from the DOM.
+    */
+    void DeleteNode( XMLNode* node )	{
+        node->_parent->DeleteChild( node );
+    }
+
+    void SetError( XMLError error, const char* str1, const char* str2 );
+
+    /// Return true if there was an error parsing the document.
+    bool Error() const {
+        return _errorID != XML_NO_ERROR;
+    }
+    /// Return the errorID.
+    XMLError  ErrorID() const {
+        return _errorID;
+    }
+    /// Return a possibly helpful diagnostic location or string.
+    const char* GetErrorStr1() const {
+        return _errorStr1;
+    }
+    /// Return a possibly helpful secondary diagnostic location or string.
+    const char* GetErrorStr2() const {
+        return _errorStr2;
+    }
+    /// If there is an error, print it to stdout.
+    void PrintError() const;
+    
+    /// Clear the document, resetting it to the initial state.
+    void Clear();
+
+    // internal
+    char* Identify( char* p, XMLNode** node );
+
+    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
+        return 0;
+    }
+    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
+        return false;
+    }
+
+private:
+    XMLDocument( const XMLDocument& );	// not supported
+    void operator=( const XMLDocument& );	// not supported
+
+    bool        _writeBOM;
+    bool        _processEntities;
+    XMLError    _errorID;
+    Whitespace  _whitespace;
+    const char* _errorStr1;
+    const char* _errorStr2;
+    char*       _charBuffer;
+
+    MemPoolT< sizeof(XMLElement) >	 _elementPool;
+    MemPoolT< sizeof(XMLAttribute) > _attributePool;
+    MemPoolT< sizeof(XMLText) >		 _textPool;
+    MemPoolT< sizeof(XMLComment) >	 _commentPool;
+};
+
+
+/**
+	A XMLHandle is a class that wraps a node pointer with null checks; this is
+	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
+	DOM structure. It is a separate utility class.
+
+	Take an example:
+	@verbatim
+	<Document>
+		<Element attributeA = "valueA">
+			<Child attributeB = "value1" />
+			<Child attributeB = "value2" />
+		</Element>
+	</Document>
+	@endverbatim
+
+	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+	easy to write a *lot* of code that looks like:
+
+	@verbatim
+	XMLElement* root = document.FirstChildElement( "Document" );
+	if ( root )
+	{
+		XMLElement* element = root->FirstChildElement( "Element" );
+		if ( element )
+		{
+			XMLElement* child = element->FirstChildElement( "Child" );
+			if ( child )
+			{
+				XMLElement* child2 = child->NextSiblingElement( "Child" );
+				if ( child2 )
+				{
+					// Finally do something useful.
+	@endverbatim
+
+	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
+	of such code. A XMLHandle checks for null pointers so it is perfectly safe
+	and correct to use:
+
+	@verbatim
+	XMLHandle docHandle( &document );
+	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
+	if ( child2 )
+	{
+		// do something useful
+	@endverbatim
+
+	Which is MUCH more concise and useful.
+
+	It is also safe to copy handles - internally they are nothing more than node pointers.
+	@verbatim
+	XMLHandle handleCopy = handle;
+	@endverbatim
+
+	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
+*/
+class XMLHandle
+{
+public:
+    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+    XMLHandle( XMLNode* node )												{
+        _node = node;
+    }
+    /// Create a handle from a node.
+    XMLHandle( XMLNode& node )												{
+        _node = &node;
+    }
+    /// Copy constructor
+    XMLHandle( const XMLHandle& ref )										{
+        _node = ref._node;
+    }
+    /// Assignment
+    XMLHandle& operator=( const XMLHandle& ref )							{
+        _node = ref._node;
+        return *this;
+    }
+
+    /// Get the first child of this handle.
+    XMLHandle FirstChild() 													{
+        return XMLHandle( _node ? _node->FirstChild() : 0 );
+    }
+    /// Get the first child element of this handle.
+    XMLHandle FirstChildElement( const char* value=0 )						{
+        return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
+    }
+    /// Get the last child of this handle.
+    XMLHandle LastChild()													{
+        return XMLHandle( _node ? _node->LastChild() : 0 );
+    }
+    /// Get the last child element of this handle.
+    XMLHandle LastChildElement( const char* _value=0 )						{
+        return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
+    }
+    /// Get the previous sibling of this handle.
+    XMLHandle PreviousSibling()												{
+        return XMLHandle( _node ? _node->PreviousSibling() : 0 );
+    }
+    /// Get the previous sibling element of this handle.
+    XMLHandle PreviousSiblingElement( const char* _value=0 )				{
+        return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
+    }
+    /// Get the next sibling of this handle.
+    XMLHandle NextSibling()													{
+        return XMLHandle( _node ? _node->NextSibling() : 0 );
+    }
+    /// Get the next sibling element of this handle.
+    XMLHandle NextSiblingElement( const char* _value=0 )					{
+        return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
+    }
+
+    /// Safe cast to XMLNode. This can return null.
+    XMLNode* ToNode()							{
+        return _node;
+    }
+    /// Safe cast to XMLElement. This can return null.
+    XMLElement* ToElement() 					{
+        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
+    }
+    /// Safe cast to XMLText. This can return null.
+    XMLText* ToText() 							{
+        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
+    }
+    /// Safe cast to XMLUnknown. This can return null.
+    XMLUnknown* ToUnknown() 					{
+        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
+    }
+    /// Safe cast to XMLDeclaration. This can return null.
+    XMLDeclaration* ToDeclaration() 			{
+        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
+    }
+
+private:
+    XMLNode* _node;
+};
+
+
+/**
+	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
+	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
+*/
+class XMLConstHandle
+{
+public:
+    XMLConstHandle( const XMLNode* node )											{
+        _node = node;
+    }
+    XMLConstHandle( const XMLNode& node )											{
+        _node = &node;
+    }
+    XMLConstHandle( const XMLConstHandle& ref )										{
+        _node = ref._node;
+    }
+
+    XMLConstHandle& operator=( const XMLConstHandle& ref )							{
+        _node = ref._node;
+        return *this;
+    }
+
+    const XMLConstHandle FirstChild() const											{
+        return XMLConstHandle( _node ? _node->FirstChild() : 0 );
+    }
+    const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
+        return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
+    }
+    const XMLConstHandle LastChild()	const										{
+        return XMLConstHandle( _node ? _node->LastChild() : 0 );
+    }
+    const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
+        return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
+    }
+    const XMLConstHandle PreviousSibling() const									{
+        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
+    }
+    const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
+        return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
+    }
+    const XMLConstHandle NextSibling() const										{
+        return XMLConstHandle( _node ? _node->NextSibling() : 0 );
+    }
+    const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
+        return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
+    }
+
+
+    const XMLNode* ToNode() const				{
+        return _node;
+    }
+    const XMLElement* ToElement() const			{
+        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
+    }
+    const XMLText* ToText() const				{
+        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
+    }
+    const XMLUnknown* ToUnknown() const			{
+        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
+    }
+    const XMLDeclaration* ToDeclaration() const	{
+        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
+    }
+
+private:
+    const XMLNode* _node;
+};
+
+
+/**
+	Printing functionality. The XMLPrinter gives you more
+	options than the XMLDocument::Print() method.
+
+	It can:
+	-# Print to memory.
+	-# Print to a file you provide.
+	-# Print XML without a XMLDocument.
+
+	Print to Memory
+
+	@verbatim
+	XMLPrinter printer;
+	doc.Print( &printer );
+	SomeFunction( printer.CStr() );
+	@endverbatim
+
+	Print to a File
+
+	You provide the file pointer.
+	@verbatim
+	XMLPrinter printer( fp );
+	doc.Print( &printer );
+	@endverbatim
+
+	Print without a XMLDocument
+
+	When loading, an XML parser is very useful. However, sometimes
+	when saving, it just gets in the way. The code is often set up
+	for streaming, and constructing the DOM is just overhead.
+
+	The Printer supports the streaming case. The following code
+	prints out a trivially simple XML file without ever creating
+	an XML document.
+
+	@verbatim
+	XMLPrinter printer( fp );
+	printer.OpenElement( "foo" );
+	printer.PushAttribute( "foo", "bar" );
+	printer.CloseElement();
+	@endverbatim
+*/
+class XMLPrinter : public XMLVisitor
+{
+public:
+    /** Construct the printer. If the FILE* is specified,
+    	this will print to the FILE. Else it will print
+    	to memory, and the result is available in CStr().
+    	If 'compact' is set to true, then output is created
+    	with only required whitespace and newlines.
+    */
+    XMLPrinter( FILE* file=0, bool compact = false );
+    ~XMLPrinter()	{}
+
+    /** If streaming, write the BOM and declaration. */
+    void PushHeader( bool writeBOM, bool writeDeclaration );
+    /** If streaming, start writing an element.
+        The element must be closed with CloseElement()
+    */
+    void OpenElement( const char* name );
+    /// If streaming, add an attribute to an open element.
+    void PushAttribute( const char* name, const char* value );
+    void PushAttribute( const char* name, int value );
+    void PushAttribute( const char* name, unsigned value );
+    void PushAttribute( const char* name, bool value );
+    void PushAttribute( const char* name, double value );
+    /// If streaming, close the Element.
+    void CloseElement();
+
+    /// Add a text node.
+    void PushText( const char* text, bool cdata=false );
+    /// Add a text node from an integer.
+    void PushText( int value );
+    /// Add a text node from an unsigned.
+    void PushText( unsigned value );
+    /// Add a text node from a bool.
+    void PushText( bool value );
+    /// Add a text node from a float.
+    void PushText( float value );
+    /// Add a text node from a double.
+    void PushText( double value );
+
+    /// Add a comment
+    void PushComment( const char* comment );
+
+    void PushDeclaration( const char* value );
+    void PushUnknown( const char* value );
+
+    virtual bool VisitEnter( const XMLDocument& /*doc*/ );
+    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
+        return true;
+    }
+
+    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
+    virtual bool VisitExit( const XMLElement& element );
+
+    virtual bool Visit( const XMLText& text );
+    virtual bool Visit( const XMLComment& comment );
+    virtual bool Visit( const XMLDeclaration& declaration );
+    virtual bool Visit( const XMLUnknown& unknown );
+
+    /**
+    	If in print to memory mode, return a pointer to
+    	the XML file in memory.
+    */
+    const char* CStr() const {
+        return _buffer.Mem();
+    }
+    /**
+    	If in print to memory mode, return the size
+    	of the XML file in memory. (Note the size returned
+    	includes the terminating null.)
+    */
+    int CStrSize() const {
+        return _buffer.Size();
+    }
+
+private:
+    void SealElement();
+    void PrintSpace( int depth );
+    void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
+    void Print( const char* format, ... );
+
+    bool _elementJustOpened;
+    bool _firstElement;
+    FILE* _fp;
+    int _depth;
+    int _textDepth;
+    bool _processEntities;
+    bool _compactMode;
+
+    enum {
+        ENTITY_RANGE = 64,
+        BUF_SIZE = 200
+    };
+    bool _entityFlag[ENTITY_RANGE];
+    bool _restrictedEntityFlag[ENTITY_RANGE];
+
+    DynArray< const char*, 10 > _stack;
+    DynArray< char, 20 > _buffer;
+#ifdef _MSC_VER
+    DynArray< char, 20 > _accumulator;
+#endif
+};
+
+
+}	// tinyxml2
+
+
+#endif // TINYXML2_INCLUDED

+ 0 - 56
tools/compilers/vs/VSCompiler.h

@@ -1,56 +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 "Compiler.h"
-
-namespace crown
-{
-
-class VSCompiler : public Compiler
-{
-public:
-
-					VSCompiler(const char* root_path, const char* dest_path);
-					~VSCompiler();
-
-	size_t			read_header_impl(DiskFile* in_file);
-	size_t			read_resource_impl(DiskFile* in_file);
-
-	void			write_header_impl(DiskFile* out_file);
-	void			write_resource_impl(DiskFile* out_file);
-
-	void			cleanup_impl();
-
-private:
-
-	uint32_t		m_file_size;
-	char*			m_file_data;
-};
-
-} // namespace crown
-

+ 31 - 28
engine/core/math/Shape.h → tools/core/formats/MeshFormat.h

@@ -26,40 +26,43 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Plane.h"
-#include "Sphere.h"
-#include "Box.h"
-#include "Ray.h"
+#include "Types.h"
 
 namespace crown
 {
 
-enum ShapeType
-{
-	ST_PLANE				= BIT(0),
-	ST_SPHERE				= BIT(1),
-	ST_BOX					= BIT(2),
-	ST_RAY					= BIT(3),
-	ST_CONVEX				= BIT(4)
-//	ST_RECT					= BIT(4),
-//	ST_CIRCLE				= BIT(5),
-//	ST_ORIENTED_RECTANGLE	= BIT(6),
-//	ST_RAY_2D				= BIT(7),
-//	ST_SEGMENT				= BIT(8)
-};
-
-class Shape
-{
-public:
-					Shape(ShapeType type);
-					~Shape();
-
-	ShapeType		type();
+//
+// STRUCT
+// {
+//     FIELD             : SIZE                    COMMENT
+// }
+//
+// MeshHeader [1]
+// {
+//     version           : uint32_t                Version identifier
+//     mesh_count        : uint32_t                Number of meshes in the file
+//     joint_count       : uint32_t                Number of joints in the file
+//     padding           : uint32_t * 16           Reserved
+// }
+// MeshChunk [1, 2, ..., n]
+// {
+//     vertex_count      : uint32_t                Number of vertices in the mesh
+//     vertices          : float * vertex_count    Vertex data
+//
+//     tri_count         : uint32_t                Number of triangles in the mesh
+//     tris              : uint16_t * tri_count    Triangle data as indices into 'vertices'
+// }
+//
 
-private:
+// Bump the version whenever a change in the format is made.
+const uint32_t MESH_VERSION = 1;
 
-	ShapeType		m_type;
-	void*			m_shape;
+struct MeshHeader
+{
+	uint32_t	version;
+	uint32_t	mesh_count;
+	uint32_t	joint_count;
+	uint32_t	padding[16];
 };
 
 } // namespace crown

+ 8 - 18
tools/compilers/ps/PSCompiler.h → tools/core/formats/VertexFormat.h

@@ -26,31 +26,21 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Compiler.h"
-
 namespace crown
 {
 
-class PSCompiler : public Compiler
+/// Enumerates vertex formats.
+enum VertexFormat
 {
-public:
-
-					PSCompiler(const char* root_path, const char* dest_path);
-					~PSCompiler();
-
-	size_t			read_header_impl(DiskFile* in_file);
-	size_t			read_resource_impl(DiskFile* in_file);
+	VF_XY_FLOAT_32					= 0,	///< XY coordinates, 32-bit floating point each
+	VF_XYZ_FLOAT_32					= 1,	///< XYZ coordinates, 32-bit floating point each
 
-	void			write_header_impl(DiskFile* out_file);
-	void			write_resource_impl(DiskFile* out_file);
+	VF_UV_FLOAT_32					= 2,	///< UV coordinates, 32-bit floating point each
+	VF_UVT_FLOAT_32					= 3,	///< UVT coordinates, 32-bit floating point each
 
-	void			cleanup_impl();
+	VF_XYZ_NORMAL_FLOAT_32			= 4, 	///< XYZ normal coordinates, 32-bit floating point each
 
-private:
-
-	uint32_t		m_file_size;
-	char*			m_file_data;
+	VF_XYZ_UV_XYZ_NORMAL_FLOAT_32	= 5		///< XYZ coordinates, UV coordinates, XYZ normal coordinates, 32-bit floating point each
 };
 
 } // namespace crown
-