Explorar o código

tools: refactor database.vala to be more easily portable

Daniele Bartolini %!s(int64=8) %!d(string=hai) anos
pai
achega
38c2b0f7a6

+ 437 - 224
tools/core/database.vala

@@ -9,58 +9,22 @@ namespace Crown
 {
 	public class Database
 	{
-		private enum ActionType
+		private enum Action
 		{
 			CREATE,
 			DESTROY,
-			SET_PROPERTY,
+			SET_PROPERTY_NULL,
+			SET_PROPERTY_BOOL,
+			SET_PROPERTY_DOUBLE,
+			SET_PROPERTY_STRING,
+			SET_PROPERTY_GUID,
+			SET_PROPERTY_VECTOR3,
+			SET_PROPERTY_QUATERNION,
 			ADD_TO_SET,
 			REMOVE_FROM_SET,
 			RESTORE_POINT
 		}
 
-		private enum ValueType
-		{
-			NULL,
-			BOOL,
-			DOUBLE,
-			STRING,
-			GUID,
-			VECTOR3,
-			QUATERNION
-		}
-
-		private struct CreateAction
-		{
-			public Guid id;
-		}
-
-		private struct DestroyAction
-		{
-			public Guid id;
-		}
-
-		private struct SetPropertyAction
-		{
-			public Guid id;
-			public string key;
-			public Value? val;
-		}
-
-		private struct AddToSetAction
-		{
-			public Guid id;
-			public string key;
-			public Guid item_id;
-		}
-
-		private struct RemoveFromSetAction
-		{
-			public Guid id;
-			public string key;
-			public Guid item_id;
-		}
-
 		private struct RestorePoint
 		{
 			public int id;
@@ -138,21 +102,16 @@ namespace Crown
 				write_data(&a, sizeof(Quaternion));
 			}
 
-			public void write_action_type(ActionType t)
-			{
-				write_uint32((uint32)t);
-			}
-
-			public void write_value_type(ValueType t)
+			public void write_action(Action t)
 			{
 				write_uint32((uint32)t);
 			}
 
-			public ActionType read_action_type()
+			public Action read_action()
 			{
 				_read -= (uint32)sizeof(uint32);
 				uint32 a = *(uint32*)(&_data[_read]);
-				return (ActionType)a;
+				return (Action)a;
 			}
 
 			public bool read_bool()
@@ -216,165 +175,110 @@ namespace Crown
 				return (string)str;
 			}
 
-			public ValueType read_value_type()
-			{
-				_read -= (uint32)sizeof(uint32);
-				uint32 a = *(uint32*)(&_data[_read]);
-				return (ValueType)a;
-			}
-
 			public void write_create_action(Guid id)
 			{
 				write_guid(id);
-				write_action_type(ActionType.CREATE);
+				write_action(Action.CREATE);
 			}
 
 			public void write_destroy_action(Guid id)
 			{
 				write_guid(id);
-				write_action_type(ActionType.DESTROY);
+				write_action(Action.DESTROY);
 			}
 
-			public void write_set_property_action(Guid id, string key, Value? val)
+			public void write_set_property_null_action(Guid id, string key)
 			{
-				if (val == null)
-				{
-					// Push nothing
-					write_value_type(ValueType.NULL);
-				}
-				else if (val.holds(typeof(bool)))
-				{
-					write_bool((bool)val);
-					write_value_type(ValueType.BOOL);
-				}
-				else if (val.holds(typeof(double)))
-				{
-					write_double((double)val);
-					write_value_type(ValueType.DOUBLE);
-				}
-				else if (val.holds(typeof(string)))
-				{
-					write_string((string)val);
-					write_value_type(ValueType.STRING);
-				}
-				else if (val.holds(typeof(Guid)))
-				{
-					write_guid((Guid)val);
-					write_value_type(ValueType.GUID);
-				}
-				else if (val.holds(typeof(Vector3)))
-				{
-					write_vector3((Vector3)val);
-					write_value_type(ValueType.VECTOR3);
-				}
-				else if (val.holds(typeof(Quaternion)))
-				{
-					write_quaternion((Quaternion)val);
-					write_value_type(ValueType.QUATERNION);
-				}
-
+				// No value to push
 				write_string(key);
 				write_guid(id);
-				write_action_type(ActionType.SET_PROPERTY);
+				write_action(Action.SET_PROPERTY_NULL);
 			}
 
-			public void write_add_to_set_action(Guid id, string key, Guid item_id)
+			public void write_set_property_bool_action(Guid id, string key, bool val)
 			{
-				write_guid(item_id);
+				write_bool(val);
 				write_string(key);
 				write_guid(id);
-				write_action_type(ActionType.ADD_TO_SET);
+				write_action(Action.SET_PROPERTY_BOOL);
 			}
 
-			public void write_remove_from_set_action(Guid id, string key, Guid item_id)
+			public void write_set_property_double_action(Guid id, string key, double val)
 			{
-				write_guid(item_id);
+				write_double(val);
 				write_string(key);
 				write_guid(id);
-				write_action_type(ActionType.REMOVE_FROM_SET);
+				write_action(Action.SET_PROPERTY_DOUBLE);
 			}
 
-			public void write_restore_point(int id, uint32 size, Guid[] data)
+			public void write_set_property_string_action(Guid id, string key, string val)
 			{
-				uint32 num_guids = data.length;
-				for (uint32 i = 0; i < num_guids; ++i)
-					write_guid(data[i]);
-				write_uint32(num_guids);
-				write_uint32(size);
-				write_int(id);
-				write_action_type(ActionType.RESTORE_POINT);
+				write_string(val);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.SET_PROPERTY_STRING);
 			}
 
-			public uint32 peek_type()
+			public void write_set_property_guid_action(Guid id, string key, Guid val)
 			{
-				return *(uint32*)(&_data[_read - (uint32)sizeof(uint32)]);
+				write_guid(val);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.SET_PROPERTY_GUID);
 			}
 
-			public CreateAction read_create_action()
+			public void write_set_property_vector3_action(Guid id, string key, Vector3 val)
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.CREATE);
-				return { read_guid() };
+				write_vector3(val);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.SET_PROPERTY_VECTOR3);
 			}
 
-			public DestroyAction read_destroy_action()
+			public void write_set_property_quaternion_action(Guid id, string key, Quaternion val)
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.DESTROY);
-				return { read_guid() };
+				write_quaternion(val);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.SET_PROPERTY_QUATERNION);
 			}
 
-			public SetPropertyAction read_set_property_action()
+			public void write_add_to_set_action(Guid id, string key, Guid item_id)
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.SET_PROPERTY);
-
-				Guid id = read_guid();
-				string key = read_string();
-				ValueType type = read_value_type();
-
-				Value? val = null;
-
-				if (type == ValueType.NULL)
-				{
-					// Pop nothing
-				}
-				else if (type == ValueType.BOOL)
-					val = read_bool();
-				else if (type == ValueType.DOUBLE)
-					val = read_double();
-				else if (type == ValueType.STRING)
-					val = read_string();
-				else if (type == ValueType.GUID)
-					val = read_guid();
-				else if (type == ValueType.VECTOR3)
-					val = read_vector3();
-				else if (type == ValueType.QUATERNION)
-					val = read_quaternion();
-				else
-					assert(false);
+				write_guid(item_id);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.ADD_TO_SET);
+			}
 
-				return { id, key, val };
+			public void write_remove_from_set_action(Guid id, string key, Guid item_id)
+			{
+				write_guid(item_id);
+				write_string(key);
+				write_guid(id);
+				write_action(Action.REMOVE_FROM_SET);
 			}
 
