diff --git a/Plugins/GameTelemetry/Editor/EventEditorContainer.cs b/Plugins/GameTelemetry/Editor/EventEditorContainer.cs index aeaeeeb..be685da 100644 --- a/Plugins/GameTelemetry/Editor/EventEditorContainer.cs +++ b/Plugins/GameTelemetry/Editor/EventEditorContainer.cs @@ -26,16 +26,7 @@ namespace GameTelemetry public Vector3 Orientation; public DateTime Time; - public float Value; - private bool isPct; - public bool IsPercentage - { - get - { - return isPct; - } - } - + public Dictionary Values = new Dictionary(); public TelemetryEvent() { @@ -47,16 +38,12 @@ namespace GameTelemetry Point = Vector3.zero; Orientation = Vector3.zero; Time = DateTime.Now; - Value = 0; - isPct = false; } - public TelemetryEvent(string inName, string inCategory, string inSession, string inBuild, string inUser, Vector3 point, DateTime time, float value, bool isPct) + public TelemetryEvent(string inName, string inCategory, string inSession, string inBuild, string inUser, Vector3 point, DateTime time) { this.Point = point; this.Time = time; - this.Value = value; - this.isPct = isPct; Orientation = Vector3.zero; Name = inName; Category = inCategory; @@ -65,19 +52,29 @@ namespace GameTelemetry Build = inBuild; } - public TelemetryEvent(string inName, string inCategory, string inSession, string inBuild, string inUser, Vector3 point, Vector3 orientation, DateTime time, float value, bool isPct) + public TelemetryEvent(string inName, string inCategory, string inSession, string inBuild, string inUser, Vector3 point, Vector3 orientation, DateTime time) { this.Point = point; this.Orientation = orientation; this.Time = time; - this.Value = value; - this.isPct = isPct; Name = inName; Category = inCategory; Session = inSession; User = inUser; Build = inBuild; } + + public double GetValue(string key) + { + double value = 0; + + if (Values.ContainsKey(key)) + { + value = Values[key].f; + } + + return value; + } }; //Wrapper for the event container with draw information @@ -135,15 +132,6 @@ namespace GameTelemetry } } - private bool isPct; - public bool IsPercentage - { - get - { - return isPct; - } - } - public DateTime TimeStart { get @@ -163,15 +151,16 @@ namespace GameTelemetry public string Name; public string Session; public List events; + public HashSet attributeNames; public EventEditorContainer() { shouldDraw = Globals.DefaultDrawSetting; shouldAnimate = false; - isPct = false; color = Color.red; type = (int)PrimitiveType.Sphere; events = new List(); + attributeNames = new HashSet(); } public EventEditorContainer(string Name, int index) : this() @@ -191,23 +180,11 @@ namespace GameTelemetry { Fill(inEvents); Name = inEvents[0].Name; - isPct = events[0].IsPercentage; } } public void AddEvent(QueryEvent newEvent) { - string valueName = ""; - double value = 0; - bool isPct = false; - - //Check for a specified value the event wants to draw - if (newEvent.TryGetString("disp_val", out valueName)) - { - value = newEvent.GetNumber(valueName); - isPct = valueName.StartsWith("pct_"); - } - events.Add(new TelemetryEvent( newEvent.Name, newEvent.Category, @@ -216,9 +193,14 @@ namespace GameTelemetry newEvent.UserId, newEvent.PlayerPosition, newEvent.PlayerDirection, - newEvent.Time, - (float)value, - isPct)); + newEvent.Time)); + + newEvent.GetAttributes(ref events[events.Count - 1].Values); + + foreach (var attr in events[events.Count - 1].Values) + { + attributeNames.Add(attr.Key); + } } //Add an array of query results diff --git a/Plugins/GameTelemetry/Editor/TelemetryEventGameObject.cs b/Plugins/GameTelemetry/Editor/TelemetryEventGameObject.cs index 82bd563..9e8378e 100644 --- a/Plugins/GameTelemetry/Editor/TelemetryEventGameObject.cs +++ b/Plugins/GameTelemetry/Editor/TelemetryEventGameObject.cs @@ -10,6 +10,7 @@ //-------------------------------------------------------------------------------------- using UnityEngine; using System; +using System.Collections.Generic; namespace GameTelemetry { @@ -19,7 +20,7 @@ namespace GameTelemetry public DateTime Time; //Value for an event - public float Value; + public Dictionary Values = new Dictionary(); //Session of the event public string Session; @@ -39,7 +40,7 @@ namespace GameTelemetry public void CopyFrom(EventInfo inEvent) { this.Time = inEvent.Time; - this.Value = inEvent.Value; + this.Values = inEvent.Values; this.Session = inEvent.Session; this.User = inEvent.User; this.Build = inEvent.Build; @@ -145,7 +146,6 @@ namespace GameTelemetry eventInfo = new EventInfo(); eventInfo.Time = inEvent.Time; - eventInfo.Value = inEvent.Value; eventInfo.Session = inEvent.Session; eventInfo.User = inEvent.User; eventInfo.Build = inEvent.Build; @@ -160,6 +160,11 @@ namespace GameTelemetry eventName = $"{eventInfo.Category} {eventInfo.Name}"; + foreach (var value in inEvent.Values) + { + eventInfo.Values.Add(value.Key, value.Value.ToString()); + } + if (index >= 0) { eventName += index; @@ -169,15 +174,15 @@ namespace GameTelemetry } //Populates event values for heatmaps - public void SetHeatmapEvent(int index, Vector3 inPoint, Vector3 inOrientation, Color inColor, PrimitiveType inType, float inScale, float inValue) + public void SetHeatmapEvent(int index, Vector3 inPoint, Vector3 inOrientation, Color inColor, PrimitiveType inType, float inScale, double inValue) { SetHeatmapEvent(index, inPoint, inOrientation, inColor, inType, new Vector3(inScale, inScale, inScale), inValue); } - public void SetHeatmapEvent(int index, Vector3 inPoint, Vector3 inOrientation, Color inColor, PrimitiveType inType, Vector3 inScale, float inValue) + public void SetHeatmapEvent(int index, Vector3 inPoint, Vector3 inOrientation, Color inColor, PrimitiveType inType, Vector3 inScale, double inValue) { eventInfo = new EventInfo(); - eventInfo.Value = inValue; + eventInfo.Values.Add("Value", inValue.ToString()); location = inPoint; orientation = inOrientation; color = inColor; diff --git a/Plugins/GameTelemetry/Editor/TelemetryRenderer.cs b/Plugins/GameTelemetry/Editor/TelemetryRenderer.cs index 08e3913..e721ee9 100644 --- a/Plugins/GameTelemetry/Editor/TelemetryRenderer.cs +++ b/Plugins/GameTelemetry/Editor/TelemetryRenderer.cs @@ -30,8 +30,8 @@ namespace GameTelemetry } } - public float HeatmapValueMin = -1; - public float HeatmapValueMax = -1; + public double HeatmapValueMin = -1; + public double HeatmapValueMax = -1; private List gameObjectCollection = new List(); private bool needsTelemetryObjectUpdate = false; @@ -42,7 +42,7 @@ namespace GameTelemetry } // Master draw call. Updates animation if running, otherwise checks if objects need to be updated - public void Tick(List filterCollection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, ref AnimationController animController) + public void Tick(List filterCollection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, string subEvent, ref AnimationController animController) { if (!animController.IsStopped()) { @@ -81,7 +81,7 @@ namespace GameTelemetry animController.AnimSlider = animController.GetTimeScaleFromTime() * animController.AnimSliderMax; if (start != next) { - GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1); + GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1, subEvent); } } else @@ -108,7 +108,7 @@ namespace GameTelemetry animController.AnimSlider = (1 - animController.GetTimeScaleFromTime()) * animController.AnimSliderMax; if (start != next) { - GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1); + GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1, subEvent); } } else @@ -157,12 +157,12 @@ namespace GameTelemetry } //Generate a heatmap for the range of events - public void GenerateHeatmap(EventEditorContainer collection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation) + public void GenerateHeatmap(EventEditorContainer collection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, string subEvent) { - GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, 0, collection.events.Count - 1); + GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, 0, collection.events.Count - 1, subEvent); } - public void GenerateHeatmap(EventEditorContainer collection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, int first, int last) + public void GenerateHeatmap(EventEditorContainer collection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, int first, int last, string subEvent) { DestroyTelemetryObjects(); @@ -175,209 +175,229 @@ namespace GameTelemetry } //Segment the world in to blocks of the specified size encompassing all points - Bounds range = collection.GetPointRange(first, last); - float extent = heatmapSize / 2; - Vector3 boxSize = new Vector3(heatmapSize, heatmapSize, heatmapSize); - List parts = new List(); + Vector3 origin = collection.GetPointRange(first, last).center; - range.max = new Vector3(range.max.x + heatmapSize, range.max.y + heatmapSize, range.max.z + heatmapSize); + //For each segment, collect all of the points inside and decide what data to watch based on the heatmap type + float scaledHeatmapSize = heatmapSize / 100; + Vector3 tempPoint; + Dictionary heatmapNodes = new Dictionary(); - for (float x = range.min.x + extent; x < range.max.x; x += heatmapSize) + //For each segment, collect all of the points inside and decide what data to watch based on the heatmap type + TelemetryEventGameObject tempTelemetryObject; + + if ((HeatmapValueMin == -1 && HeatmapValueMax == -1) || HeatmapValueMin == HeatmapValueMax) { - for (float y = range.min.y + extent; y < range.max.y; y += heatmapSize) + double largestValue = 0; + double smallestValue = 0; + int largestNumValue = 0; + + if (useOrientation) { - for (float z = range.min.z + extent; z < range.max.z; z += heatmapSize) + for (int j = first; j <= last; j++) { - parts.Add(new Bounds(new Vector3(x, y, z), boxSize)); - } - } - } + tempPoint = (collection.events[j].Point - origin) / heatmapSize; + tempPoint.x = (float)Math.Floor(tempPoint.x); + tempPoint.y = (float)Math.Floor(tempPoint.y); + tempPoint.z = (float)Math.Floor(tempPoint.z); - if (parts.Count > 0) - { - //For each segment, collect all of the points inside and decide what data to watch based on the heatmap type - List numValues = new List(); - List values = new List(); - List orientation = new List(); - TelemetryEventGameObject tempTelemetryObject; + HeatmapNode tempNode; - numValues.AddRange(System.Linq.Enumerable.Repeat(0, parts.Count)); - values.AddRange(System.Linq.Enumerable.Repeat(0, parts.Count)); - orientation.AddRange(System.Linq.Enumerable.Repeat(new Vector3(), parts.Count)); - - if ((HeatmapValueMin == -1 && HeatmapValueMax == -1) || HeatmapValueMin == HeatmapValueMax) - { - float largestValue = 0; - int largestNumValue = 0; - - if (useOrientation) - { - for (int i = 0; i < parts.Count; i++) + if (heatmapNodes.ContainsKey(tempPoint)) { - for (int j = first; j <= last; j++) - { - if (parts[i].Contains(collection.events[j].Point)) - { - numValues[i]++; - orientation[i] += collection.events[j].Orientation; - values[i] += collection.events[j].Value; - } - } - - if (numValues[i] > 0) - { - largestValue = Math.Max(largestValue, values[i] / numValues[i]); - } - - largestNumValue = Math.Max(largestNumValue, numValues[i]); - orientation[i] = orientation[i] / numValues[i]; - } - } - else - { - for (int i = 0; i < parts.Count; i++) - { - for (int j = first; j <= last; j++) - { - if (parts[i].Contains(collection.events[j].Point)) - { - numValues[i]++; - values[i] += collection.events[j].Value; - } - } - - if (numValues[i] > 0) - { - largestValue = Math.Max(largestValue, values[i] / numValues[i]); - } - - largestNumValue = Math.Max(largestNumValue, numValues[i]); - } - } - - HeatmapValueMin = 0; - - if (heatmapType == (int)Globals.HeatmapType.Value || heatmapType == (int)Globals.HeatmapType.Value_Bar) - { - if (collection.IsPercentage) - { - HeatmapValueMax = 100; + heatmapNodes[tempPoint].numValues++; + heatmapNodes[tempPoint].values += collection.events[j].GetValue(subEvent); + heatmapNodes[tempPoint].orientation += collection.events[j].Orientation; + tempNode = heatmapNodes[tempPoint]; } else { - HeatmapValueMax = largestValue; + tempNode = new HeatmapNode(1, collection.events[j].GetValue(subEvent), collection.events[j].Orientation); + heatmapNodes.Add(tempPoint, tempNode); } + + smallestValue = Math.Min(smallestValue, tempNode.values / tempNode.numValues); + largestValue = Math.Max(largestValue, tempNode.values / tempNode.numValues); + largestNumValue = Math.Max(largestNumValue, tempNode.numValues); } - else + + foreach (var node in heatmapNodes) { - HeatmapValueMax = largestNumValue; + node.Value.orientation = node.Value.orientation / node.Value.numValues; } } else { - if (useOrientation) + for (int j = first; j <= last; j++) { - for (int i = 0; i < parts.Count; i++) - { - for (int j = first; j <= last; j++) - { - if (parts[i].Contains(collection.events[j].Point)) - { - numValues[i]++; - orientation[i] += collection.events[j].Orientation; - values[i] += collection.events[j].Value; - } - } + tempPoint = (collection.events[j].Point - origin) / heatmapSize; + tempPoint.x = (float)Math.Floor(tempPoint.x); + tempPoint.y = (float)Math.Floor(tempPoint.y); + tempPoint.z = (float)Math.Floor(tempPoint.z); - orientation[i] = orientation[i] / numValues[i]; - } - } - else - { - for (int i = 0; i < parts.Count; i++) + HeatmapNode tempNode; + + if (heatmapNodes.ContainsKey(tempPoint)) { - for (int j = first; j <= last; j++) - { - if (parts[i].Contains(collection.events[j].Point)) - { - numValues[i]++; - values[i] += collection.events[j].Value; - } - } + heatmapNodes[tempPoint].numValues++; + heatmapNodes[tempPoint].values += collection.events[j].GetValue(subEvent); + tempNode = heatmapNodes[tempPoint]; } + else + { + tempNode = new HeatmapNode(1, collection.events[j].GetValue(subEvent)); + heatmapNodes.Add(tempPoint, tempNode); + } + + smallestValue = Math.Min(smallestValue, tempNode.values / tempNode.numValues); + largestValue = Math.Max(largestValue, tempNode.values / tempNode.numValues); + largestNumValue = Math.Max(largestNumValue, tempNode.numValues); } } + HeatmapValueMin = 0; + + if (heatmapType == (int)Globals.HeatmapType.Value || heatmapType == (int)Globals.HeatmapType.Value_Bar) + { + if (subEvent.StartsWith("pct_")) + { + HeatmapValueMin = 0; + HeatmapValueMax = 100; + } + else + { + HeatmapValueMin = smallestValue; + HeatmapValueMax = largestValue; + } + } + else + { + HeatmapValueMax = largestNumValue; + } + } + else + { + if (useOrientation) + { + for (int j = first; j <= last; j++) + { + tempPoint = (collection.events[j].Point - origin) / heatmapSize; + tempPoint.x = (float)Math.Floor(tempPoint.x); + tempPoint.y = (float)Math.Floor(tempPoint.y); + tempPoint.z = (float)Math.Floor(tempPoint.z); + + HeatmapNode tempNode; + + if (heatmapNodes.ContainsKey(tempPoint)) + { + heatmapNodes[tempPoint].numValues++; + heatmapNodes[tempPoint].values += collection.events[j].GetValue(subEvent); + heatmapNodes[tempPoint].orientation += collection.events[j].Orientation; + tempNode = heatmapNodes[tempPoint]; + } + else + { + tempNode = new HeatmapNode(1, collection.events[j].GetValue(subEvent), collection.events[j].Orientation); + heatmapNodes.Add(tempPoint, tempNode); + } + } + + foreach (var node in heatmapNodes) + { + node.Value.orientation = node.Value.orientation / node.Value.numValues; + } + } + else + { + for (int j = first; j <= last; j++) + { + tempPoint = (collection.events[j].Point - origin) / heatmapSize; + tempPoint.x = (float)Math.Floor(tempPoint.x); + tempPoint.y = (float)Math.Floor(tempPoint.y); + tempPoint.z = (float)Math.Floor(tempPoint.z); + + HeatmapNode tempNode; + + if (heatmapNodes.ContainsKey(tempPoint)) + { + heatmapNodes[tempPoint].numValues++; + heatmapNodes[tempPoint].values += collection.events[j].GetValue(subEvent); + tempNode = heatmapNodes[tempPoint]; + } + else + { + tempNode = new HeatmapNode(1, collection.events[j].GetValue(subEvent)); + heatmapNodes.Add(tempPoint, tempNode); + } + } + } + } + + if (heatmapNodes.Count > 0) + { + double tempValue; float tempColorValue; + int i = 0; if (heatmapType == (int)Globals.HeatmapType.Value) { - for (int i = 0; i < parts.Count; i++) + foreach (var node in heatmapNodes) { - if (values[i] > 0) - { - tempColorValue = (((float)values[i] / numValues[i]) - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin); - tempColorValue = Math.Max(tempColorValue, 0); - tempColorValue = Math.Min(tempColorValue, 1); + tempValue = node.Value.values / node.Value.numValues; + tempColorValue = (float)((tempValue - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); + tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); - tempTelemetryObject = new TelemetryEventGameObject(); - tempTelemetryObject.SetHeatmapEvent(i, parts[i].center, orientation[i], heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, heatmapSize, values[i] / numValues[i]); - CreateHeatmapObject(tempTelemetryObject); - } + tempTelemetryObject = new TelemetryEventGameObject(); + tempTelemetryObject.SetHeatmapEvent(i, (node.Key * heatmapSize) + origin, node.Value.orientation, heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, heatmapSize, tempValue); + CreateHeatmapObject(tempTelemetryObject); + i++; } } else if (heatmapType == (int)Globals.HeatmapType.Population) { - for (int i = 0; i < parts.Count; i++) + foreach (var node in heatmapNodes) { - if (numValues[i] > 0) - { - tempColorValue = (float)(numValues[i] - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin); - tempColorValue = Math.Max(tempColorValue, 0); - tempColorValue = Math.Min(tempColorValue, 1); + tempValue = node.Value.values / HeatmapValueMax; + tempColorValue = (float)((tempValue - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); + tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); - tempTelemetryObject = new TelemetryEventGameObject(); - tempTelemetryObject.SetHeatmapEvent(i, parts[i].center, orientation[i], heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, heatmapSize, numValues[i]); - CreateHeatmapObject(tempTelemetryObject); - } + tempTelemetryObject = new TelemetryEventGameObject(); + tempTelemetryObject.SetHeatmapEvent(i, (node.Key * heatmapSize) + origin, node.Value.orientation, heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, heatmapSize, tempValue); + CreateHeatmapObject(tempTelemetryObject); + i++; } } else if (heatmapType == (int)Globals.HeatmapType.Value_Bar) { float tempHeight; - for (int i = 0; i < parts.Count; i++) + foreach (var node in heatmapNodes) { - if (values[i] > 0) - { - tempColorValue = (((float)values[i] / numValues[i]) - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin); - tempColorValue = Math.Max(tempColorValue, 0); - tempColorValue = Math.Min(tempColorValue, 1); - tempHeight = (((float)values[i] / numValues[i]) / HeatmapValueMax) * heatmapSize; + tempValue = node.Value.values / node.Value.numValues; + tempColorValue = (float)((tempValue - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); + tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); + tempHeight = (float)(tempValue / HeatmapValueMax) * heatmapSize; - tempTelemetryObject = new TelemetryEventGameObject(); - tempTelemetryObject.SetHeatmapEvent(i, parts[i].center, Vector3.zero, heatmapColor.GetColorFromRange(tempColorValue), PrimitiveType.Cube, new Vector3(heatmapSize, heatmapSize, tempHeight), values[i] / numValues[i]); - CreateHeatmapObject(tempTelemetryObject); - } + tempTelemetryObject = new TelemetryEventGameObject(); + tempTelemetryObject.SetHeatmapEvent(i, (node.Key * heatmapSize) + origin, Vector3.zero, heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, new Vector3(heatmapSize, heatmapSize, tempHeight), tempValue); + CreateHeatmapObject(tempTelemetryObject); + i++; } } else if (heatmapType == (int)Globals.HeatmapType.Population_Bar) { float tempHeight; - for (int i = 0; i < parts.Count; i++) + foreach (var node in heatmapNodes) { - if (numValues[i] > 0) - { - tempColorValue = (float)(numValues[i] - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin); - tempColorValue = Math.Max(tempColorValue, 0); - tempColorValue = Math.Min(tempColorValue, 1); - tempHeight = ((float)numValues[i] / HeatmapValueMax) * heatmapSize; + tempValue = node.Value.values / HeatmapValueMax; + tempColorValue = (float)((tempValue - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); + tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); + tempHeight = (float)tempValue * heatmapSize; - tempTelemetryObject = new TelemetryEventGameObject(); - tempTelemetryObject.SetHeatmapEvent(i, parts[i].center, Vector3.zero, heatmapColor.GetColorFromRange(tempColorValue), PrimitiveType.Cube, new Vector3(heatmapSize, heatmapSize, tempHeight), numValues[i]); - CreateHeatmapObject(tempTelemetryObject); - } + tempTelemetryObject = new TelemetryEventGameObject(); + tempTelemetryObject.SetHeatmapEvent(i, (node.Key * heatmapSize) + origin, Vector3.zero, heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, new Vector3(heatmapSize, heatmapSize, tempHeight), tempValue); + CreateHeatmapObject(tempTelemetryObject); + i++; } } } diff --git a/Plugins/GameTelemetry/Editor/TelemetryVisualizerTypes.cs b/Plugins/GameTelemetry/Editor/TelemetryVisualizerTypes.cs index bcec927..f72d468 100644 --- a/Plugins/GameTelemetry/Editor/TelemetryVisualizerTypes.cs +++ b/Plugins/GameTelemetry/Editor/TelemetryVisualizerTypes.cs @@ -195,6 +195,34 @@ namespace GameTelemetry } }; + //Nodes used when preparing a heatmap + public class HeatmapNode + { + public int numValues; + public double values; + public Vector3 orientation; + + public HeatmapNode() + { + numValues = 0; + values = 0; + orientation = Vector3.zero; + } + public HeatmapNode(int inNumVals, double inValues) + { + numValues = inNumVals; + values = inValues; + orientation = Vector3.zero; + } + + public HeatmapNode(int inNumVals, double inValues, Vector3 inOrientation) + { + numValues = 0; + values = 0; + orientation = inOrientation; + } + }; + //Container for each UI line of the query public class QuerySetting { diff --git a/Plugins/GameTelemetry/Editor/TelemetryVisualizerUI.cs b/Plugins/GameTelemetry/Editor/TelemetryVisualizerUI.cs index f20c248..7aa4fc5 100644 --- a/Plugins/GameTelemetry/Editor/TelemetryVisualizerUI.cs +++ b/Plugins/GameTelemetry/Editor/TelemetryVisualizerUI.cs @@ -49,6 +49,8 @@ namespace GameTelemetry private AnimationController animController = new AnimationController(); //Heatmap + private int vizSubSelectedEvent; + private List subEventNames = new List(); private int heatmapType = 0; private int heatmapShape = 3; private HeatmapColors heatmapColor = new HeatmapColors(); @@ -74,7 +76,14 @@ namespace GameTelemetry private void Update() { - renderer.Tick(filterCollection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, ref animController); + if(subEventNames.Count > vizSubSelectedEvent && vizSubSelectedEvent > -1) + { + renderer.Tick(filterCollection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, subEventNames[vizSubSelectedEvent], ref animController); + } + else + { + renderer.Tick(filterCollection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, "", ref animController); + } } void OnGUI() @@ -169,11 +178,12 @@ namespace GameTelemetry { vizSelectedEvent = currSelectedEvent; - for(int i = 0; i < queryEventCollection.Count; i++) + for (int i = 0; i < queryEventCollection.Count; i++) { if (queryEventCollection[i].Name == eventNames[vizSelectedEvent]) { animController.EventContainer = queryEventCollection[i]; + subEventNames = new List(queryEventCollection[i].attributeNames); break; } } @@ -264,6 +274,21 @@ namespace GameTelemetry GUILayout.Space(heatmapGap); + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(marginSize); + EditorGUILayout.LabelField("Value", GUILayout.Width(textWidth)); + int currSelectedSubEvent = EditorGUILayout.Popup("", vizSubSelectedEvent, subEventNames.ToArray()); + if (vizSubSelectedEvent != currSelectedSubEvent) + { + vizSubSelectedEvent = currSelectedSubEvent; + renderer.HeatmapValueMin = -1; + renderer.HeatmapValueMax = -1; + } + GUILayout.Space(marginSize); + EditorGUILayout.EndHorizontal(); + + GUILayout.Space(heatmapGap); + EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Type", GUILayout.Width(textWidth)); @@ -313,9 +338,9 @@ namespace GameTelemetry EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Value Range", GUILayout.Width(textWidth)); - renderer.HeatmapValueMin = EditorGUILayout.FloatField(renderer.HeatmapValueMin); + renderer.HeatmapValueMin = EditorGUILayout.DoubleField(renderer.HeatmapValueMin); GUILayout.Space(marginSize); - renderer.HeatmapValueMax = EditorGUILayout.FloatField(renderer.HeatmapValueMax); + renderer.HeatmapValueMax = EditorGUILayout.DoubleField(renderer.HeatmapValueMax); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); @@ -362,7 +387,7 @@ namespace GameTelemetry } } - renderer.GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation); + renderer.GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, subEventNames[vizSubSelectedEvent]); } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); @@ -523,6 +548,7 @@ namespace GameTelemetry { queryEventCollection.Clear(); eventNames.Clear(); + subEventNames.Clear(); string currentName; @@ -555,6 +581,7 @@ namespace GameTelemetry } vizSelectedEvent = -1; + vizSubSelectedEvent = -1; searchFolddown = true; FilterEvents(); diff --git a/Plugins/GameTelemetry/QueryEvents.cs b/Plugins/GameTelemetry/QueryEvents.cs index ffc890b..75d4266 100644 --- a/Plugins/GameTelemetry/QueryEvents.cs +++ b/Plugins/GameTelemetry/QueryEvents.cs @@ -186,6 +186,17 @@ namespace GameTelemetry return ev; } + public void GetAttributes(ref Dictionary inMap) + { + foreach (var attr in Attributes) + { + if (attr.Key.StartsWith("pct_") || attr.Key.StartsWith("val_")) + { + inMap.Add(attr.Key, attr.Value); + } + } + } + public bool TryGetString(string name, out string outString) { if(Attributes.ContainsKey(name)) diff --git a/Plugins/GameTelemetry/Telemetry.cs b/Plugins/GameTelemetry/Telemetry.cs index 9323cce..9f0c5c7 100644 --- a/Plugins/GameTelemetry/Telemetry.cs +++ b/Plugins/GameTelemetry/Telemetry.cs @@ -73,12 +73,6 @@ namespace GameTelemetry return new TelemetryProperty("dir", vec); } - // The name of the value the visualizer will use - public static TelemetryProperty DisplayValue(string value) - { - return new TelemetryProperty("disp_val", value); - } - // Timestamp of the event using the client's clock by default public static TelemetryProperty ClientTimestamp() { return new TelemetryProperty("client_ts", System.DateTime.UtcNow);