VR Development Framework
v 1.0.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
AVR_Logger.cs
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using System.Reflection;
5 using System.IO;
6 #if UNITY_EDITOR
7 using UnityEditor;
8 #endif
9 
10 // TODO: Documentation is very scarce for a reasonably complex component such as this.
11 
12 namespace AVR.Core {
13  /// <summary>
14  /// Generic datalogger that logs any given variables or object properties in a csv-like format.
15  /// </summary>
16  [AVR.Core.Attributes.DocumentationUrl("class_a_v_r_1_1_core_1_1_a_v_r___logger.html")]
17  public class AVR_Logger : AVR_Behaviour
18  {
19  public string filepath = "logs/sample.log";
20  public string delimeter = ";";
21 
22  public bool manualLog = false;
23 
24  public enum deltaTypes {ON_UPDATE, ON_FIXEDUPDATE, ON_LATEUPDATE, CUSTOM}
25 
27  public deltaTypes deltaType;
29  public float delta = 0.05f;
30 
31  private float stime = 0.0f;
32 
33  [System.Serializable]
34  public class DataSource {
35  public enum ValueTypes {CUSTOM, TIME};
36  public enum ReadTypes {AUTO, HIGH_ACCURACY_NUMERAL, HIGH_ACCURACY_VECTOR3};
37 
38  public string label;
39  public MonoBehaviour target;
40  public string field;
43  }
44 
45  [SerializeField]
46  public List<DataSource> columns = new List<DataSource>();
47 
48  private StreamWriter file;
49 
50  void Update() {
51  if(manualLog) return;
52 
53  if(deltaType==deltaTypes.ON_UPDATE) logObjects();
54  else if(deltaType == deltaTypes.CUSTOM && Time.time >= stime + delta - 0.005f) { //0.005f is a small epsilon to account for small framerates
55  logObjects();
56  stime = Time.time;
57  }
58  }
59 
60  void FixedUpdate() {
61  if (deltaType == deltaTypes.ON_FIXEDUPDATE) logObjects();
62  }
63 
64  void LateUpdate() {
65  if (deltaType == deltaTypes.ON_LATEUPDATE) logObjects();
66  }
67 
68  public override void OnDestroy() {
69  if(file!=null) file.Close();
70  }
71 
72  void Start() {
73  init();
74  }
75 
76  public void logObjects() {
77  string o = "";
78  foreach(DataSource c in columns) {
79  o += getData(c) + delimeter;
80  }
81  file.WriteLine(o);
82  }
83 
84  void init() {
85  string folder = new FileInfo(filepath).Directory.FullName;
86  var dir = Directory.CreateDirectory(folder);
87  file = File.CreateText(filepath);
88  string header = "";
89  foreach(DataSource c in columns) {
90  header += c.label + delimeter;
91  }
92  file.WriteLine(header);
93  }
94 
95  string getData(DataSource src) {
96  switch(src.valueType) {
97  case DataSource.ValueTypes.TIME : {
98  return Time.time.ToString();
99  }
100  default : {
101  var data = getPropertyValue(src.target, src.field);
102 
103  switch(src.readType) {
104  case DataSource.ReadTypes.HIGH_ACCURACY_NUMERAL : {
105  return ((float) data).ToString();
106  }
107  case DataSource.ReadTypes.HIGH_ACCURACY_VECTOR3:
108  {
109  Vector3 v = (Vector3) data;
110  return "("+v.x.ToString()+"f, "+v.y.ToString()+"f, "+v.z.ToString()+"f)";
111  }
112  }
113 
114  if(data==null) return "null";
115  return data.ToString();
116  }
117  }
118  }
119 
120  object getPropertyValue(object target, string field) {
121  if (target == null || field==null) return null;
122 
123  if (field.Contains("."))//complex type nested
124  {
125  var temp = field.Split(new char[] { '.' }, 2);
126  return getPropertyValue(getPropertyValue(target, temp[0]), temp[1]);
127  }
128  else
129  {
130  // Return field or proprty depending on which one it is
131  // NOTE: use "GetProperty(field, System.Reflection.BindingFlags.NonPublic)" for non-public fields.
132  BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Default | BindingFlags.GetField | BindingFlags.GetProperty;
133  try {
134  return target.GetType().GetProperty(field, flags).GetValue(target, null);
135  }
136  catch(System.Exception) {
137  return target.GetType().GetField(field, flags).GetValue(target);
138  }
139  }
140  }
141  }
142 
143 #if UNITY_EDITOR
144  [CustomPropertyDrawer(typeof(AVR_Logger.DataSource))]
145  public class LookAtPointEditor : PropertyDrawer
146  {
147  public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
148  {
149  if(property.FindPropertyRelative("valueType").intValue == (int)AVR_Logger.DataSource.ValueTypes.CUSTOM) {
150  return 100; // We need 2 lines for custom ones
151  }
152  return 30;
153  }
154 
155  public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
156  {
157  EditorGUI.BeginProperty(position, label, property);
158 
159  EditorGUIUtility.labelWidth = 50;
160  EditorGUI.PropertyField(new Rect(position.x+0, position.y, 200, 20), property.FindPropertyRelative("label"), new GUIContent("Label:", "Header given to the value in the logged table"));
161  EditorGUI.PropertyField(new Rect(position.x+200, position.y, 140, 20), property.FindPropertyRelative("valueType"), new GUIContent("Type:", "Type of value logged."));
162 
163  if(property.FindPropertyRelative("valueType").intValue == (int)AVR_Logger.DataSource.ValueTypes.CUSTOM) {
164  EditorGUIUtility.labelWidth = 80;
165  EditorGUI.PropertyField(new Rect(position.x + 20, position.y+20, 320, 20), property.FindPropertyRelative("target"), new GUIContent("Target:", "Target Monobehavior."));
166  EditorGUI.PropertyField(new Rect(position.x + 20, position.y+40, 320, 20), property.FindPropertyRelative("field"), new GUIContent("Field:", "Field or Property of the target that will be logged."));
167  EditorGUI.PropertyField(new Rect(position.x + 20, position.y+60, 320, 20), property.FindPropertyRelative("readType"), new GUIContent("ReadType:", "How we log the data extracted from the field."));
168  }
169 
170  EditorGUI.EndProperty();
171  }
172  }
173 #endif
174 }
Monobehaviour but with an added URL button to a documentation page.
override void OnDestroy()
Definition: AVR_Logger.cs:68
StreamWriter file
Definition: AVR_Logger.cs:48
Sets the documentation html file inside of Packages/com.avr.core/Documentation/html of a given class...
string getData(DataSource src)
Definition: AVR_Logger.cs:95
Generic datalogger that logs any given variables or object properties in a csv-like format...
Definition: AVR_Logger.cs:17
Allows for simple hiding of properties in the UnityEditor depending on certain conditions. For instance, in the following example the "type" field will only be displayed in the inspector if the "tracking" field is set to true:
object getPropertyValue(object target, string field)
Definition: AVR_Logger.cs:120