-			public AddToSetAction read_add_to_set_action()
+			public void write_restore_point(int id, uint32 size, Guid[] data)
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.ADD_TO_SET);
-				return { read_guid(), read_string(), read_guid() };
+				uint32 num_guids = data.length;
+				for (uint32 i = 0; i < num_guids; ++i)
+					write_guid(data[i]);
+				write_uint32(num_guids);
+				write_uint32(size);
+				write_int(id);
+				write_action(Action.RESTORE_POINT);
 			}
 
-			public RemoveFromSetAction read_remove_from_set_action()
+			public uint32 peek_type()
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.REMOVE_FROM_SET);
-				return { read_guid(), read_string(), read_guid() };
+				return *(uint32*)(&_data[_read - (uint32)sizeof(uint32)]);
 			}
 
 			public RestorePoint read_restore_point()
 			{
-				ActionType t = read_action_type();
-				assert(t == ActionType.RESTORE_POINT);
+				Action t = read_action();
+				assert(t == Action.RESTORE_POINT);
 				int id = read_int();
 				uint32 size = read_uint32();
 				uint32 num_guids = read_uint32();
@@ -828,7 +732,7 @@ namespace Crown
 				}
 				else
 				{
-					set_property(id, key, null);
+					set_property_null(id, key);
 				}
 			}
 
@@ -839,18 +743,145 @@ namespace Crown
 			destroy_internal(id);
 		}
 
-		public void set_property(Guid id, string key, Value? value)
+		public void set_property_null(Guid id, string key)
 		{
 			assert(has_object(id));
 			assert(is_valid_key(key));
-			assert(is_valid_value(value));
+			assert(is_valid_value(null));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+			{
+				if (ob[key].holds(typeof(bool)))
+					_undo.write_set_property_bool_action(id, key, (bool)ob[key]);
+				if (ob[key].holds(typeof(double)))
+					_undo.write_set_property_double_action(id, key, (double)ob[key]);
+				if (ob[key].holds(typeof(string)))
+					_undo.write_set_property_string_action(id, key, (string)ob[key]);
+				if (ob[key].holds(typeof(Guid)))
+					_undo.write_set_property_guid_action(id, key, (Guid)ob[key]);
+				if (ob[key].holds(typeof(Vector3)))
+					_undo.write_set_property_vector3_action(id, key, (Vector3)ob[key]);
+				if (ob[key].holds(typeof(Quaternion)))
+					_undo.write_set_property_quaternion_action(id, key, (Quaternion)ob[key]);
+			}
+			else
+			{
+				_undo.write_set_property_null_action(id, key);
+			}
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, null);
+		}
+
+		public void set_property_bool(Guid id, string key, bool val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
 
 			HashMap<string, Value?> ob = get_data(id);
-			_undo.write_set_property_action(id, key, ob.has_key(key) ? ob[key] : null);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_bool_action(id, key, (bool)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
 			_redo.clear();
 			_redo_points.clear();
 
-			set_property_internal(id, key, value);
+			set_property_internal(id, key, val);
+		}
+
+		public void set_property_double(Guid id, string key, double val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_double_action(id, key, (double)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, val);
+		}
+
+		public void set_property_string(Guid id, string key, string val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_string_action(id, key, (string)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, val);
+		}
+
+		public void set_property_guid(Guid id, string key, Guid val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_guid_action(id, key, (Guid)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, val);
+		}
+
+		public void set_property_vector3(Guid id, string key, Vector3 val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_vector3_action(id, key, (Vector3)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, val);
+		}
+
+		public void set_property_quaternion(Guid id, string key, Quaternion val)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+			assert(is_valid_value(val));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key) && ob[key] != null)
+				_undo.write_set_property_quaternion_action(id, key, (Quaternion)ob[key]);
+			else
+				_undo.write_set_property_null_action(id, key);
+
+			_redo.clear();
+			_redo_points.clear();
+
+			set_property_internal(id, key, val);
 		}
 
 		public void add_to_set(Guid id, string key, Guid item_id)
@@ -911,6 +942,55 @@ namespace Crown
 			return value;
 		}
 
+		public bool get_property_bool(Guid id, string key)
+		{
+			return (bool)get_property(id, key);
+		}
+
+		public double get_property_double(Guid id, string key)
+		{
+			return (double)get_property(id, key);
+		}
+
+		public string get_property_string(Guid id, string key)
+		{
+			return (string)get_property(id, key);
+		}
+
+		public Guid get_property_guid(Guid id, string key)
+		{
+			return (Guid)get_property(id, key);
+		}
+
+		public Vector3 get_property_vector3(Guid id, string key)
+		{
+			return (Vector3)get_property(id, key);
+		}
+
+		public Quaternion get_property_quaternion(Guid id, string key)
+		{
+			return (Quaternion)get_property(id, key);
+		}
+
+		public HashSet<Guid?> get_property_set(Guid id, string key, HashSet<Guid?> deffault)
+		{
+			assert(has_object(id));
+			assert(is_valid_key(key));
+
+			HashMap<string, Value?> ob = get_data(id);
+			if (ob.has_key(key))
+				return ob[key] as HashSet<Guid?>;
+			else
+				return deffault;
+#if 0
+			// stdout.printf("get_property %s %s %s\n"
+			// 	, id.to_string()
+			// 	, key
+			// 	, (value == null) ? "null" : value_to_string(value)
+			// 	);
+#endif // CROWN_DEBUG
+		}
+
 		public HashMap<string, Value?> get_object(Guid id)
 		{
 			return (HashMap<string, Value?>)get_data(GUID_ZERO)[id.to_string()];
@@ -943,11 +1023,11 @@ namespace Crown
 
 			create(new_id);
 
-			HashMap<string, Value?> o = get_data(id);
-			string[] keys = o.keys.to_array();
+			HashMap<string, Value?> ob = get_data(id);
+			string[] keys = ob.keys.to_array();
 			foreach (string key in keys)
 			{
-				Value? val = o[key];
+				Value? val = ob[key];
 				if (val.holds(typeof(HashSet)))
 				{
 					HashSet<Guid?> hs = (HashSet<Guid?>)val;
@@ -960,7 +1040,20 @@ namespace Crown
 				}
 				else
 				{
-					set_property(new_id, key, o[key]);
+					if (ob[key] == null)
+						set_property_null(new_id, key);
+					if (ob[key].holds(typeof(bool)))
+						set_property_bool(new_id, key, (bool)ob[key]);
+					if (ob[key].holds(typeof(double)))
+						set_property_double(new_id, key, (double)ob[key]);
+					if (ob[key].holds(typeof(string)))
+						set_property_string(new_id, key, (string)ob[key]);
+					if (ob[key].holds(typeof(Guid)))
+						set_property_guid(new_id, key, (Guid)ob[key]);
+					if (ob[key].holds(typeof(Vector3)))
+						set_property_vector3(new_id, key, (Vector3)ob[key]);
+					if (ob[key].holds(typeof(Quaternion)))
+						set_property_quaternion(new_id, key, (Quaternion)ob[key]);
 				}
 			}
 		}
@@ -976,14 +1069,14 @@ namespace Crown
 
 		public void copy_deep(Database db, Guid id, string new_key)
 		{
-			HashMap<string, Value?> o = get_data(id);
-			string[] keys = o.keys.to_array();
+			HashMap<string, Value?> ob = get_data(id);
+			string[] keys = ob.keys.to_array();
 			foreach (string key in keys)
 			{
 				if (key == "_objects")
 					continue;
 
-				Value? value = o[key];
+				Value? value = ob[key];
 				if (value.holds(typeof(HashSet)))
 				{
 					HashSet<Guid?> hs = (HashSet<Guid?>)value;
@@ -996,7 +1089,22 @@ namespace Crown
 				}
 				else
 				{
-					db.set_property(id, new_key + (new_key == "" ? "" : ".") + key, o[key]);
+					string kk = new_key + (new_key == "" ? "" : ".") + key;
+
+					if (ob[key] == null)
+						db.set_property_null(id, kk);
+					if (ob[key].holds(typeof(bool)))
+						db.set_property_bool(id, kk, (bool)ob[key]);
+					if (ob[key].holds(typeof(double)))
+						db.set_property_double(id, kk, (double)ob[key]);
+					if (ob[key].holds(typeof(string)))
+						db.set_property_string(id, kk, (string)ob[key]);
+					if (ob[key].holds(typeof(Guid)))
+						db.set_property_guid(id, kk, (Guid)ob[key]);
+					if (ob[key].holds(typeof(Vector3)))
+						db.set_property_vector3(id, kk, (Vector3)ob[key]);
+					if (ob[key].holds(typeof(Quaternion)))
+						db.set_property_quaternion(id, kk, (Quaternion)ob[key]);
 				}
 			}
 		}
