Browse Source

Add basic system for storing key/value pairs in units

Daniele Bartolini 11 years ago
parent
commit
a374504f8e
5 changed files with 370 additions and 1 deletions
  1. 102 0
      engine/lua/LuaUnit.cpp
  2. 81 1
      engine/resource/UnitResource.cpp
  3. 71 0
      engine/resource/UnitResource.h
  4. 100 0
      engine/world/Unit.cpp
  5. 16 0
      engine/world/Unit.h

+ 102 - 0
engine/lua/LuaUnit.cpp

@@ -294,6 +294,101 @@ static int unit_is_a(lua_State* L)
 	return 1;
 }
 
+//-----------------------------------------------------------------------------
+static int unit_play_sprite_animation(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Unit* unit = stack.get_unit(1);
+	const char* anim = stack.get_string(2);
+	unit->play_sprite_animation(anim, stack.get_bool(3));
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int unit_stop_sprite_animation(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Unit* unit = stack.get_unit(1);
+	unit->stop_sprite_animation();
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int unit_has_key(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Unit* unit = stack.get_unit(1);
+	stack.push_bool(unit->has_key(stack.get_string(2)));
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+static int unit_get_key(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Unit* unit = stack.get_unit(1);
+	const char* key = stack.get_string(2);
+
+	switch (unit->value_type(key))
+	{
+		case ValueType::BOOL:
+		{
+			bool val;
+			unit->get_key(key, val);
+			stack.push_bool(val);
+			return 1;
+		}
+		case ValueType::FLOAT:
+		{
+			float val;
+			unit->get_key(key, val);
+			stack.push_float(val);
+			return 1;
+		}
+		case ValueType::STRING:
+		{
+			StringId32 val;
+			unit->get_key(key, val);
+			stack.push_uint32(val);
+			return 1;
+		}
+		case ValueType::VECTOR3:
+		{
+			Vector3 val;
+			unit->get_key(key, val);
+			stack.push_vector3(val);
+			return 1;
+		}
+		default: CE_FATAL("Unknown value type"); break;
+	}
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int unit_set_key(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Unit* unit = stack.get_unit(1);
+	const char* key = stack.get_string(2);
+
+	switch (stack.value_type(3))
+	{
+		case LUA_TBOOLEAN: unit->set_key(key, stack.get_bool(3)); break;
+		case LUA_TNUMBER: unit->set_key(key, stack.get_float(3)); break;
+		case LUA_TSTRING: unit->set_key(key, stack.get_string(3)); break;
+		case LUA_TLIGHTUSERDATA: unit->set_key(key, stack.get_vector3(3)); break;
+		default: CE_FATAL("Unsupported value type"); break; // FIXME use LUA_ASSERT
+	}
+
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 void load_unit(LuaEnvironment& env)
 {
@@ -320,6 +415,13 @@ void load_unit(LuaEnvironment& env)
 	env.load_module_function("Unit", "controller",				unit_controller);
 
 	env.load_module_function("Unit", "is_a",					unit_is_a);
+
+	env.load_module_function("Unit", "play_sprite_animation",	unit_play_sprite_animation);
+	env.load_module_function("Unit", "stop_sprite_animation",	unit_stop_sprite_animation);
+
+	env.load_module_function("Unit", "has_key",					unit_has_key);
+	env.load_module_function("Unit", "get_key",					unit_get_key);
+	env.load_module_function("Unit", "set_key",					unit_set_key);
 }
 
 } // namespace crown

+ 81 - 1
engine/resource/UnitResource.cpp

@@ -246,6 +246,69 @@ void parse_renderables(JSONElement e, Array<UnitRenderable>& renderables, const
 	}
 }
 
+//-----------------------------------------------------------------------------
+void parse_keys(JSONElement e, Array<Key>& generic_keys, Array<char>& values)
+{
+	Vector<DynamicString> keys(default_allocator());
+	e.to_keys(keys);
+
+	for (uint32_t k = 0; k < vector::size(keys); k++)
+	{
+		const char* key = keys[k].c_str();
+		JSONElement value = e.key(key);
+
+		Key out_key;
+		out_key.name = string::murmur2_32(key, string::strlen(key));
+		out_key.offset = array::size(values);
+
+		if (value.is_bool()) out_key.type = ValueType::BOOL;
+		else if (value.is_number()) out_key.type = ValueType::FLOAT;
+		else if (value.is_string()) out_key.type = ValueType::STRING;
+		else if (value.is_array() && value.size() == 3) out_key.type = ValueType::VECTOR3;
+		else CE_FATAL("Value type not supported");
+
+		array::push_back(generic_keys, out_key);
+
+		switch (out_key.type)
+		{
+			case ValueType::BOOL:
+			{
+				uint32_t val = value.to_bool();
+				array::push(values, (char*) &val, sizeof(uint32_t));
+				break;
+			}
+			case ValueType::FLOAT:
+			{
+				float val = value.to_float();
+				array::push(values, (char*) &val, sizeof(float));
+				break;
+			}
+			case ValueType::STRING:
+			{
+				DynamicString val;
+				value.to_string(val);
+				StringId32 val_hash = string::murmur2_32(val.c_str(), val.length());
+				array::push(values, (char*) &val_hash, sizeof(StringId32));
+				break;
+			}
+			case ValueType::VECTOR3:
+			{
+				float val[3];
+				val[0] = value[0].to_float();
+				val[1] = value[1].to_float();
+				val[2] = value[2].to_float();
+				array::push(values, (char*) val, sizeof(float) * 3);
+				break;
+			}
+			default:
+			{
+				CE_FATAL("Oops, you should not be here");
+				return;
+			}
+		}
+	}
+}
+
 //-----------------------------------------------------------------------------
 void compile(Filesystem& fs, const char* resource_path, File* out_file)
 {
@@ -260,10 +323,12 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	ResourceId				m_physics_resource;
 	ResourceId				m_material_resource;
-	Array<GraphNode>			m_nodes(default_allocator());
+	Array<GraphNode>		m_nodes(default_allocator());
 	Array<GraphNodeDepth>	m_node_depths(default_allocator());
 	Array<UnitCamera>		m_cameras(default_allocator());
 	Array<UnitRenderable>	m_renderables(default_allocator());
+	Array<Key>				m_keys(default_allocator());
+	Array<char>				m_values(default_allocator());
 
 	// Check for nodes
 	if (root.has_key("nodes")) parse_nodes(root.key("nodes"), m_nodes, m_node_depths);
@@ -277,6 +342,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	if (root.has_key("renderables")) parse_renderables(root.key("renderables"), m_renderables, m_node_depths);
 	if (root.has_key("cameras")) parse_cameras(root.key("cameras"), m_cameras, m_node_depths);
+	if (root.has_key("keys")) parse_keys(root.key("keys"), m_keys, m_values);
 
 	// Check if the unit has a .physics resource
 	DynamicString unit_name(resource_path);
@@ -316,6 +382,8 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	h.renderables_offset         = offt; offt += sizeof(UnitRenderable) * h.num_renderables;
 	h.cameras_offset             = offt; offt += sizeof(UnitCamera) * h.num_cameras;
 	h.scene_graph_nodes_offset   = offt; offt += sizeof(UnitNode) * h.num_scene_graph_nodes;
+	h.keys_offset                = offt; offt += sizeof(uint32_t) + sizeof(Key) * array::size(m_keys);
+	h.values_offset              = offt; offt += array::size(m_values);
 
 	// Write header
 	out_file->write((char*) &h, sizeof(UnitHeader));
@@ -339,6 +407,18 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		un.pose = Matrix4x4(node.rotation, node.position);
 		out_file->write((char*) &un, sizeof(UnitNode));
 	}
+
+	// Write key/values
+	if (array::size(m_keys))
+	{
+		const uint32_t num_keys = array::size(m_keys);
+		out_file->write((char*) &num_keys, sizeof(uint32_t));
+		out_file->write((char*) array::begin(m_keys), sizeof(Key) * num_keys);
+
+		const uint32_t values_size = array::size(m_values);
+		out_file->write((char*) &values_size, sizeof(uint32_t));
+		out_file->write((char*) array::begin(m_values), array::size(m_values));
+	}
 }
 
 } // namespace unit_resource

+ 71 - 0
engine/resource/UnitResource.h

@@ -49,6 +49,8 @@ struct UnitHeader
 	uint32_t cameras_offset;
 	uint32_t num_scene_graph_nodes;
 	uint32_t scene_graph_nodes_offset;
+	uint32_t keys_offset;
+	uint32_t values_offset;
 };
 
 struct UnitRenderable
