march 30, 2018 - *NEW* CONVERTIBLE and transformable types
Convertible Types: Prior to the change, your domain model could only have primitive types that were supported directly by the database. In the new version, whenever the attribute uses the stereotype "convert", we generate a converter. Your job is to convert the field into a string field so that it can be stored in the database, and provide a converter back from a string into the internal type.
The converters are then placed into the partial static Factory that you create:
namespace Assets.Data.Utility {
public static partial class Factory {
public static string ConvertVector2ToString(Vector2 aVector2) {
return aVector2.x + "," + aVector2.y;
}
public static Vector2 ConvertStringToVector2(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Vector2(Convert.ToSingle(PARTS[0]), Convert.ToSingle(PARTS[1]));
}
public static string ConvertVector3ToString(Vector3 aVector3) {
return aVector3.x + "," + aVector3.y + "," + aVector3.z;
}
public static Vector3 ConvertStringToVector3(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Vector3(Convert.ToSingle(PARTS[0])
, Convert.ToSingle(PARTS[1])
, Convert.ToSingle(PARTS[2]));
}
public static string ConvertQuaternionToString(Quaternion aQuaternion) {
return aQuaternion.x + "," + aQuaternion.y + "," + aQuaternion.z + "," + aQuaternion.w;
}
public static Quaternion ConvertStringToQuaternion(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Quaternion( Convert.ToSingle(PARTS[0])
, Convert.ToSingle(PARTS[1])
, Convert.ToSingle(PARTS[2])
, Convert.ToSingle(PARTS[3]) );
}
}
}
The code shown above shows how to convert a Vector2, Vector3 and Quaternion to and from a string. When the string is defined in the table, it's given an unlimited size, so any string up to 1Gb can be used. This allows the class domain to reference the full type while saving the data as a string. We also added "Using" tagged values so that the proper using statements are generated for the extra types you may want to define.
The converters are then placed into the partial static Factory that you create:
namespace Assets.Data.Utility {
public static partial class Factory {
public static string ConvertVector2ToString(Vector2 aVector2) {
return aVector2.x + "," + aVector2.y;
}
public static Vector2 ConvertStringToVector2(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Vector2(Convert.ToSingle(PARTS[0]), Convert.ToSingle(PARTS[1]));
}
public static string ConvertVector3ToString(Vector3 aVector3) {
return aVector3.x + "," + aVector3.y + "," + aVector3.z;
}
public static Vector3 ConvertStringToVector3(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Vector3(Convert.ToSingle(PARTS[0])
, Convert.ToSingle(PARTS[1])
, Convert.ToSingle(PARTS[2]));
}
public static string ConvertQuaternionToString(Quaternion aQuaternion) {
return aQuaternion.x + "," + aQuaternion.y + "," + aQuaternion.z + "," + aQuaternion.w;
}
public static Quaternion ConvertStringToQuaternion(string aString) {
string[] PARTS = aString.Split(",".ToCharArray());
return new Quaternion( Convert.ToSingle(PARTS[0])
, Convert.ToSingle(PARTS[1])
, Convert.ToSingle(PARTS[2])
, Convert.ToSingle(PARTS[3]) );
}
}
}
The code shown above shows how to convert a Vector2, Vector3 and Quaternion to and from a string. When the string is defined in the table, it's given an unlimited size, so any string up to 1Gb can be used. This allows the class domain to reference the full type while saving the data as a string. We also added "Using" tagged values so that the proper using statements are generated for the extra types you may want to define.

Transformable Types. Prior to the change, attributes where auto generated based on the type, code like this:
/// <summary>
/// Angle the ship is pointed.
/// </summary>
public Quaternion Rotation {
get { return _Rotation; }
set {
if ( _Rotation != value ) {
_Rotation = value;
IsDirty = true;
}
}
}
protected Quaternion _Rotation;
When the attribute contains the "transform" stereotype, this code is not generated, and it becomes the responsibility of the Developer to create their own transformation in their implementation of the partial class.
Important Note: During this change we did try to implement a MonoBehaviour interface so that database instances could be directly assigned to components on Game Objects. However, Unity does not support this ability. At best you can say gameObject.AddComponent<Ship>() ... but it returns it's own instance. Our framework create's it's own instance as well, and there isn't a way to tie the two together.
/// <summary>
/// Angle the ship is pointed.
/// </summary>
public Quaternion Rotation {
get { return _Rotation; }
set {
if ( _Rotation != value ) {
_Rotation = value;
IsDirty = true;
}
}
}
protected Quaternion _Rotation;
When the attribute contains the "transform" stereotype, this code is not generated, and it becomes the responsibility of the Developer to create their own transformation in their implementation of the partial class.
Important Note: During this change we did try to implement a MonoBehaviour interface so that database instances could be directly assigned to components on Game Objects. However, Unity does not support this ability. At best you can say gameObject.AddComponent<Ship>() ... but it returns it's own instance. Our framework create's it's own instance as well, and there isn't a way to tie the two together.
March 29, 2018 - *new* string multiplicity support
We now use an attributes multiplicity for string fields to identify the string field length. This does not break existing code, but does allow for two different ways to specify strings.
March 29, 2018 - *NEW* object association parent management
Changed the Master references to automatically unload the child from the original parent and assign it to the new parent's child list. The code shown below is the change.
public SolarSystem TheSolarSystem {
get { return _TheSolarSystem.Value; }
set {
if ( _TheSolarSystem.Value != value ) {
// Remove the reference of this instance in the original parent's list
if ( _TheSolarSystem.Value != null )
_TheSolarSystem.Value.Ships.Remove( this ) // Ignored if not present or loaded
_TheSolarSystem.Value = value;
// Add this to the new parent's list
if ( _TheSolarSystem.Value != null )
_TheSolarSystem.Value.Ships.Add( this );
IsDirty = true;
}
}
}
get { return _TheSolarSystem.Value; }
set {
if ( _TheSolarSystem.Value != value ) {
// Remove the reference of this instance in the original parent's list
if ( _TheSolarSystem.Value != null )
_TheSolarSystem.Value.Ships.Remove( this ) // Ignored if not present or loaded
_TheSolarSystem.Value = value;
// Add this to the new parent's list
if ( _TheSolarSystem.Value != null )
_TheSolarSystem.Value.Ships.Add( this );
IsDirty = true;
}
}
}
This allows code to simply reassign the parent to update all of the references properly.