@@ -1025,76 +1133,181 @@ namespace Crown
 
 		private void undo_until(uint32 size)
 		{
-			while (_undo.size() != size)
+			undo_redo_until(size, _undo, _redo);
+		}
+
+		private void redo_until(uint32 size)
+		{
+			undo_redo_until(size, _redo, _undo);
+		}
+
+		private void undo_redo_until(uint32 size, Stack undo, Stack redo)
+		{
+			while (undo.size() != size)
 			{
-				uint32 type = _undo.peek_type();
-				if (type == ActionType.CREATE)
+				uint32 type = undo.peek_type();
+				if (type == Action.CREATE)
 				{
-					CreateAction a = _undo.read_create_action();
-					_redo.write_destroy_action(a.id);
-					create_internal(a.id);
+					Action t = undo.read_action();
+					assert(t == Action.CREATE);
+
+					Guid id = undo.read_guid();
+
+					redo.write_destroy_action(id);
+					create_internal(id);
 				}
-				else if (type == ActionType.DESTROY)
+				else if (type == Action.DESTROY)
 				{
-					DestroyAction a = _undo.read_destroy_action();
-					_redo.write_create_action(a.id);
-					destroy_internal(a.id);
+					Action t = undo.read_action();
+					assert(t == Action.DESTROY);
+
+					Guid id = undo.read_guid();
+
+					redo.write_create_action(id);
+					destroy_internal(id);
 				}
-				else if (type == ActionType.SET_PROPERTY)
+				else if (type == Action.SET_PROPERTY_NULL)
 				{
-					SetPropertyAction a = _undo.read_set_property_action();
-					_redo.write_set_property_action(a.id, a.key, get_data(a.id).has_key(a.key) ? get_data(a.id)[a.key] : null);
-					set_property_internal(a.id, a.key, a.val);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_NULL);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+
+					if (get_data(id).has_key(key))
+					{
+						if (get_data(id)[key].holds(typeof(bool)))
+							redo.write_set_property_bool_action(id, key, (bool)get_data(id)[key]);
+						if (get_data(id)[key].holds(typeof(double)))
+							redo.write_set_property_double_action(id, key, (double)get_data(id)[key]);
+						if (get_data(id)[key].holds(typeof(string)))
+							redo.write_set_property_string_action(id, key, (string)get_data(id)[key]);
+						if (get_data(id)[key].holds(typeof(Guid)))
+							redo.write_set_property_guid_action(id, key, (Guid)get_data(id)[key]);
+						if (get_data(id)[key].holds(typeof(Vector3)))
+							redo.write_set_property_vector3_action(id, key, (Vector3)get_data(id)[key]);
+						if (get_data(id)[key].holds(typeof(Quaternion)))
+							redo.write_set_property_quaternion_action(id, key, (Quaternion)get_data(id)[key]);
+					}
+					else
+					{
+						redo.write_set_property_null_action(id, key);
+					}
+					set_property_internal(id, key, null);
 				}
-				else if (type == ActionType.ADD_TO_SET)
+				else if (type == Action.SET_PROPERTY_BOOL)
 				{
-					AddToSetAction a = _undo.read_add_to_set_action();
-					_redo.write_remove_from_set_action(a.id, a.key, a.item_id);
-					add_to_set_internal(a.id, a.key, a.item_id);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_BOOL);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					bool val = undo.read_bool();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_bool_action(id, key, (bool)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
 				}
-				else if (type == ActionType.REMOVE_FROM_SET)
+				else if (type == Action.SET_PROPERTY_DOUBLE)
 				{
-					RemoveFromSetAction a = _undo.read_remove_from_set_action();
-					_redo.write_add_to_set_action(a.id, a.key, a.item_id);
-					remove_from_set_internal(a.id, a.key, a.item_id);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_DOUBLE);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					double val = undo.read_double();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_double_action(id, key, (double)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
 				}
-			}
-		}
+				else if (type == Action.SET_PROPERTY_STRING)
+				{
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_STRING);
 
-		private void redo_until(uint32 size)
-		{
-			while (_redo.size() != size)
-			{
-				uint32 type = _redo.peek_type();
-				if (type == ActionType.CREATE)
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					string val = undo.read_string();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_string_action(id, key, (string)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
+				}
+				else if (type == Action.SET_PROPERTY_GUID)
 				{
-					CreateAction a = _redo.read_create_action();
-					_undo.write_destroy_action(a.id);
-					create_internal(a.id);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_GUID);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					Guid val = undo.read_guid();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_guid_action(id, key, (Guid)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
 				}
-				else if (type == ActionType.DESTROY)
+				else if (type == Action.SET_PROPERTY_VECTOR3)
 				{
-					DestroyAction a = _redo.read_destroy_action();
-					_undo.write_create_action(a.id);
-					destroy_internal(a.id);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_VECTOR3);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					Vector3 val = undo.read_vector3();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_vector3_action(id, key, (Vector3)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
 				}
-				else if (type == ActionType.SET_PROPERTY)
+				else if (type == Action.SET_PROPERTY_QUATERNION)
 				{
-					SetPropertyAction a = _redo.read_set_property_action();
-					_undo.write_set_property_action(a.id, a.key, get_data(a.id).has_key(a.key) ? get_data(a.id)[a.key] : null);
-					set_property_internal(a.id, a.key, a.val);
+					Action t = undo.read_action();
+					assert(t == Action.SET_PROPERTY_QUATERNION);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					Quaternion val = undo.read_quaternion();
+
+					if (get_data(id).has_key(key))
+						redo.write_set_property_quaternion_action(id, key, (Quaternion)get_data(id)[key]);
+					else
+						redo.write_set_property_null_action(id, key);
+					set_property_internal(id, key, val);
 				}
-				else if (type == ActionType.ADD_TO_SET)
+				else if (type == Action.ADD_TO_SET)
 				{
-					AddToSetAction a = _redo.read_add_to_set_action();
-					_undo.write_remove_from_set_action(a.id, a.key, a.item_id);
-					add_to_set_internal(a.id, a.key, a.item_id);
+					Action t = undo.read_action();
+					assert(t == Action.ADD_TO_SET);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					Guid item_id = undo.read_guid();
+
+					redo.write_remove_from_set_action(id, key, item_id);
+					add_to_set_internal(id, key, item_id);
 				}
-				else if (type == ActionType.REMOVE_FROM_SET)
+				else if (type == Action.REMOVE_FROM_SET)
 				{
-					RemoveFromSetAction a = _redo.read_remove_from_set_action();
-					_undo.write_add_to_set_action(a.id, a.key, a.item_id);
-					remove_from_set_internal(a.id, a.key, a.item_id);
+					Action t = undo.read_action();
+					assert(t == Action.REMOVE_FROM_SET);
+
+					Guid id = undo.read_guid();
+					string key = undo.read_string();
+					Guid item_id = undo.read_guid();
+
+					redo.write_add_to_set_action(id, key, item_id);
+					remove_from_set_internal(id, key, item_id);
 				}
 			}
 		}

+ 95 - 104
tools/level_editor/level.vala

