浏览代码

Merge branch 'world' of https://github.com/taylor001/crown into world

Conflicts:
	engine/CMakeLists.txt
	engine/renderers/RenderWorld.cpp
	engine/renderers/RenderWorld.h
	engine/world/World.h
Daniele Bartolini 12 年之前
父节点
当前提交
7895af4483

+ 5 - 0
engine/CMakeLists.txt

@@ -88,6 +88,7 @@ set (CROWN_INCLUDES
 
 set (SRC
 	Device.cpp
+	Gui.cpp
 	ConsoleServer.cpp
 )
 
@@ -95,6 +96,7 @@ set (HEADERS
 	Config.h
 	Crown.h
 	Device.h
+	Gui.h
 	ConsoleServer.h
 )
 
@@ -303,6 +305,7 @@ set (RESOURCE_SRC
 	resource/PackageResource.cpp
 	resource/MeshResource.cpp
 	resource/LuaResource.cpp
+	resource/GuiResource.cpp
 )
 
 set (RESOURCE_HEADERS
@@ -322,6 +325,7 @@ set (RESOURCE_HEADERS
 	resource/ResourcePackage.h
 	resource/SpriteResource.h
 	resource/PhysicsResource.h
+	resource/GuiResource.h
 )
 
 if (CROWN_DEBUG OR CROWN_DEVELOPMENT)
@@ -351,6 +355,7 @@ set (LUA_SRC
 	lua/LuaDevice.cpp
 	lua/LuaEnvironment.cpp
 	lua/LuaFloatSetting.cpp
+	lua/LuaGui.cpp
 	lua/LuaIntSetting.cpp
 	lua/LuaKeyboard.cpp
 	lua/LuaMath.cpp

+ 130 - 0
engine/Gui.cpp

@@ -0,0 +1,130 @@
+/*
+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 "Gui.h"
+#include "Assert.h"
+#include "Renderer.h"
+#include "Vector3.h"
+#include "Vector2.h"
+#include "GuiResource.h"
+#include "RenderWorld.h"
+
+namespace crown
+{
+
+static const char* default_vertex =
+	"uniform mat4      	u_model;"
+	"uniform mat4      	u_model_view_projection;"
+
+	"in vec4           	a_position;"
+	"in vec4           	a_normal;"
+	"in vec2           	a_tex_coord0;"
+	"in vec4           	a_color;"
+
+	"varying out vec2	tex_coord0;"
+	"varying out vec4	color;"
+
+	"void main(void)"
+	"{"
+	"	tex_coord0 = a_tex_coord0;"
+	"   color = a_color;"
+	"	gl_Position = u_model_view_projection * a_position;"
+	"}";
+
+static const char* default_fragment =
+	"in vec2            tex_coord0;"
+	"in vec4            color;"
+
+	"uniform sampler2D  u_albedo_0;"
+
+	"void main(void)"
+	"{"
+	"	gl_FragColor = color;"
+	"}";
+
+//-----------------------------------------------------------------------------
+Gui::Gui(RenderWorld& render_world, GuiResource* gr, Renderer& r)
+	: m_render_world(render_world)
+	, m_resource(gr)
+	, m_r(r)
+{
+	Vector2 size = m_resource->gui_size();
+	// orthographic projection
+	m_projection.build_projection_ortho_rh(0, size.x, size.y, 0, -0.01f, 100.0f);
+
+	// pose
+	Vector3 pos = m_resource->gui_position();
+	m_pose.load_identity();
+	m_pose.set_translation(pos);
+
+	m_default_vs = m_r.create_shader(ShaderType::VERTEX, default_vertex);
+	m_default_fs = m_r.create_shader(ShaderType::FRAGMENT, default_fragment);
+	m_default_program = m_r.create_gpu_program(m_default_vs, m_default_fs);
+}
+
+//-----------------------------------------------------------------------------
+Gui::~Gui()
+{
+	m_r.destroy_gpu_program(m_default_program);
+	m_r.destroy_shader(m_default_fs);
+	m_r.destroy_shader(m_default_vs);
+}
+
+//-----------------------------------------------------------------------------
+void Gui::move(const Vector3& pos)
+{
+	m_pose.load_identity();
+	m_pose.set_translation(pos);
+}
+
+//-----------------------------------------------------------------------------
+void Gui::render(Renderer& r, UniformId uniform)
+{
+	Vector2 size = m_resource->gui_size();
+
+	r.set_layer_view(1, Matrix4x4::IDENTITY);
+	r.set_layer_projection(1, m_projection);
+	r.set_layer_viewport(1, m_pose.translation().x, m_pose.translation().y, size.x, size.y);
+	r.set_program(m_default_program);
+	r.set_state(STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_ALPHA_WRITE | STATE_CULL_CW | STATE_PRIMITIVE_LINES);	
+	r.set_pose(m_pose);
+
+	// draw gui's rects
+	r.set_vertex_buffer(m_resource->rect_vertex_buffer());
+	r.set_index_buffer(m_resource->rect_index_buffer());
+	r.commit(1);
+
+	r.set_program(m_default_program);
+	r.set_state(STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_ALPHA_WRITE | STATE_CULL_CW | STATE_PRIMITIVE_LINES);	
+	r.set_pose(m_pose);
+
+	// draw gui's triangles
+	r.set_vertex_buffer(m_resource->triangle_vertex_buffer());
+	r.set_index_buffer(m_resource->triangle_index_buffer());
+	r.commit(1);
+}
+
+} // namespace crown

+ 66 - 0
engine/Gui.h

@@ -0,0 +1,66 @@
+/*
+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 "Matrix4x4.h"
+#include "RendererTypes.h"
+
+namespace crown
+{
+
+typedef Id MaterialId;
+typedef Id UniformId;
+typedef Id VertexBufferId;
+typedef Id IndexBufferId;
+
+struct Renderer;
+struct RenderWorld;
+struct Vector3;
+struct GuiResource;
+
+struct Gui
+{
+						Gui(RenderWorld& render_world, GuiResource* gr, Renderer& r);
+						~Gui();
+	void				move(const Vector3& pos);
+	void				render(Renderer& r, UniformId uniform);
+
+public:
+
+	RenderWorld&		m_render_world;
+	const GuiResource*	m_resource;
+	Renderer&			m_r;
+
+	Matrix4x4			m_projection;
+	Matrix4x4			m_pose;
+
+	ShaderId			m_default_vs;
+	ShaderId			m_default_fs;
+	GPUProgramId		m_default_program;
+};
+
+} // namespace crown

+ 5 - 0
engine/compilers/BundleCompiler.cpp

@@ -48,6 +48,7 @@ namespace unit_resource { extern void compile(Filesystem&, const char*, File*);
 namespace sound_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace sprite_resource { extern void compile(Filesystem&, const char*, File*); }
 namespace material_resource { extern void compile(Filesystem&, const char*, File*); }
+namespace gui_resource { extern void compile(Filesystem&, const char*, File*); }
 
 //-----------------------------------------------------------------------------
 BundleCompiler::BundleCompiler()
@@ -161,6 +162,10 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir, con
 			{
 				material_resource::compile(root_fs, filename, out_file);
 			}
+			else if (resource_type_hash == GUI_TYPE)
+			{
+				gui_resource::compile(root_fs, filename, out_file);
+			}
 			else
 			{
 				Log::e("Oops, unknown resource type!");

+ 2 - 0
engine/lua/LuaEnvironment.cpp

@@ -83,6 +83,8 @@ CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
 	load_controller(*env);
 	load_physics_world(*env);
 
+	load_gui(*env);
+
 	return 1;
 }
 

+ 1 - 0
engine/lua/LuaEnvironment.h

@@ -114,6 +114,7 @@ void load_sprite(LuaEnvironment& env);
 void load_actor(LuaEnvironment& env);
 void load_controller(LuaEnvironment& env);
 void load_physics_world(LuaEnvironment& env);
+void load_gui(LuaEnvironment& env);
 
 CE_EXPORT int32_t luaopen_libcrown(lua_State* L);
 

+ 56 - 0
engine/lua/LuaGui.cpp

@@ -0,0 +1,56 @@
+/*
+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 "Gui.h"
+#include "LuaEnvironment.h"
+#include "LuaStack.h"
+#include "Vector3.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int gui_move(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Gui* gui = stack.get_gui(1);
+
+	const Vector3 pos = stack.get_vector3(2);
+
+	gui->move(pos);
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+void load_gui(LuaEnvironment& env)
+{
+	env.load_module_function("Gui", "move",	gui_move);
+}
+
+
+} // namespace crown

+ 31 - 0
engine/lua/LuaStack.h

@@ -46,7 +46,10 @@ class PhysicsWorld;
 struct Actor;
 struct Controller;
 class ResourcePackage;
+struct Gui;
+
 typedef Id SoundInstanceId;
+typedef Id GuiId;
 
 void clear_lua_temporaries();
 
@@ -308,6 +311,34 @@ public:
 		return id;
 	}
 
+	//-----------------------------------------------------------------------------
+	void push_gui_id(GuiId id)
+	{
+		uintptr_t enc = id.encode();
+		lua_pushlightuserdata(m_state, (void*)enc);
+	}
+
+	//-----------------------------------------------------------------------------
+	GuiId get_gui_id(int32_t index)
+	{
+		uint32_t enc = (uintptr_t) lua_touserdata(m_state, index);
+		GuiId id;
+		id.decode(enc);
+		return id;
+	}
+
+	//-----------------------------------------------------------------------------
+	void push_gui(Gui* gui)
+	{
+		lua_pushlightuserdata(m_state, gui);
+	}
+
+	//-----------------------------------------------------------------------------
+	Gui* get_gui(int32_t index)
+	{
+		return (Gui*) lua_touserdata(m_state, index);
+	}
+
 	bool is_vector2(int32_t index);
 	bool is_vector3(int32_t index);
 	bool is_matrix4x4(int32_t index);

+ 43 - 0
engine/lua/LuaWorld.cpp

@@ -172,6 +172,45 @@ CE_EXPORT int world_set_sound_volume(lua_State* L)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+CE_EXPORT int world_create_window_gui(lua_State* L)
+{
+	LuaStack stack(L);
+
+	World* world = stack.get_world(1);
+
+	GuiId gui = world->create_window_gui(stack.get_string(2));
+	stack.push_gui_id(gui);
+
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int world_destroy_gui(lua_State* L)
+{
+	LuaStack stack(L);
+
+	World* world = stack.get_world(1);
+
+	world->destroy_gui(stack.get_gui_id(2));
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int world_lookup_gui(lua_State* L)
+{
+	LuaStack stack(L);
+
+	World* world = stack.get_world(1);
+
+	Gui* gui = world->lookup_gui(stack.get_gui_id(2));
+
+	stack.push_gui(gui);
+
+	return 1;	
+}
+
 //-----------------------------------------------------------------------------
 CE_EXPORT int world_physics_world(lua_State* L)
 {
@@ -198,6 +237,10 @@ void load_world(LuaEnvironment& env)
 	env.load_module_function("World", "set_sound_range", 	world_set_sound_range);
 	env.load_module_function("World", "set_sound_volume", 	world_set_sound_volume);
 
+	env.load_module_function("World", "create_window_gui",	world_create_window_gui);
+	env.load_module_function("World", "destroy_gui",		world_destroy_gui);
+	env.load_module_function("World", "lookup_gui",			world_lookup_gui);
+
 	env.load_module_function("World", "physics_world",		world_physics_world);
 }
 

+ 36 - 2
engine/renderers/RenderWorld.cpp

@@ -36,6 +36,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Sprite.h"
 #include "Material.h"
 #include "Config.h"
+#include "Gui.h"
+#include "GuiResource.h"
 
 namespace crown
 {
@@ -91,6 +93,7 @@ RenderWorld::RenderWorld()
 	: m_mesh_pool(default_allocator(), MAX_MESHES, sizeof(Mesh), CE_ALIGNOF(Mesh))
 	, m_sprite_pool(default_allocator(), MAX_SPRITES, sizeof(Sprite), CE_ALIGNOF(Sprite))
 	, m_material_pool(default_allocator(), MAX_MATERIALS, sizeof(Material), CE_ALIGNOF(Material))
+	, m_gui_pool(default_allocator(), MAX_GUIS, sizeof(Gui), CE_ALIGNOF(Gui))
 {
 	Renderer* r = device()->renderer();
 
@@ -187,6 +190,31 @@ Material* RenderWorld::lookup_material(MaterialId id)
 	return m_materials.lookup(id);
 }
 
+//-----------------------------------------------------------------------------
+GuiId RenderWorld::create_gui(GuiResource* gr)
+{
+	Renderer* r = device()->renderer();
+	Gui* gui = CE_NEW(m_gui_pool, Gui)(*this, gr, *r);
+	return m_guis.create(gui);
+}
+
+//-----------------------------------------------------------------------------
+void RenderWorld::destroy_gui(GuiId id)
+{
+	CE_ASSERT(m_guis.has(id), "Gui does not exist");
+
+	CE_DELETE(m_gui_pool, m_guis.lookup(id));
+	m_guis.destroy(id);
+}
+
+//-----------------------------------------------------------------------------
+Gui* RenderWorld::lookup_gui(GuiId id)
+{
+	CE_ASSERT(m_guis.has(id), "Gui does not exist");
+	
+	return m_guis.lookup(id);
+}
+
 //-----------------------------------------------------------------------------
 void RenderWorld::update(const Matrix4x4& view, const Matrix4x4& projection, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
 {
@@ -212,8 +240,8 @@ void RenderWorld::update(const Matrix4x4& view, const Matrix4x4& projection, uin
 		r->set_vertex_buffer(mesh->m_vbuffer);
 		r->set_index_buffer(mesh->m_ibuffer);
 		r->set_program(default_program);
-		/*r->set_texture(0, u_albedo_0, grass_texture, TEXTURE_FILTER_LINEAR | TEXTURE_WRAP_CLAMP_EDGE);
-		r->set_uniform(u_brightness, UNIFORM_FLOAT_1, &brightness, 1);*/
+		// r->set_texture(0, u_albedo_0, grass_texture, TEXTURE_FILTER_LINEAR | TEXTURE_WRAP_CLAMP_EDGE);
+		// r->set_uniform(u_brightness, UNIFORM_FLOAT_1, &brightness, 1);
 
 		r->set_pose(mesh->world_pose());
 		r->commit(0);
@@ -225,6 +253,12 @@ void RenderWorld::update(const Matrix4x4& view, const Matrix4x4& projection, uin
 		r->set_program(texture_program);
 		m_sprite[s]->render(*r, u_albedo_0);
 	}
+
+	// Draw all guis
+	for (uint32_t g = 0; g < m_guis.size(); g++)
+	{
+		m_guis[g]->render(*r, u_albedo_0);
+	}
 }
 
 } // namespace crown

+ 11 - 0
engine/renderers/RenderWorld.h

@@ -36,6 +36,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #define MAX_MESHES 100
 #define MAX_SPRITES 256
 #define MAX_MATERIALS 256
+#define MAX_GUIS 8
 
 namespace crown
 {
@@ -47,6 +48,10 @@ struct MeshResource;
 struct SceneGraph;
 struct Sprite;
 struct SpriteResource;
+struct Gui;
+struct Vector2;
+struct Vector3;
+struct GuiResource;
 
 class RenderWorld
 {
@@ -67,6 +72,10 @@ public:
 	void		destroy_material(MaterialId id);
 	Material*	lookup_material(MaterialId id);
 
+	GuiId		create_gui(GuiResource* gr);
+	void		destroy_gui(GuiId id);
+	Gui*		lookup_gui(GuiId id);
+
 	void		update(const Matrix4x4& view, const Matrix4x4& projection, uint16_t x, uint16_t y, uint16_t width, uint16_t height);
 
 private:
@@ -74,10 +83,12 @@ private:
 	PoolAllocator						m_mesh_pool;
 	PoolAllocator						m_sprite_pool;
 	PoolAllocator						m_material_pool;
+	PoolAllocator						m_gui_pool;
 
 	IdArray<MAX_MESHES, Mesh*>			m_mesh;
 	IdArray<MAX_SPRITES, Sprite*>		m_sprite;
 	IdArray<MAX_MATERIALS, Material*>	m_materials;
+	IdArray<MAX_GUIS, Gui*>				m_guis;
 };
 
 } // namespace crown

+ 1 - 0
engine/renderers/RenderWorldTypes.h

@@ -32,5 +32,6 @@ namespace crown
 typedef Id MeshId;
 typedef Id SpriteId;
 typedef Id MaterialId;
+typedef Id GuiId;
 
 } // namespace crown

