Skip to content

Guide 403: Custom SmartType Templates

Dr Luke Thompson edited this page Oct 28, 2018 · 2 revisions

The generation tool creates multiple classes for each SmartType. For example, SmartFloat includes, amongst others:

  • FloatVar (SmartObject)
  • FloatReader / FloatWriter (SmartRefs)
  • WriteSmartFloat / ReadSmartFloat (SmartComponents)
  • ...

In many cases you may want to create additional classes on top of these, but it would be tedious and error-prone to manually code them, even with a generic base class to inherit from. For example, creating a network replication decorator for each SmartType. The generation tool supports custom templates to make this as simple as possible.

This will look complex - but once you've done it once it's not so bad!

Writing a custom SmartType template

Templates are .txt files with format tags for the generator to insert type names and other information. Their contents are used as the first argument for string.Format with the other arguments representing the underlying data type. The resulting string is saved to a .cs file by the tool.

SmartData's built-in generated types are created using the exact same system. The templates are found in *SmartData/Editor/Resources.

A template file should therefore look largely like a C# script file, with a few differences. Here's an example.

using UnityEngine;
namespace MySmartTypes.Smart{1} {{
	public class MySmart{1}Class : MySmartBaseClass<{0}> {{
		[SerializeField]
		{0} _myData;
		
		public string myPrettyTypeName {{
			get {{ return "Smart {2}"; }}
		}}
	}}
}}

For an underlying type of List<float>, this would result in the following output file:

using UnityEngine;
namespace MySmartTypes.SmartList_Float {
	public class MySmartList_FloatClass : MySmartBaseClass<List<float>> {
		[SerializeField]
		List<float> _myData;
		
		public string myPrettyTypeName {
			get { return "Smart List<float>"; }
		}
	}
}

Format Rules

  • Any { or } in the final output must be {{ or }} in the template.
    • Single braces are understood by string.Format() to mean a replacement tag. Those not followed by an integer will cause a FormatException.
  • To use the underlying type as understood by C# insert {0}.
    • This is the type name including namespace.
  • To insert a "pretty" version of that type name which is still safe for C# insert {1}.
    • This is the type name without namespace, capitalized, and with any unsafe characters such as < removed.
  • To insert a capitalized version of that type name within a string only insert {2}.
    • This is the type name without namespace, capitalized, without unsafe characters removed.

In the case of List<float>

  • {0} is "List"
  • {1} is "List_float"
  • {2} is "List"

In the case of float[]

  • {0} is "float[]"
  • {1} is "FloatArray"
  • {2} is "Float[]"

{1} is created by SmartTypeCreator.PrettyTypeName() and {2} is created by SmartTypeCreator.Capitalize().

The generation tool has a summary of these rules, shown by clicking the book icon next to Advanced > Custom Templates.

Adding Custom Templates to the Generator

Custom templates should be saved as .txt files in your project. They must be within a Resources folder. The top and bottom levels of this folder structure can be arbitrary. The tool uses Resources.Load() to find templates so the same rules apply.

It's recommended for the relevant Resources folder to be within an Editor folder to exclude templates from builds. However this is not critical.

For example:

  • Assets/Editor/Resources/MySmartTemplate.txt
  • Assets/MyFolder/Resources/MyOtherFolder/AnotherTemplateFile.txt
  • Assets/Resources/YetAnotherTemplate.txt are all fine.

To add your template(s), launch the generator tool and fold out the Advanced > Custom Templates section. This is an array of structs, so increment the count. This will cause an error message - this is expected. The tool will display this until the entry is valid.

The template file field is just the name of the template - no path, no .txt extension. Resources.Load() will find the file.

The Output File field is the pattern for the generated C# script filename, with no path or .cs extension. It must include the {0} tag - this will be replaced by the C#-safe capitalized underlying type name. This corresponds to the {1} tag within templates.

In this instance, an underlying type of float will create a C# script file called MySmartFloatClass.cs.

If your class inherits from MonoBehaviour or ScriptableObject, the generated filename must match the class name, as with normal Unity classes.

Generating your Custom Classes

Now, any time you use the tool's Create or Regenerate functionality, your templates will be included in the generation process. Regenerating will create these new classes for your existing SmartTypes. See Guide 401: Generating Custom SmartTypes and Guide 402: Regenerating SmartTypes for more.