@@ -195,23 +195,23 @@ namespace Crown
 
 			_db.add_restore_point((int)ActionType.SPAWN_UNIT, new Guid[] { id });
 			_db.create(id);
-			_db.set_property(id, "editor.name", "unit_%04u".printf(_num_units++));
-			_db.set_property(id, "prefab", name);
+			_db.set_property_string(id, "editor.name", "unit_%04u".printf(_num_units++));
+			_db.set_property_string(id, "prefab", name);
 
 			Guid transform_id = GUID_ZERO;
 			Unit unit = new Unit(_db, id, _prefabs);
 			if (unit.has_component("transform", ref transform_id))
 			{
-				unit.set_component_property(transform_id, "data.position", pos);
-				unit.set_component_property(transform_id, "data.rotation", rot);
-				unit.set_component_property(transform_id, "data.scale", scl);
-				unit.set_component_property(transform_id, "type", "transform");
+				unit.set_component_property_vector3   (transform_id, "data.position", pos);
+				unit.set_component_property_quaternion(transform_id, "data.rotation", rot);
+				unit.set_component_property_vector3   (transform_id, "data.scale", scl);
+				unit.set_component_property_string    (transform_id, "type", "transform");
 			}
 			else
 			{
-				_db.set_property(id, "position", pos);
-				_db.set_property(id, "rotation", rot);
-				_db.set_property(id, "scale", scl);
+				_db.set_property_vector3   (id, "position", pos);
+				_db.set_property_quaternion(id, "rotation", rot);
+				_db.set_property_vector3   (id, "scale", scl);
 			}
 			_db.add_to_set(GUID_ZERO, "units", id);
 		}
@@ -220,13 +220,13 @@ namespace Crown
 		{
 			_db.add_restore_point((int)ActionType.SPAWN_SOUND, new Guid[] { id });
 			_db.create(id);
-			_db.set_property(id, "editor.name", "sound_%04u".printf(_num_sounds++));
-			_db.set_property(id, "position", pos);
-			_db.set_property(id, "rotation", rot);
-			_db.set_property(id, "name", name);
-			_db.set_property(id, "range", range);
-			_db.set_property(id, "volume", volume);
-			_db.set_property(id, "loop", loop);
+			_db.set_property_string    (id, "editor.name", "sound_%04u".printf(_num_sounds++));
+			_db.set_property_vector3   (id, "position", pos);
+			_db.set_property_quaternion(id, "rotation", rot);
+			_db.set_property_string    (id, "name", name);
+			_db.set_property_double    (id, "range", range);
+			_db.set_property_double    (id, "volume", volume);
+			_db.set_property_bool      (id, "loop", loop);
 			_db.add_to_set(GUID_ZERO, "sounds", id);
 		}
 
@@ -248,21 +248,21 @@ namespace Crown
 
 					if (unit.has_component("transform", ref transform_id))
 					{
-						unit.set_component_property(transform_id, "data.position", pos);
-						unit.set_component_property(transform_id, "data.rotation", rot);
-						unit.set_component_property(transform_id, "data.scale", scl);
+						unit.set_component_property_vector3   (transform_id, "data.position", pos);
+						unit.set_component_property_quaternion(transform_id, "data.rotation", rot);
+						unit.set_component_property_vector3   (transform_id, "data.scale", scl);
 					}
 					else
 					{
-						_db.set_property(id, "position", pos);
-						_db.set_property(id, "rotation", rot);
-						_db.set_property(id, "scale", scl);
+						_db.set_property_vector3   (id, "position", pos);
+						_db.set_property_quaternion(id, "rotation", rot);
+						_db.set_property_vector3   (id, "scale", scl);
 					}
 				}
 				else if (is_sound(id))
 				{
-					_db.set_property(id, "position", pos);
-					_db.set_property(id, "rotation", rot);
+					_db.set_property_vector3   (id, "position", pos);
+					_db.set_property_quaternion(id, "rotation", rot);
 				}
 			}
 			// FIXME: Hack to force update the properties view
@@ -293,12 +293,12 @@ namespace Crown
 			_db.add_restore_point((int)ActionType.SET_LIGHT, new Guid[] { unit_id });
 
 			Unit unit = new Unit(_db, unit_id, _prefabs);
-			unit.set_component_property(component_id, "data.type",       type);
-			unit.set_component_property(component_id, "data.range",      range);
-			unit.set_component_property(component_id, "data.intensity",  intensity);
-			unit.set_component_property(component_id, "data.spot_angle", spot_angle);
-			unit.set_component_property(component_id, "data.color",      color);
-			unit.set_component_property(component_id, "type", "light");
+			unit.set_component_property_string (component_id, "data.type",       type);
+			unit.set_component_property_double (component_id, "data.range",      range);
+			unit.set_component_property_double (component_id, "data.intensity",  intensity);
+			unit.set_component_property_double (component_id, "data.spot_angle", spot_angle);
+			unit.set_component_property_vector3(component_id, "data.color",      color);
+			unit.set_component_property_string (component_id, "type", "light");
 
 			_client.send_script(LevelEditorApi.set_light(unit_id, type, range, intensity, spot_angle, color));
 		}
@@ -308,12 +308,12 @@ namespace Crown
 			_db.add_restore_point((int)ActionType.SET_SPRITE, new Guid[] { unit_id });
 
 			Unit unit = new Unit(_db, unit_id, _prefabs);
-			unit.set_component_property(component_id, "data.layer", layer);
-			unit.set_component_property(component_id, "data.depth", depth);
-			unit.set_component_property(component_id, "data.material", material);
-			unit.set_component_property(component_id, "data.sprite_resource", sprite_resource);
-			unit.set_component_property(component_id, "data.visible", visible);
-			unit.set_component_property(component_id, "type", "sprite_renderer");
+			unit.set_component_property_double(component_id, "data.layer", layer);
+			unit.set_component_property_double(component_id, "data.depth", depth);
+			unit.set_component_property_string(component_id, "data.material", material);
+			unit.set_component_property_string(component_id, "data.sprite_resource", sprite_resource);
+			unit.set_component_property_bool  (component_id, "data.visible", visible);
+			unit.set_component_property_string(component_id, "type", "sprite_renderer");
 
 			_client.send_script(LevelEditorApi.set_sprite(unit_id, layer, depth));
 		}
@@ -322,24 +322,26 @@ namespace Crown
 		{
 			_db.add_restore_point((int)ActionType.SET_SOUND, new Guid[] { sound_id });
 
-			_db.set_property(sound_id, "name", name);
-			_db.set_property(sound_id, "range", range);
-			_db.set_property(sound_id, "volume", volume);
-			_db.set_property(sound_id, "loop", loop);
+			_db.set_property_string(sound_id, "name", name);
+			_db.set_property_double(sound_id, "range", range);
+			_db.set_property_double(sound_id, "volume", volume);
+			_db.set_property_bool  (sound_id, "loop", loop);
 
 			_client.send_script(LevelEditorApi.set_sound_range(sound_id, range));
 		}
 
 		public string object_editor_name(Guid object_id)
 		{
-			Value? name = _db.get_property(object_id, "editor.name");
-			return name != null ? (string)name : "<unnamed>";
+			if (_db.has_property(object_id, "editor.name"))
+				return _db.get_property_string(object_id, "editor.name");
+			else
+				return "<unnamed>";
 		}
 
 		public void object_set_editor_name(Guid object_id, string name)
 		{
 			_db.add_restore_point((int)ActionType.OBJECT_SET_EDITOR_NAME, new Guid[] { object_id });
-			_db.set_property(object_id, "editor.name", name);
+			_db.set_property_string(object_id, "editor.name", name);
 
 			object_editor_name_changed(object_id, name);
 		}