@@ -78,6 +80,24 @@ struct UnitNode
 	int32_t parent;
 };
 
+struct ValueType
+{
+	enum Enum
+	{
+		BOOL,
+		FLOAT,
+		STRING,
+		VECTOR3
+	};
+};
+
+struct Key
+{
+	StringId32 name;
+	uint32_t type;
+	uint32_t offset;
+};
+
 struct UnitResource
 {
 	//-----------------------------------------------------------------------------
@@ -168,6 +188,57 @@ struct UnitResource
 		return (UnitNode*) (((char*) this) + h->scene_graph_nodes_offset);
 	}
 
+	//-----------------------------------------------------------------------------
+	bool has_key(const char* k) const
+	{
+		UnitHeader* h = (UnitHeader*) this;
+		uint32_t num_keys = *(uint32_t*)(((char*) this) + h->keys_offset);
+		Key* begin = (Key*) (((char*) this) + h->keys_offset + sizeof(uint32_t));
+
+		for (uint32_t i = 0; i < num_keys; i++)
+		{
+			if (begin[i].name == string::murmur2_32(k, string::strlen(k)))
+			{
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	//-----------------------------------------------------------------------------
+	bool get_key(const char* k, Key& out_k) const
+	{
+		UnitHeader* h = (UnitHeader*) this;
+		uint32_t num_keys = *(uint32_t*)(((char*) this) + h->keys_offset);
+		Key* begin = (Key*) (((char*) this) + h->keys_offset + sizeof(uint32_t));
+
+		for (uint32_t i = 0; i < num_keys; i++)
+		{
+			if (begin[i].name == string::murmur2_32(k, string::strlen(k)))
+			{
+				out_k = begin[i];
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint32_t values_size() const
+	{
+		UnitHeader* h = (UnitHeader*) this;
+		return *(uint32_t*)(((char*) this) + h->values_offset);
+	}
+
+	//-----------------------------------------------------------------------------
+	const char* values() const
+	{
+		UnitHeader* h = (UnitHeader*) this;
+		return ((char*) this) + h->values_offset + sizeof(uint32_t);
+	}
+
 private:
 
 	// Disable construction

+ 100 - 0
engine/world/Unit.cpp

@@ -52,6 +52,7 @@ Unit::Unit(World& w, UnitId unit_id, const ResourceId id, const UnitResource* ur
 	, m_num_sprites(0)
 	, m_num_actors(0)
 	, m_num_materials(0)
+	, m_values(NULL)
 {
 	m_controller.component.id = INVALID_ID;
 	create_objects(pose);
@@ -93,11 +94,16 @@ void Unit::create_objects(const Matrix4x4& pose)
 	create_physics_objects();
 
 	set_default_material();
+
+	m_values = (char*) default_allocator().allocate(m_resource->values_size());
+	memcpy(m_values, m_resource->values(), m_resource->values_size());
 }
 
 //-----------------------------------------------------------------------------
 void Unit::destroy_objects()
 {
+	default_allocator().deallocate(m_values);
+
 	// Destroy cameras
 	for (uint32_t i = 0; i < m_num_cameras; i++)
 	{
@@ -560,4 +566,98 @@ bool Unit::is_a(const char* name)
 	return m_resource_id.id == string::murmur2_64(unit.c_str(), string::strlen(unit.c_str()), 0);
 }
 
+//-----------------------------------------------------------------------------
+void Unit::play_sprite_animation(const char* name, bool loop)
+{
+	// sprite((uint32_t) 0)->play_animation(name, loop);
+}
+
+//-----------------------------------------------------------------------------
+void Unit::stop_sprite_animation()
+{
+	// sprite((uint32_t) 0)->stop_animation();
+}
+
+//-----------------------------------------------------------------------------
+bool Unit::has_key(const char* k) const
+{
+	return m_resource->has_key(k);
+}
+
+//-----------------------------------------------------------------------------
+ValueType::Enum Unit::value_type(const char* k)
+{
+	Key key;
+	m_resource->get_key(k, key);
+	return (ValueType::Enum) key.type;
+}
+
+//-----------------------------------------------------------------------------
+bool Unit::get_key(const char* k, bool& v) const
+{
+	Key key;
+	bool has = m_resource->get_key(k, key);
+	v = *(uint32_t*)(m_values + key.offset);
+	return has;
+}
+
+//-----------------------------------------------------------------------------
+bool Unit::get_key(const char* k, float& v) const
+{
+	Key key;
+	bool has = m_resource->get_key(k, key);
+	v = *(float*)(m_values + key.offset);
+	return has;
+}
+
+//-----------------------------------------------------------------------------
+bool Unit::get_key(const char* k, StringId32& v) const
+{
+	Key key;
+	bool has = m_resource->get_key(k, key);
+	v = *(StringId32*)(m_values + key.offset);
+	return has;
+}
+
+//-----------------------------------------------------------------------------
+bool Unit::get_key(const char* k, Vector3& v) const
+{
+	Key key;
+	bool has = m_resource->get_key(k, key);
+	v = *(Vector3*)(m_values + key.offset);
+	return has;
+}
+
+//-----------------------------------------------------------------------------
+void Unit::set_key(const char* k, bool v)
+{
+	Key key;
+	m_resource->get_key(k, key);
+	*(uint32_t*)(m_values + key.offset) = v;
+}
+
+//-----------------------------------------------------------------------------
+void Unit::set_key(const char* k, float v)
+{
+	Key key;
+	m_resource->get_key(k, key);
+	*(float*)(m_values + key.offset) = v;
+}
+
+//-----------------------------------------------------------------------------
+void Unit::set_key(const char* k, const char* v)
+{
+	Key key;
+	m_resource->get_key(k, key);
+	*(StringId32*)(m_values + key.offset) = string::murmur2_32(v, string::strlen(v));
+}
+
+//-----------------------------------------------------------------------------
+void Unit::set_key(const char* k, const Vector3& v)
+{
+	Key key;
+	m_resource->get_key(k, key);
+	*(Vector3*)(m_values + key.offset) = v;
+}
+
 } // namespace crown

+ 16 - 0
engine/world/Unit.h

@@ -138,6 +138,20 @@ struct Unit
 
 	bool is_a(const char* name);
 
+	void play_sprite_animation(const char* name, bool loop);
+	void stop_sprite_animation();
+
+	bool has_key(const char* k) const;
+	ValueType::Enum value_type(const char* k);
+	bool get_key(const char* k, bool& v) const;
+	bool get_key(const char* k, float& v) const;
+	bool get_key(const char* k, StringId32& v) const;
+	bool get_key(const char* k, Vector3& v) const;
+	void set_key(const char* k, bool v);
+	void set_key(const char* k, float v);
+	void set_key(const char* k, const char* v);
+	void set_key(const char* k, const Vector3& v);
+
 private:
 
 	void create_objects(const Matrix4x4& pose);
@@ -171,6 +185,8 @@ public:
 	Component m_materials[CE_MAX_MATERIAL_COMPONENTS];
 
 	Component m_controller;
+
+	char* m_values;
 };
 
 } // namespace crown