+ 227 - 0
engine/resource/GuiResource.cpp

@@ -0,0 +1,227 @@
+/*
+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 <cstring>
+#include <inttypes.h>
+
+#include "Allocator.h"
+#include "Filesystem.h"
+#include "Hash.h"
+#include "JSONParser.h"
+#include "GuiResource.h"
+#include "StringUtils.h"
+#include "Log.h"
+
+
+namespace crown
+{
+namespace gui_resource
+{
+
+//-----------------------------------------------------------------------------
+void parse_rect(JSONElement rect, List<float>& positions, List<float>& sizes, List<float>& colors)
+{
+	JSONElement position 	= rect.key("position");
+	JSONElement size 		= rect.key("size");
+	JSONElement color 		= rect.key("color");
+
+	position.array_value(positions);
+	size.array_value(sizes);
+	color.array_value(colors);
+}
+
+//-----------------------------------------------------------------------------
+void parse_triangle(JSONElement rect, List<float>& points, List<float>& colors)
+{
+	JSONElement point	= rect.key("points");
+	JSONElement color 	= rect.key("color");
+
+	point.array_value(points);
+	color.array_value(colors);
+}
+
+//-----------------------------------------------------------------------------
+void compile(Filesystem& fs, const char* resource_path, File* out_file)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+	char* buf = (char*)default_allocator().allocate(file->size());
+	file->read(buf, file->size());
+
+	JSONParser json(buf);
+	JSONElement root = json.root();
+
+	List<float>			m_gui_position(default_allocator());
+	List<float>			m_gui_size(default_allocator());
+
+	root.key("position").array_value(m_gui_position);
+	root.key("size").array_value(m_gui_size);
+
+	List<float> 		m_rect_positions(default_allocator());
+	List<float> 		m_rect_sizes(default_allocator());
+	List<float> 		m_rect_colors(default_allocator());
+
+	// Parse all rects
+	JSONElement rects = root.key("rects");
+	uint32_t num_rects = rects.size();
+
+	for (uint32_t i = 0; i < num_rects; i++)
+	{
+		parse_rect(rects[i], m_rect_positions, m_rect_sizes, m_rect_colors);
+	}
+
+	// Compile all rects
+	List<float>	m_rect_vertices(default_allocator());
+	List<uint16_t> m_rect_indices(default_allocator());
+
+	uint32_t rprx = 0;
+	uint32_t rclx = 0;
+	uint32_t ridx = 0;
+	for (uint32_t i = 0; i < num_rects; i++)
+	{
+		// first vertex
+		m_rect_vertices.push_back(m_rect_positions[rprx]);
+		m_rect_vertices.push_back(m_rect_positions[rprx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+2]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+3]);
+
+		// second vertex
+		m_rect_vertices.push_back(m_rect_positions[rprx] + m_rect_sizes[rprx]);
+		m_rect_vertices.push_back(m_rect_positions[rprx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+2]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+3]);
+
+		// third vertex
+		m_rect_vertices.push_back(m_rect_positions[rprx] + m_rect_sizes[rprx]);
+		m_rect_vertices.push_back(m_rect_positions[rprx+1] - m_rect_sizes[rprx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+2]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+3]);
+
+		// fourth vertex
+		m_rect_vertices.push_back(m_rect_positions[rprx]);
+		m_rect_vertices.push_back(m_rect_positions[rprx+1] - m_rect_sizes[rprx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+1]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+2]);
+		m_rect_vertices.push_back(m_rect_colors[rclx+3]);
+
+		// indices
+		m_rect_indices.push_back(ridx); m_rect_indices.push_back(ridx+1);
+		m_rect_indices.push_back(ridx+1); m_rect_indices.push_back(ridx+2);
+		m_rect_indices.push_back(ridx+2); m_rect_indices.push_back(ridx+3);
+		m_rect_indices.push_back(ridx+3); m_rect_indices.push_back(ridx);
+
+		rprx += 2;
+		rclx += 4;
+		ridx += 4;
+	}
+
+	// Parse all triangles
+	List<float> m_triangle_points(default_allocator());
+	List<float> m_triangle_colors(default_allocator());
+
+	JSONElement triangles = root.key("triangles");
+	uint32_t num_triangles = triangles.size();
+	for (uint32_t i = 0; i < num_triangles; i++)
+	{
+		parse_triangle(triangles[i], m_triangle_points, m_triangle_colors);
+	}
+
+	// Compile all triangles
+	List<float>	m_triangle_vertices(default_allocator());
+	List<uint16_t> m_triangle_indices(default_allocator());
+
+	uint32_t tpnx = 0;
+	uint32_t tclx = 0;
+	uint32_t tidx = 0;
+	for (uint32_t i = 0; i < num_triangles; i++)
+	{
+		// first vertex
+		m_triangle_vertices.push_back(m_triangle_points[tpnx]);
+		m_triangle_vertices.push_back(m_triangle_points[tpnx+1]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+1]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+2]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+3]);
+
+		// second vertex
+		m_triangle_vertices.push_back(m_triangle_points[tpnx+2]);
+		m_triangle_vertices.push_back(m_triangle_points[tpnx+3]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+1]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+2]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+3]);
+
+		// third vertex
+		m_triangle_vertices.push_back(m_triangle_points[tpnx+4]);
+		m_triangle_vertices.push_back(m_triangle_points[tpnx+5]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+1]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+2]);
+		m_triangle_vertices.push_back(m_triangle_colors[tclx+3]);
+
+		m_triangle_indices.push_back(tidx); m_triangle_indices.push_back(tidx+1);
+		m_triangle_indices.push_back(tidx+1); m_triangle_indices.push_back(tidx+2);
+		m_triangle_indices.push_back(tidx+2); m_triangle_indices.push_back(tidx);
+
+		tpnx += 6;
+		tclx += 4;
+		tidx += 3;
+	}
+
+	fs.close(file);
+	default_allocator().deallocate(buf);
+
+	// Write compiled resource to out_file
+	GuiHeader h;
+	h.position[0] = m_gui_position[0];
+	h.position[1] = m_gui_position[1];
+	h.size[0] = m_gui_size[0];
+	h.size[1] = m_gui_size[1];
+
+	h.num_rects = num_rects;
+	h.num_triangles = num_triangles;
+
+	h.rect_vertices_off = sizeof(GuiHeader);
+	h.rect_indices_off = h.rect_vertices_off + sizeof(float) * m_rect_vertices.size();
+	h.triangle_vertices_off = h.rect_indices_off + sizeof(uint16_t) * m_rect_indices.size();
+	h.triangle_indices_off = h.triangle_vertices_off + sizeof(float) * m_triangle_vertices.size();
+
+	out_file->write((char*) &h, sizeof(GuiHeader));
+	out_file->write((char*) m_rect_vertices.begin(), sizeof(float) * m_rect_vertices.size());
+	out_file->write((char*) m_rect_indices.begin(), sizeof(uint16_t) * m_rect_indices.size());
+	out_file->write((char*) m_triangle_vertices.begin(), sizeof(float) * m_triangle_vertices.size());
+	out_file->write((char*) m_triangle_indices.begin(), sizeof(uint16_t) * m_triangle_indices.size());
+}
+
+} // namespace gui_resource
+} // namespace crown

+ 179 - 0
engine/resource/GuiResource.h

@@ -0,0 +1,179 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <cstring>
+#include <inttypes.h>
+
+#include "Assert.h"
+#include "Types.h"
+#include "Allocator.h"
+#include "File.h"
+#include "OS.h"
+#include "StringUtils.h"
+#include "List.h"
+#include "Bundle.h"
+#include "Device.h"
+#include "Renderer.h"
+#include "Vector2.h"
+#include "Vector3.h"
+
+namespace crown
+{
+
+const uint32_t GUI_RESOURCE_VERSION = 1;
+
+//-----------------------------------------------------------------------------
+struct GuiHeader
+{
+	uint32_t position[2];
+	uint32_t size[2];
+
+	VertexBufferId rect_vb;
+	IndexBufferId rect_ib;
+	VertexBufferId triangle_vb;
+	IndexBufferId triangle_ib;
+
+	uint32_t num_rects;
+	uint32_t num_triangles;
+
+	uint32_t rect_vertices_off;
+	uint32_t rect_indices_off;
+	uint32_t triangle_vertices_off;
+	uint32_t triangle_indices_off;
+};
+
+//-----------------------------------------------------------------------------
+struct GuiResource
+{
+	//-----------------------------------------------------------------------------
+	static void* load(Allocator& allocator, Bundle& bundle, ResourceId id)
+	{
+		File* file = bundle.open(id);
+		const size_t file_size = file->size();
+
+		void* res = allocator.allocate(file_size);
+		file->read(res, file_size);
+
+		bundle.close(file);
+
+		return res;
+	}
+
+	//-----------------------------------------------------------------------------
+	static void online(void* resource)
+	{
+		GuiHeader* h = (GuiHeader*) resource;
+
+		const float* rect_vertices = (float*) (((char*) resource) + h->rect_vertices_off);
+		const uint16_t* rect_indices = (uint16_t*) (((char*) resource) + h->rect_indices_off);
+
+		h->rect_vb = device()->renderer()->create_vertex_buffer(h->num_rects * 4, VertexFormat::P2_C4, rect_vertices);
+		h->rect_ib = device()->renderer()->create_index_buffer(h->num_rects * 8, rect_indices);
+
+		const float* triangle_vertices = (float*) (((char*) resource) + h->triangle_vertices_off);
+		const uint16_t* triangle_indices = (uint16_t*) (((char*) resource) + h->triangle_indices_off);
+
+		h->triangle_vb = device()->renderer()->create_vertex_buffer(h->num_triangles * 3, VertexFormat::P2_C4, triangle_vertices);
+		h->triangle_ib = device()->renderer()->create_index_buffer(h->num_triangles * 6, triangle_indices);
+	}
+
+	//-----------------------------------------------------------------------------
+	static void unload(Allocator& allocator, void* resource)
+	{
+		CE_ASSERT_NOT_NULL(resource);
+		allocator.deallocate(resource);
+	}
+
+	//-----------------------------------------------------------------------------
+	static void offline(void* resource)
+	{
+		CE_ASSERT_NOT_NULL(resource);
+
+		GuiResource* gr = (GuiResource*) resource;
+		GuiHeader* h = (GuiHeader*) gr;
+
+		device()->renderer()->destroy_vertex_buffer(h->triangle_vb);
+		device()->renderer()->destroy_index_buffer(h->triangle_ib);
+		device()->renderer()->destroy_vertex_buffer(h->rect_vb);
+		device()->renderer()->destroy_index_buffer(h->rect_ib);
+	}
+
+	//-----------------------------------------------------------------------------
+	Vector3 gui_position() const
+	{
+		Vector3 pos;
+		
+		pos.x = ((GuiHeader*)this)->position[0];
+		pos.y = ((GuiHeader*)this)->position[1];
+		pos.z = 0.0f;
+
+		return pos;
+	}
+
+	//-----------------------------------------------------------------------------
+	Vector2 gui_size() const
+	{
+		Vector2 size;
+
+		size.x = ((GuiHeader*)this)->size[0];
+		size.y = ((GuiHeader*)this)->size[1];
+
+		return size;
+	}
+
+	//-----------------------------------------------------------------------------
+	VertexBufferId rect_vertex_buffer() const
+	{
+		return ((GuiHeader*)this)->rect_vb;
+	}
+
+	//-----------------------------------------------------------------------------
+	IndexBufferId rect_index_buffer() const
+	{
+		return ((GuiHeader*)this)->rect_ib;
+	}
+
+	//-----------------------------------------------------------------------------
+	VertexBufferId triangle_vertex_buffer() const
+	{
+		return ((GuiHeader*)this)->triangle_vb;
+	}
+
+	//-----------------------------------------------------------------------------
+	IndexBufferId triangle_index_buffer() const
+	{
+		return ((GuiHeader*)this)->triangle_ib;
+	}
+
+
+private:
+	
+	GuiResource();
+};
+
+} // namespace crown

+ 32 - 0
engine/resource/PackageResource.cpp

@@ -58,6 +58,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	List<ResourceId> m_sprite(default_allocator());
 	List<ResourceId> m_physics(default_allocator());
 	List<ResourceId> m_materials(default_allocator());
+	List<ResourceId> m_guis(default_allocator());
 
 	// Check for resource types
 	if (root.has_key("texture"))
@@ -244,6 +245,31 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		}
 	}
 
+	// Check for materials
+	if (root.has_key("gui"))
+	{
+		JSONElement guis_array = root.key("gui");
+		uint32_t guis_array_size = guis_array.size();
+
+		for (uint32_t i = 0; i < guis_array_size; i++)
+		{
+			TempAllocator256 alloc;
+			DynamicString guis_name(alloc);
+			guis_name += guis_array[i].string_value();
+			guis_name += ".gui";
+
+			if (!fs.is_file(guis_name.c_str()))
+			{
+				Log::e("gui '%s' does not exist.", guis_name.c_str());
+				return;
+			}
+
+			ResourceId id;
+			id.id = hash::murmur2_64(guis_name.c_str(), string::strlen(guis_name.c_str()), 0);
+			m_guis.push_back(id);
+		}
+	}	
+
 	PackageHeader header;
 	header.num_textures = m_texture.size();
 	header.num_scripts = m_script.size();
@@ -253,6 +279,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	header.num_sprites = m_sprite.size();
 	header.num_physics = m_physics.size();
 	header.num_materials = m_materials.size();
+	header.num_guis = m_guis.size();
 
 	header.textures_offset = sizeof(PackageHeader);
 	header.scripts_offset  = header.textures_offset + sizeof(ResourceId) * header.num_textures;
@@ -262,6 +289,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	header.sprites_offset = header.units_offset + sizeof(ResourceId) * header.num_units;
 	header.physics_offset = header.sprites_offset + sizeof(ResourceId) * header.num_sprites;
 	header.materials_offset = header.physics_offset + sizeof(ResourceId) * header.num_physics;
+	header.guis_offset = header.materials_offset + sizeof(ResourceId) * header.num_materials;
 
 	out_file->write((char*) &header, sizeof(PackageHeader));
 
@@ -297,6 +325,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	{
 		out_file->write((char*) m_materials.begin(), sizeof(ResourceId) * header.num_materials);
 	}
+	if (m_guis.size() > 0)
+	{
+		out_file->write((char*) m_guis.begin(), sizeof(ResourceId) * header.num_guis);
+	}
 }
 
 } // namespace package_resource

+ 18 - 0
engine/resource/PackageResource.h

@@ -54,6 +54,8 @@ struct PackageHeader
 	uint32_t physics_offset;
 	uint32_t num_materials;
 	uint32_t materials_offset;
+	uint32_t num_guis;
+	uint32_t guis_offset;
 };
 
 struct PackageResource
@@ -137,6 +139,12 @@ struct PackageResource
 		return ((PackageHeader*) this)->num_materials;
 	}
 
+	//-----------------------------------------------------------------------------
+	uint32_t num_guis() const
+	{
+		return ((PackageHeader*) this)->num_guis;
+	}
+
 	//-----------------------------------------------------------------------------
 	ResourceId get_texture_id(uint32_t i) const
 	{
@@ -209,6 +217,16 @@ struct PackageResource
 		return begin[i];
 	}
 
+	//-----------------------------------------------------------------------------
+	ResourceId get_gui_id(uint32_t i) const
+	{
+		CE_ASSERT(i < num_guis(), "Index out of bounds");
+
+		ResourceId* begin = (ResourceId*) ((char*) this + ((PackageHeader*) this)->guis_offset);
+		return begin[i];
+	}
+
+
 private:
 
 	// Disable construction

+ 2 - 0
engine/resource/Resource.h

@@ -45,6 +45,7 @@ const char* const CONFIG_EXTENSION			= "config";
 const char* const PACKAGE_EXTENSION			= "package";
 const char* const UNIT_EXTENSION			= "unit";
 const char* const PHYSICS_EXTENSION			= "physics";
+const char* const GUI_EXTENSION				= "gui";
 
 const uint32_t TEXTURE_TYPE					= 0x0DEED4F7;
 const uint32_t MESH_TYPE					= 0x742FBC9A;
@@ -57,6 +58,7 @@ const uint32_t CONFIG_TYPE					= 0x17DEA5E1;
 const uint32_t PACKAGE_TYPE					= 0xC0A2212C;
 const uint32_t UNIT_TYPE					= 0x516224CF;
 const uint32_t PHYSICS_TYPE					= 0xFA32C012;
+const uint32_t GUI_TYPE						= 0x2C56149A;
 
 /// ResourceId uniquely identifies a resource by its name and type.
 /// In order to speed up the lookup by the manager, it also keeps

+ 10 - 0
engine/resource/ResourcePackage.h

@@ -92,11 +92,21 @@ public:
 		{
 			m_resource_manager->load(MATERIAL_TYPE, m_package->get_material_id(i));
 		}
+
+		for (uint32_t i = 0; i < m_package->num_guis(); i++)
+		{
+			m_resource_manager->load(GUI_TYPE, m_package->get_gui_id(i));
+		}
 	}
 
 	/// Unloads all the resources in the package.
 	void unload()
 	{
+		for (uint32_t i = 0; i < m_package->num_guis(); i++)
+		{
+			m_resource_manager->unload(m_package->get_gui_id(i));
+		}
+
 		for (uint32_t i = 0; i < m_package->num_materials(); i++)
 		{
 			m_resource_manager->unload(m_package->get_material_id(i));

+ 3 - 1
engine/resource/ResourceRegistry.cpp

@@ -34,6 +34,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "UnitResource.h"
 #include "PhysicsResource.h"
 #include "MaterialResource.h"
+#include "GuiResource.h"
 
 namespace crown
 {
@@ -48,7 +49,8 @@ static const ResourceCallback RESOURCE_CALLBACK_REGISTRY[] =
 	{ SPRITE_TYPE, SpriteResource::load, SpriteResource::unload, SpriteResource::online, SpriteResource::offline},
 	{ PACKAGE_TYPE, PackageResource::load, PackageResource::unload, PackageResource::online, PackageResource::offline },
 	{ PHYSICS_TYPE, PhysicsResource::load, PhysicsResource::unload, PhysicsResource::online, PhysicsResource::offline },
-	{ MATERIAL_TYPE, MaterialResource::load, MaterialResource::unload, MaterialResource::online, MaterialResource::offline },	
+	{ MATERIAL_TYPE, MaterialResource::load, MaterialResource::unload, MaterialResource::online, MaterialResource::offline },
+	{ GUI_TYPE, GuiResource::load, GuiResource::unload, GuiResource::online, GuiResource::offline },	
 	{ 0, NULL, NULL, NULL, NULL }
 };
 

+ 19 - 0
engine/world/World.cpp

@@ -281,6 +281,25 @@ void World::set_sound_volume(SoundId id, const float vol)
 	sound.volume = vol;
 }
 
+//-----------------------------------------------------------------------------
+GuiId World::create_window_gui(const char* name)
+{
+	GuiResource* gr = (GuiResource*)device()->resource_manager()->lookup(GUI_EXTENSION, name);
+	return m_render_world.create_gui(gr);
+}
+
+//-----------------------------------------------------------------------------
+void World::destroy_gui(GuiId id)
+{
+	m_render_world.destroy_gui(id);
+}
+
+//-----------------------------------------------------------------------------
+Gui* World::lookup_gui(GuiId id)
+{
+	return m_render_world.lookup_gui(id);
+}
+
 //-----------------------------------------------------------------------------
 SceneGraphManager* World::scene_graph_manager()
 {

+ 4 - 0
engine/world/World.h

@@ -114,6 +114,10 @@ public:
 	void								set_sound_range(SoundId sound, const float range);
 	void								set_sound_volume(SoundId sound, const float vol);
 
+	GuiId								create_window_gui(const char* name);
+	void								destroy_gui(GuiId id);
+	Gui*								lookup_gui(GuiId id);
+
 	SceneGraphManager*					scene_graph_manager();
 	RenderWorld*						render_world();
 	PhysicsWorld*						physics_world();