@@ -395,8 +397,8 @@ namespace Crown
 
 		public void send_level()
 		{
-			HashSet<Guid?> units = _db.get_property(GUID_ZERO, "units") as HashSet<Guid?>;
-			HashSet<Guid?> sounds = _db.get_property(GUID_ZERO, "sounds") as HashSet<Guid?>;
+			HashSet<Guid?> units  = _db.get_property_set(GUID_ZERO, "units", new HashSet<Guid?>());
+			HashSet<Guid?> sounds = _db.get_property_set(GUID_ZERO, "sounds", new HashSet<Guid?>());
 
 			Guid[] unit_ids = new Guid[units.size];
 			Guid[] sound_ids = new Guid[sounds.size];
@@ -437,9 +439,8 @@ namespace Crown
 			else
 				prefab_db.load(_source_dir + "/" + name + ".unit");
 
-			Value? prefab = prefab_db.get_property(GUID_ZERO, "prefab");
-			if (prefab != null)
-				load_prefab((string)prefab);
+			if (prefab_db.has_property(GUID_ZERO, "prefab"))
+				load_prefab((prefab_db.get_property_string(GUID_ZERO, "prefab")));
 
 			prefab_db.copy_to(_prefabs, name);
 			_loaded_prefabs.add(name);
@@ -452,7 +453,7 @@ namespace Crown
 				Unit unit = new Unit(_db, unit_id, _prefabs);
 
 				if (unit.has_prefab())
-					load_prefab((string)_db.get_property(unit_id, "prefab"));
+					load_prefab(_db.get_property_string(unit_id, "prefab"));
 
 				sb.append(LevelEditorApi.spawn_empty_unit(unit_id));
 
@@ -462,9 +463,9 @@ namespace Crown
 				{
 					string s = LevelEditorApi.add_tranform_component(unit_id
 						, component_id
-						, (Vector3)   unit.get_component_property(component_id, "data.position")
-						, (Quaternion)unit.get_component_property(component_id, "data.rotation")
-						, (Vector3)   unit.get_component_property(component_id, "data.scale")
+						, unit.get_component_property_vector3   (component_id, "data.position")
+						, unit.get_component_property_quaternion(component_id, "data.rotation")
+						, unit.get_component_property_vector3   (component_id, "data.scale")
 						);
 					sb.append(s);
 				}
@@ -472,10 +473,10 @@ namespace Crown
 				{
 					string s = LevelEditorApi.add_mesh_component(unit_id
 						, component_id
-						, (string)unit.get_component_property(component_id, "data.mesh_resource")
-						, (string)unit.get_component_property(component_id, "data.geometry_name")
-						, (string)unit.get_component_property(component_id, "data.material")
-						, (bool)  unit.get_component_property(component_id, "data.visible")
+						, unit.get_component_property_string(component_id, "data.mesh_resource")
+						, unit.get_component_property_string(component_id, "data.geometry_name")
+						, unit.get_component_property_string(component_id, "data.material")
+						, unit.get_component_property_bool  (component_id, "data.visible")
 						);
 					sb.append(s);
 				}
@@ -483,11 +484,11 @@ namespace Crown
 				{
 					string s = LevelEditorApi.add_sprite_component(unit_id
 						, component_id
-						, (string)unit.get_component_property(component_id, "data.sprite_resource")
-						, (string)unit.get_component_property(component_id, "data.material")
-						, (double)unit.get_component_property(component_id, "data.layer")
-						, (double)unit.get_component_property(component_id, "data.depth")
-						, (bool)  unit.get_component_property(component_id, "data.visible")
+						, unit.get_component_property_string(component_id, "data.sprite_resource")
+						, unit.get_component_property_string(component_id, "data.material")
+						, unit.get_component_property_double(component_id, "data.layer")
+						, unit.get_component_property_double(component_id, "data.depth")
+						, unit.get_component_property_bool  (component_id, "data.visible")
 						);
 					sb.append(s);
 				}
@@ -495,11 +496,11 @@ namespace Crown
 				{
 					string s = LevelEditorApi.add_light_component(unit_id
 						, component_id
-						, (string) unit.get_component_property(component_id, "data.type")
-						, (double) unit.get_component_property(component_id, "data.range")
-						, (double) unit.get_component_property(component_id, "data.intensity")
-						, (double) unit.get_component_property(component_id, "data.spot_angle")
-						, (Vector3)unit.get_component_property(component_id, "data.color")
+						, unit.get_component_property_string (component_id, "data.type")
+						, unit.get_component_property_double (component_id, "data.range")
+						, unit.get_component_property_double (component_id, "data.intensity")
+						, unit.get_component_property_double (component_id, "data.spot_angle")
+						, unit.get_component_property_vector3(component_id, "data.color")
 						);
 					sb.append(s);
 				}
@@ -507,10 +508,10 @@ namespace Crown
 				{
 					string s = LevelEditorApi.add_camera_component(unit_id
 						, component_id
-						, (string)unit.get_component_property(component_id, "data.projection")
-						, (double)unit.get_component_property(component_id, "data.fov")
-						, (double)unit.get_component_property(component_id, "data.far_range")
-						, (double)unit.get_component_property(component_id, "data.near_range")
+						, unit.get_component_property_string(component_id, "data.projection")
+						, unit.get_component_property_double(component_id, "data.fov")
+						, unit.get_component_property_double(component_id, "data.far_range")
+						, unit.get_component_property_double(component_id, "data.near_range")
 						);
 					sb.append(s);
 				}
@@ -522,12 +523,12 @@ namespace Crown
 			foreach (Guid sound_id in sound_ids)
 			{
 				string s = LevelEditorApi.spawn_sound(sound_id
-					, (string)    _db.get_property(sound_id, "name")
-					, (Vector3)   _db.get_property(sound_id, "position")
-					, (Quaternion)_db.get_property(sound_id, "rotation")
-					, (double)    _db.get_property(sound_id, "range")
-					, (double)    _db.get_property(sound_id, "volume")
-					, (bool)      _db.get_property(sound_id, "loop")
+					, _db.get_property_string    (sound_id, "name")
+					, _db.get_property_vector3   (sound_id, "position")
+					, _db.get_property_quaternion(sound_id, "rotation")
+					, _db.get_property_double    (sound_id, "range")
+					, _db.get_property_double    (sound_id, "volume")
+					, _db.get_property_bool      (sound_id, "loop")
 					);
 				sb.append(s);
 			}
@@ -592,22 +593,22 @@ namespace Crown
 
 							if (unit.has_component("transform", ref transform_id))
 							{
-								positions[i] = (Vector3)   unit.get_component_property(transform_id, "data.position");
-								rotations[i] = (Quaternion)unit.get_component_property(transform_id, "data.rotation");
-								scales[i]    = (Vector3)   unit.get_component_property(transform_id, "data.scale");
+								positions[i] = unit.get_component_property_vector3   (transform_id, "data.position");
+								rotations[i] = unit.get_component_property_quaternion(transform_id, "data.rotation");
+								scales[i]    = unit.get_component_property_vector3   (transform_id, "data.scale");
 							}
 							else
 							{
-								positions[i] = (Vector3)   _db.get_property(unit_id, "position");
-								rotations[i] = (Quaternion)_db.get_property(unit_id, "rotation");
-								scales[i]    = (Vector3)   _db.get_property(unit_id, "scale");
+								positions[i] = _db.get_property_vector3   (unit_id, "position");
+								rotations[i] = _db.get_property_quaternion(unit_id, "rotation");
+								scales[i]    = _db.get_property_vector3   (unit_id, "scale");
 							}
 						}
 						else if (is_sound(ids[i]))
 						{
 							Guid sound_id = ids[i];
-							positions[i] = (Vector3)   _db.get_property(sound_id, "position");
-							rotations[i] = (Quaternion)_db.get_property(sound_id, "rotation");
+							positions[i] = _db.get_property_vector3   (sound_id, "position");
+							rotations[i] = _db.get_property_quaternion(sound_id, "rotation");
 							scales[i]    = Vector3(1.0, 1.0, 1.0);
 						}
 						else
@@ -645,11 +646,11 @@ namespace Crown
 					unit.has_component("light", ref component_id);
 
 					_client.send_script(LevelEditorApi.set_light(unit_id
-						, (string) unit.get_component_property(component_id, "data.type")
-						, (double) unit.get_component_property(component_id, "data.range")
-						, (double) unit.get_component_property(component_id, "data.intensity")
-						, (double) unit.get_component_property(component_id, "data.spot_angle")
-						, (Vector3)unit.get_component_property(component_id, "data.color")
+						, unit.get_component_property_string (component_id, "data.type")
+						, unit.get_component_property_double (component_id, "data.range")
+						, unit.get_component_property_double (component_id, "data.intensity")
+						, unit.get_component_property_double (component_id, "data.spot_angle")
+						, unit.get_component_property_vector3(component_id, "data.color")
 						));
 					// FIXME: Hack to force update the properties view
 					selection_changed(_selection);
@@ -665,8 +666,8 @@ namespace Crown
 					unit.has_component("sprite_renderer", ref component_id);
 
 					_client.send_script(LevelEditorApi.set_sprite(unit_id
-						, (double)unit.get_component_property(component_id, "data.layer")
-						, (double)unit.get_component_property(component_id, "data.depth")
+						, unit.get_component_property_double(component_id, "data.layer")
+						, unit.get_component_property_double(component_id, "data.depth")
 						));
 					// FIXME: Hack to force update the properties view
 					selection_changed(_selection);
@@ -678,7 +679,7 @@ namespace Crown
 					Guid sound_id = data[0];
 
 					_client.send_script(LevelEditorApi.set_sound_range(sound_id
-						, (double)_db.get_property(sound_id, "range")
+						, _db.get_property_double(sound_id, "range")
 						));
 					// FIXME: Hack to force update the properties view
 					selection_changed(_selection);
@@ -691,24 +692,14 @@ namespace Crown
 			}
 		}
 
-		public Value? get_property(Guid id, string key)
-		{
-			return _db.get_property(id, key);
-		}
-
-		public void set_property(Guid id, string key, Value? value)
-		{
-			_db.set_property(id, key, value);
-		}
-
 		public bool is_unit(Guid id)
 		{
-			return (_db.get_property(GUID_ZERO, "units") as HashSet<Guid?>).contains(id);
+			return _db.get_property_set(GUID_ZERO, "units", new HashSet<Guid?>()).contains(id);
 		}
 
 		public bool is_sound(Guid id)
 		{
-			return (_db.get_property(GUID_ZERO, "sounds") as HashSet<Guid?>).contains(id);
+			return _db.get_property_set(GUID_ZERO, "sounds", new HashSet<Guid?>()).contains(id);
 		}
 	}
 }

+ 27 - 33
tools/level_editor/level_tree_view.vala

@@ -325,43 +325,37 @@ namespace Crown
 				, -1
 				);
 
-			Value? units  = _db.get_property(GUID_ZERO, "units");
-			Value? sounds = _db.get_property(GUID_ZERO, "sounds");
+			HashSet<Guid?> units  = _db.get_property_set(GUID_ZERO, "units", new HashSet<Guid?>());
+			HashSet<Guid?> sounds = _db.get_property_set(GUID_ZERO, "sounds", new HashSet<Guid?>());
 
-			if (units != null)
+			foreach (Guid unit in units)
 			{
-				foreach (Guid unit in (HashSet<Guid?>)units)
-				{
-					Unit u = new Unit(_level._db, unit, _level._prefabs);
-					Gtk.TreeIter iter;
-					_tree_store.append(out iter, u.is_light() ? light_iter : unit_iter);
-					_tree_store.set(iter
-						, Column.TYPE
-						, ItemType.UNIT
-						, Column.GUID
-						, unit
-						, Column.NAME
-						, _level.object_editor_name(unit)
-						, -1
-						);
-				}
+				Unit u = new Unit(_level._db, unit, _level._prefabs);
+				Gtk.TreeIter iter;
+				_tree_store.append(out iter, u.is_light() ? light_iter : unit_iter);
+				_tree_store.set(iter
+					, Column.TYPE
+					, ItemType.UNIT
+					, Column.GUID
+					, unit
+					, Column.NAME
+					, _level.object_editor_name(unit)
+					, -1
+					);
 			}
-			if (sounds != null)
+			foreach (Guid sound in sounds)
 			{
-				foreach (Guid sound in (HashSet<Guid?>)sounds)
-				{
-					Gtk.TreeIter iter;
-					_tree_store.append(out iter, sound_iter);
-					_tree_store.set(iter
-						, Column.TYPE
-						, ItemType.SOUND
-						, Column.GUID
-						, sound
-						, Column.NAME
-						, _level.object_editor_name(sound)
-						, -1
-						);
-				}
+				Gtk.TreeIter iter;
+				_tree_store.append(out iter, sound_iter);
+				_tree_store.set(iter
+					, Column.TYPE
+					, ItemType.SOUND
+					, Column.GUID
+					, sound
+					, Column.NAME
+					, _level.object_editor_name(sound)
+					, -1
+					);
 			}
 
 			_tree_view.model = _tree_sort;

+ 36 - 36
tools/level_editor/project.vala

@@ -101,9 +101,9 @@ namespace Crown
 
 			Guid id = Guid.new_guid();
 			_files.create(id);
-			_files.set_property(id, "path", path);
-			_files.set_property(id, "type", type);
-			_files.set_property(id, "name", name);
+			_files.set_property_string(id, "path", path);
+			_files.set_property_string(id, "type", type);
+			_files.set_property_string(id, "name", name);
 			_files.add_to_set(GUID_ZERO, "data", id);
 
 			_map[path] = id;
@@ -244,19 +244,19 @@ namespace Crown
 					if (!unit.has_component("transform", ref id))
 					{
 						db.create(id);
-						db.set_property(id, "data.position", VECTOR3_ZERO);
-						db.set_property(id, "data.rotation", QUATERNION_IDENTITY);
-						db.set_property(id, "data.scale", VECTOR3_ONE);
-						db.set_property(id, "type", "transform");
+						db.set_property_vector3   (id, "data.position", VECTOR3_ZERO);
+						db.set_property_quaternion(id, "data.rotation", QUATERNION_IDENTITY);
+						db.set_property_vector3   (id, "data.scale", VECTOR3_ONE);
+						db.set_property_string    (id, "type", "transform");
 
 						db.add_to_set(GUID_ZERO, "components", id);
 					}
 					else
 					{
-						unit.set_component_property(id, "data.position", VECTOR3_ZERO);
-						unit.set_component_property(id, "data.rotation", QUATERNION_IDENTITY);
-						unit.set_component_property(id, "data.scale", VECTOR3_ONE);
-						unit.set_component_property(id, "type", "transform");
+						unit.set_component_property_vector3   (id, "data.position", VECTOR3_ZERO);
+						unit.set_component_property_quaternion(id, "data.rotation", QUATERNION_IDENTITY);
+						unit.set_component_property_vector3   (id, "data.scale", VECTOR3_ONE);
+						unit.set_component_property_string    (id, "type", "transform");
 					}
 				}
 
@@ -267,23 +267,23 @@ namespace Crown
 					if (!unit.has_component("sprite_renderer", ref id))
 					{
 						db.create(id);
-						db.set_property(id, "data.material", resource_name);
-						db.set_property(id, "data.sprite_resource", resource_name);
-						db.set_property(id, "data.layer", layer);
-						db.set_property(id, "data.depth", depth);
-						db.set_property(id, "data.visible", true);
-						db.set_property(id, "type", "sprite_renderer");
+						db.set_property_string(id, "data.material", resource_name);
+						db.set_property_string(id, "data.sprite_resource", resource_name);
+						db.set_property_double(id, "data.layer", layer);
+						db.set_property_double(id, "data.depth", depth);
+						db.set_property_bool  (id, "data.visible", true);
+						db.set_property_string(id, "type", "sprite_renderer");
 
 						db.add_to_set(GUID_ZERO, "components", id);
 					}
 					else
 					{
-						unit.set_component_property(id, "data.material", resource_name);
-						unit.set_component_property(id, "data.sprite_resource", resource_name);
-						unit.set_component_property(id, "data.layer", layer);
-						unit.set_component_property(id, "data.depth", depth);
-						unit.set_component_property(id, "data.visible", true);
-						unit.set_component_property(id, "type", "sprite_renderer");
+						unit.set_component_property_string(id, "data.material", resource_name);
+						unit.set_component_property_string(id, "data.sprite_resource", resource_name);
+						unit.set_component_property_double(id, "data.layer", layer);
+						unit.set_component_property_double(id, "data.depth", depth);
+						unit.set_component_property_bool  (id, "data.visible", true);
+						unit.set_component_property_string(id, "type", "sprite_renderer");
 					}
 				}
 
@@ -364,19 +364,19 @@ namespace Crown
 					if (!unit.has_component("transform", ref id))
 					{
 						db.create(id);
-						db.set_property(id, "data.position", VECTOR3_ZERO);
-						db.set_property(id, "data.rotation", QUATERNION_IDENTITY);
-						db.set_property(id, "data.scale", VECTOR3_ONE);
-						db.set_property(id, "type", "transform");
+						db.set_property_vector3   (id, "data.position", VECTOR3_ZERO);
+						db.set_property_quaternion(id, "data.rotation", QUATERNION_IDENTITY);
+						db.set_property_vector3   (id, "data.scale", VECTOR3_ONE);
+						db.set_property_string    (id, "type", "transform");
 
 						db.add_to_set(GUID_ZERO, "components", id);
 					}
 					else
 					{
-						unit.set_component_property(id, "data.position", VECTOR3_ZERO);
-						unit.set_component_property(id, "data.rotation", QUATERNION_IDENTITY);
-						unit.set_component_property(id, "data.scale", VECTOR3_ONE);
-						unit.set_component_property(id, "type", "transform");
+						unit.set_component_property_vector3   (id, "data.position", VECTOR3_ZERO);
+						unit.set_component_property_quaternion(id, "data.rotation", QUATERNION_IDENTITY);
+						unit.set_component_property_vector3   (id, "data.scale", VECTOR3_ONE);
+						unit.set_component_property_string    (id, "type", "transform");
 					}
 				}
 
@@ -397,11 +397,11 @@ namespace Crown
 
 						Guid id = Guid.new_guid();
 						db.create(id);
-						db.set_property(id, "data.geometry_name", node_name);
-						db.set_property(id, "data.material", material_name);
-						db.set_property(id, "data.mesh_resource", resource_name);
-						db.set_property(id, "data.visible", true);
-						db.set_property(id, "type", "mesh_renderer");
+						db.set_property_string(id, "data.geometry_name", node_name);
+						db.set_property_string(id, "data.material", material_name);
+						db.set_property_string(id, "data.mesh_resource", resource_name);
+						db.set_property_bool  (id, "data.visible", true);
+						db.set_property_string(id, "type", "mesh_renderer");
 
 						db.add_to_set(GUID_ZERO, "components", id);
 					}

+ 38 - 36
tools/level_editor/properties_view.vala

@@ -96,9 +96,9 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			Vector3 pos    = (Vector3)   unit.get_component_property(_component_id, "data.position");
-			Quaternion rot = (Quaternion)unit.get_component_property(_component_id, "data.rotation");
-			Vector3 scl    = (Vector3)   unit.get_component_property(_component_id, "data.scale");
+			Vector3 pos    = unit.get_component_property_vector3   (_component_id, "data.position");
+			Quaternion rot = unit.get_component_property_quaternion(_component_id, "data.rotation");
+			Vector3 scl    = unit.get_component_property_vector3   (_component_id, "data.scale");
 
 			_position.value = pos;
 			_rotation.value = rot;
@@ -140,10 +140,10 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			_mesh_resource.text = (string)unit.get_component_property(_component_id, "data.mesh_resource");
-			_geometry.text      = (string)unit.get_component_property(_component_id, "data.geometry_name");
-			_material.text      = (string)unit.get_component_property(_component_id, "data.material");
-			_visible.value      = (bool)  unit.get_component_property(_component_id, "data.visible");
+			_mesh_resource.text = unit.get_component_property_string(_component_id, "data.mesh_resource");
+			_geometry.text      = unit.get_component_property_string(_component_id, "data.geometry_name");
+			_material.text      = unit.get_component_property_string(_component_id, "data.material");
+			_visible.value      = unit.get_component_property_bool  (_component_id, "data.visible");
 		}
 	}
 
@@ -199,11 +199,11 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			_sprite_resource.text = (string)unit.get_component_property(_component_id, "data.sprite_resource");
-			_material.text        = (string)unit.get_component_property(_component_id, "data.material");
-			_layer.value          = (double)unit.get_component_property(_component_id, "data.layer");
-			_depth.value          = (double)unit.get_component_property(_component_id, "data.depth");
-			_visible.value        = (bool)  unit.get_component_property(_component_id, "data.visible");
+			_sprite_resource.text = unit.get_component_property_string(_component_id, "data.sprite_resource");
+			_material.text        = unit.get_component_property_string(_component_id, "data.material");
+			_layer.value          = unit.get_component_property_double(_component_id, "data.layer");
+			_depth.value          = unit.get_component_property_double(_component_id, "data.depth");
+			_visible.value        = unit.get_component_property_bool  (_component_id, "data.visible");
 		}
 	}
 
@@ -262,11 +262,11 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			string type       = (string) unit.get_component_property(_component_id, "data.type");
-			double range      = (double) unit.get_component_property(_component_id, "data.range");
-			double intensity  = (double) unit.get_component_property(_component_id, "data.intensity");
-			double spot_angle = (double) unit.get_component_property(_component_id, "data.spot_angle");
-			Vector3 color     = (Vector3)unit.get_component_property(_component_id, "data.color");
+			string type       = unit.get_component_property_string (_component_id, "data.type");
+			double range      = unit.get_component_property_double (_component_id, "data.range");
+			double intensity  = unit.get_component_property_double (_component_id, "data.intensity");
+			double spot_angle = unit.get_component_property_double (_component_id, "data.spot_angle");
+			Vector3 color     = unit.get_component_property_vector3(_component_id, "data.color");
 
 			_type.value       = type;
 			_range.value      = range;
@@ -314,20 +314,20 @@ namespace Crown
 		private void on_value_changed()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			unit.set_component_property(_component_id, "data.projection", _projection.value);
-			unit.set_component_property(_component_id, "data.fov",        _fov.value*(Math.PI/180.0));
-			unit.set_component_property(_component_id, "data.near_range", _near_range.value);
-			unit.set_component_property(_component_id, "data.far_range",  _far_range.value);
-			unit.set_component_property(_component_id, "type", "camera");
+			unit.set_component_property_string(_component_id, "data.projection", _projection.value);
+			unit.set_component_property_double(_component_id, "data.fov",        _fov.value*(Math.PI/180.0));
+			unit.set_component_property_double(_component_id, "data.near_range", _near_range.value);
+			unit.set_component_property_double(_component_id, "data.far_range",  _far_range.value);
+			unit.set_component_property_string(_component_id, "type", "camera");
 		}
 
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			string type       = (string)unit.get_component_property(_component_id, "data.projection");
-			double fov        = (double)unit.get_component_property(_component_id, "data.fov");
-			double near_range = (double)unit.get_component_property(_component_id, "data.near_range");
-			double far_range  = (double)unit.get_component_property(_component_id, "data.far_range");
+			string type       = unit.get_component_property_string(_component_id, "data.projection");
+			double fov        = unit.get_component_property_double(_component_id, "data.fov");
+			double near_range = unit.get_component_property_double(_component_id, "data.near_range");
+			double far_range  = unit.get_component_property_double(_component_id, "data.far_range");
 
 			_projection.value = type;
 			_fov.value        = fov*(180.0/Math.PI);
@@ -359,7 +359,7 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			_script_resource.text = (string)unit.get_component_property(_component_id, "data.script_resource");
+			_script_resource.text = unit.get_component_property_string(_component_id, "data.script_resource");
 		}
 	}
 
@@ -386,7 +386,7 @@ namespace Crown
 		public override void update()
 		{
 			Unit unit = new Unit(_level._db, _id, _level._prefabs);
-			_state_machine_resource.text = (string)unit.get_component_property(_component_id, "data.state_machine_resource");
+			_state_machine_resource.text = unit.get_component_property_string(_component_id, "data.state_machine_resource");
 		}
 	}
 
@@ -412,8 +412,10 @@ namespace Crown
 
 		public override void update()
 		{
-			Value? val = _level.get_property(_id, "prefab");
-			_unit_name.text = val == null ? "<none>" : (string)val;
+			if (_level._db.has_property(_id, "prefab"))
+				_unit_name.text = _level._db.get_property_string(_id, "prefab");
+			else
+				_unit_name.text = "<none>";
 		}
 	}
 
@@ -453,8 +455,8 @@ namespace Crown
 
 		public override void update()
 		{
-			Vector3 pos    = (Vector3)   _level.get_property(_id, "position");
-			Quaternion rot = (Quaternion)_level.get_property(_id, "rotation");
+			Vector3 pos    = _level._db.get_property_vector3   (_id, "position");
+			Quaternion rot = _level._db.get_property_quaternion(_id, "rotation");
 
 			_position.value = pos;
 			_rotation.value = rot;
@@ -506,10 +508,10 @@ namespace Crown
 
 		public override void update()
 		{
-			_name.text    = (string)_level.get_property(_id, "name");
-			_range.value  = (double)_level.get_property(_id, "range");
-			_volume.value = (double)_level.get_property(_id, "volume");
-			_loop.value   = (bool)  _level.get_property(_id, "loop");
+			_name.text    = _level._db.get_property_string(_id, "name");
+			_range.value  = _level._db.get_property_double(_id, "range");
+			_volume.value = _level._db.get_property_double(_id, "volume");
+			_loop.value   = _level._db.get_property_bool  (_id, "loop");
 		}
 	}
 

+ 3 - 3
tools/level_editor/resource_browser.vala

@@ -298,15 +298,15 @@ namespace Crown
 			_tree_store.clear();
 
 			Database db = _project.files();
-			HashSet<Guid?> files = db.get_property(GUID_ZERO, "data") as HashSet<Guid?>;
+			HashSet<Guid?> files = db.get_property_set(GUID_ZERO, "data", new Gee.HashSet<Guid?>());
 			files.foreach((id) => {
 				Gtk.TreeIter resource_iter;
 				_tree_store.append(out resource_iter, null);
-				string name = (string)db.get_property(id, "name");
+				string name = db.get_property_string(id, "name");
 				if (name.has_prefix("core/"))
 					return true;
 
-				string type = (string)db.get_property(id, "type");
+				string type = db.get_property_string(id, "type");
 				_tree_store.set(resource_iter, 0, name, 1, type, -1);
 				return true;
 			});

+ 111 - 6
tools/level_editor/unit.vala

@@ -20,7 +20,7 @@ public class Unit
 		_prefabs = prefabs != null ? prefabs : new Database();
 	}
 
-	public Value? get_component_property(Guid component_id, string key)
+	private Value? get_component_property(Guid component_id, string key)
 	{
 		// Search in components
 		{
@@ -56,19 +56,124 @@ public class Unit
 		return null;
 	}
 
-	public void set_component_property(Guid component_id, string key, Value? value)
+	public bool get_component_property_bool(Guid component_id, string key)
+	{
+		return (bool)get_component_property(component_id, key);
+	}
+
+	public double get_component_property_double(Guid component_id, string key)
+	{
+		return (double)get_component_property(component_id, key);
+	}
+
+	public string get_component_property_string(Guid component_id, string key)
+	{
+		return (string)get_component_property(component_id, key);
+	}
+
+	public Guid get_component_property_guid(Guid component_id, string key)
+	{
+		return (Guid)get_component_property(component_id, key);
+	}
+
+	public Vector3 get_component_property_vector3(Guid component_id, string key)
+	{
+		return (Vector3)get_component_property(component_id, key);
+	}
+
+	public Quaternion get_component_property_quaternion(Guid component_id, string key)
+	{
+		return (Quaternion)get_component_property(component_id, key);
+	}
+
+	public void set_component_property_bool(Guid component_id, string key, bool val)
+	{
+		// Search in components
+		{
+			Value? components = _db.get_property(_unit, "components");
+			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
+			{
+				_db.set_property_bool(component_id, key, val);
+				return;
+			}
+		}
+
+		_db.set_property_bool(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
+	}
+
+	public void set_component_property_double(Guid component_id, string key, double val)
+	{
+		// Search in components
+		{
+			Value? components = _db.get_property(_unit, "components");
+			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
+			{
+				_db.set_property_double(component_id, key, val);
+				return;
+			}
+		}
+
+		_db.set_property_double(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
+	}
+
+	public void set_component_property_string(Guid component_id, string key, string val)
+	{
+		// Search in components
+		{
+			Value? components = _db.get_property(_unit, "components");
+			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
+			{
+				_db.set_property_string(component_id, key, val);
+				return;
+			}
+		}
+
+		_db.set_property_string(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
+	}
+
+	public void set_component_property_guid(Guid component_id, string key, Guid val)
+	{
+		// Search in components
+		{
+			Value? components = _db.get_property(_unit, "components");
+			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
+			{
+				_db.set_property_guid(component_id, key, val);
+				return;
+			}
+		}
+
+		_db.set_property_guid(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
+	}
+
+	public void set_component_property_vector3(Guid component_id, string key, Vector3 val)
+	{
+		// Search in components
+		{
+			Value? components = _db.get_property(_unit, "components");
+			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
+			{
+				_db.set_property_vector3(component_id, key, val);
+				return;
+			}
+		}
+
+		_db.set_property_vector3(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
+	}
+
+	public void set_component_property_quaternion(Guid component_id, string key, Quaternion val)
 	{
 		// Search in components
 		{
 			Value? components = _db.get_property(_unit, "components");
 			if (components != null && ((HashSet<Guid?>)components).contains(component_id))
 			{
-				_db.set_property(component_id, key, value);
+				_db.set_property_quaternion(component_id, key, val);
 				return;
 			}
 		}
 
-		_db.set_property(_unit, "modified_components.#" + component_id.to_string() + "." + key, value);
+		_db.set_property_quaternion(_unit, "modified_components.#" + component_id.to_string() + "." + key, val);
 	}
 
 	public static bool has_component_static(Database db, Database prefabs_db, Guid unit_id, string component_type, ref Guid ref_component_id)
@@ -152,14 +257,14 @@ public class Unit
 	/// Returns whether the unit has a prefab.
 	public bool has_prefab()
 	{
-		return _db.get_property(_unit, "prefab") != null;
+		return _db.has_property(_unit, "prefab");
 	}
 
 	/// Returns wheter the unit is a light unit.
 	public bool is_light()
 	{
 		return has_prefab()
-			&& (string)_db.get_property(_unit, "prefab") == "core/units/light";
+			&& _db.get_property_string(_unit, "prefab") == "core/units/light";
 	}
 }