public AnimationController(EventEditorContainer newContainer) { state = Globals.TelemetryAnimationState.Stopped; playSpeed = 0; nextIndexDraw = 0; needRefresh = true; eventContainer = newContainer; }
void OnGUI() { GUILayout.Space(10); //Query section EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(1)), lineColor); queryFolddown = EditorGUILayout.Foldout(queryFolddown, "Event Settings"); if (queryFolddown) { //GUILayout.Label("Create clauses to define what events are retrieved from the server. The local results are filtered in the search area", EditorStyles.wordWrappedLabel); EditorGUILayout.HelpBox("Create clauses to define what events are retrieved from the server. The local results are filtered in the search area", MessageType.Info); GenerateClauseList(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("+ Add New Clause")) { AddClause(-1); } if (isWaiting) { GUILayout.Button("Running..."); } else { if (GUILayout.Button("Submit")) { SubmitQuery(); } } EditorGUILayout.EndHorizontal(); } //Search section EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(1)), lineColor); searchFolddown = EditorGUILayout.Foldout(searchFolddown, "Event Search"); if (searchFolddown) { EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize * 2); searchText = EditorGUILayout.TextField("", searchText); if (GUILayout.Button("Search", GUILayout.Width(80))) { FilterEvents(); } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize * 2); GUILayout.Label(eventCount, EditorStyles.label); EditorGUILayout.EndHorizontal(); GenerateEventGroup(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize * 2); if (GUILayout.Button("Select All")) { for (int i = 0; i < filterCollection.Count; i++) { filterCollection[i].ShouldDraw = true; } } if (GUILayout.Button("Select None")) { for (int i = 0; i < filterCollection.Count; i++) { filterCollection[i].ShouldDraw = false; } } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); } //Viz tools section EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(1)), lineColor); vizFolddown = EditorGUILayout.Foldout(vizFolddown, "Visualization Tools"); if (vizFolddown) { GUILayout.Space(10); //Event group selection EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Event Type", GUILayout.Width(textWidth)); int currSelectedEvent = EditorGUILayout.Popup("", vizSelectedEvent, eventNames.ToArray()); if (vizSelectedEvent != currSelectedEvent) { vizSelectedEvent = currSelectedEvent; for (int i = 0; i < queryEventCollection.Count; i++) { if (queryEventCollection[i].Name == eventNames[vizSelectedEvent]) { animController.EventContainer = queryEventCollection[i]; subEventNames = new List <string>(queryEventCollection[i].attributeNames); break; } } TimeSpan tempSpan = animController.GetTimespan(); if (tempSpan.Seconds >= 10) { animMaxTime = $"{(int)tempSpan.TotalMinutes}:{tempSpan.Seconds}"; } else { animMaxTime = $"{(int)tempSpan.TotalMinutes}:0{tempSpan.Seconds}"; } animController.AnimSliderMax = (float)tempSpan.TotalSeconds; renderer.HeatmapValueMin = -1; renderer.HeatmapValueMax = -1; } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(10); //Animation EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); float newSlider = GUILayout.HorizontalSlider(animController.AnimSlider, 0, animController.AnimSliderMax); if (animController.AnimSlider != newSlider) { animController.AnimSlider = newSlider; if (animController.IsReady()) { animController.SetPlaybackTime(animController.AnimSlider / animController.AnimSliderMax); } } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); EditorGUILayout.LabelField("0:00"); GUIStyle rightAlign = new GUIStyle(GUI.skin.label); rightAlign.alignment = TextAnchor.MiddleRight; EditorGUILayout.LabelField(animMaxTime, rightAlign); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); if (GUILayout.Button("<<<")) { if (animController.IsReady()) { PlayAnimation(-4); } } if (GUILayout.Button("<<")) { if (animController.IsReady()) { PlayAnimation(-2); } } if (GUILayout.Button("||")) { if (animController.IsReady()) { PlayAnimation(0); } } if (GUILayout.Button(">")) { PlayAnimation(1); } if (GUILayout.Button(">>")) { if (animController.IsReady()) { PlayAnimation(2); } } if (GUILayout.Button(">>>")) { if (animController.IsReady()) { PlayAnimation(4); } } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(10); EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(1)), lineColor); //Heatmap EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); GUILayout.Label("Heatmap Settings"); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); 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)); heatmapType = EditorGUILayout.Popup("", heatmapType, Globals.HeatmapTypeString); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(heatmapGap); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Shape", GUILayout.Width(textWidth)); heatmapShape = EditorGUILayout.Popup("", heatmapShape, Globals.ShapeStrings); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(heatmapGap); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Shape Size", GUILayout.Width(textWidth)); heatmapSize = EditorGUILayout.FloatField(heatmapSize); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(heatmapGap); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Color Range", GUILayout.Width(textWidth)); heatmapColor.LowColor = EditorGUILayout.ColorField(new GUIContent(), heatmapColor.LowColor, false, true, false, GUILayout.Height(35)); GUILayout.Space(marginSize); heatmapColor.HighColor = EditorGUILayout.ColorField(new GUIContent(), heatmapColor.HighColor, false, true, false, GUILayout.Height(35)); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); GUILayout.Label("Minimum", EditorStyles.label); GUILayout.Space(marginSize); GUILayout.Label("Maximum", EditorStyles.label); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(heatmapGap); EditorGUILayout.BeginHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.LabelField("Value Range", GUILayout.Width(textWidth)); renderer.HeatmapValueMin = EditorGUILayout.DoubleField(renderer.HeatmapValueMin); GUILayout.Space(marginSize); renderer.HeatmapValueMax = EditorGUILayout.DoubleField(renderer.HeatmapValueMax); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); GUILayout.Label("Minimum", EditorStyles.label); GUILayout.Space(marginSize); GUILayout.Label("Maximum", EditorStyles.label); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); useOrientation = EditorGUILayout.ToggleLeft("Use Orientation", useOrientation); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); animController.IsHeatmap = EditorGUILayout.ToggleLeft("Apply to Animation", animController.IsHeatmap); GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); GUILayout.Space(marginSize); EditorGUILayout.BeginHorizontal(); GUILayout.Space(postTextMargin); if (GUILayout.Button("Generate")) { if (queryEventCollection.Count == 0 || vizSelectedEvent < 0) { return; } EventEditorContainer collection = new EventEditorContainer(); for (int i = 0; i < queryEventCollection.Count; i++) { queryEventCollection[i].ShouldAnimate = false; queryEventCollection[i].ShouldDraw = false; if (queryEventCollection[i].Name == eventNames[vizSelectedEvent]) { collection = queryEventCollection[i]; } } if (vizSubSelectedEvent > 0 && vizSubSelectedEvent > subEventNames.Count) { renderer.GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, subEventNames[vizSubSelectedEvent]); } else { renderer.GenerateHeatmap(collection, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, ""); } } GUILayout.Space(marginSize); EditorGUILayout.EndHorizontal(); } GUILayout.Space(10); }
// Master draw call. Updates animation if running, otherwise checks if objects need to be updated public void Tick(List <EventEditorContainer> filterCollection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, string subEvent, ref AnimationController animController) { if (!animController.IsStopped()) { if (animController.ShouldAnimate) { if (animController.NeedRefresh()) { DestroyTelemetryObjects(); //If we are playing in reverse, we need to add the remaining points to be removed later if (animController.PlaySpeed < 0) { EventEditorContainer eventContainer = animController.EventContainer; int j = 0; if (eventContainer != null) { foreach (var currEvent in eventContainer.events) { CreateTelemetryObject(j, currEvent, animController.Color, animController.Type); j++; } } } } List <TelemetryEvent> tempArray; if (animController.PlaySpeed >= 0) { if (animController.IsHeatmap) { //Regenerate the heatmap only using a subset of the events int start = animController.GetNextIndex(); int next = animController.GetNextEventCount(); EventEditorContainer tempContainer = animController.EventContainer; animController.AnimSlider = animController.GetTimeScaleFromTime() * animController.AnimSliderMax; if (start != next) { GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1, subEvent); } } else { //Update forward point animation by getting events that have occured over the last timespan and creating them tempArray = animController.GetNextEvents(); int i = animController.GetNextIndex(); animController.AnimSlider = animController.GetTimeScaleFromTime() * animController.AnimSliderMax; foreach (var currEvent in tempArray) { CreateTelemetryObject(i, currEvent, animController.Color, animController.Type); i++; } } } else { if (animController.IsHeatmap) { //Regenerate the heatmap only using a subset of the events int start = animController.GetPrevIndex(); int next = animController.GetPrevEventCount(); EventEditorContainer tempContainer = animController.EventContainer; animController.AnimSlider = (1 - animController.GetTimeScaleFromTime()) * animController.AnimSliderMax; if (start != next) { GenerateHeatmap(tempContainer, heatmapSize, heatmapColor, heatmapType, heatmapShape, useOrientation, next, tempContainer.events.Count - 1, subEvent); } } else { //Update reverse point animation by removing the last TelemetryObject for as many events occured over the last timespan tempArray = animController.GetPrevEvents(); animController.AnimSlider = (1 - animController.GetTimeScaleFromTime()) * animController.AnimSliderMax; foreach (var currEvent in tempArray) { DestroyLastTelemetryObject(); } } } //Set the location of the slider if (!animController.ShouldAnimate && animController.PlaySpeed >= 0) { animController.AnimSlider = animController.AnimSliderMax; } else if (!animController.ShouldAnimate && animController.PlaySpeed < 0) { animController.AnimSlider = 0; } } } else { if (needsTelemetryObjectUpdate) { //Draw data points needsTelemetryObjectUpdate = false; DestroyTelemetryObjects(); foreach (var events in filterCollection) { if (events.ShouldDraw) { int startIndex = 0; int endIndex = events.events.Count; CreateTelemetryObjects(events.events, startIndex, endIndex, events.Color, events.Type); } } } } }
public void GenerateHeatmap(EventEditorContainer collection, float heatmapSize, HeatmapColors heatmapColor, int heatmapType, int heatmapShape, bool useOrientation, int first, int last, string subEvent) { DestroyTelemetryObjects(); if (collection.events.Count != 0 && !(subEvent == "" && (heatmapType == (int)Globals.HeatmapType.Value || heatmapType == (int)Globals.HeatmapType.Value_Bar))) { if ((first == 0 && first == last) || (first == collection.events.Count - 1 && first == last)) { first = 0; last = collection.events.Count - 1; } //Segment the world in to blocks of the specified size encompassing all points Vector3 origin = collection.GetPointRange(first, last).center; //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 <Vector3, HeatmapNode> heatmapNodes = new Dictionary <Vector3, HeatmapNode>(); //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) { double largestValue = 0; double smallestValue = 0; int largestNumValue = 0; 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); } smallestValue = Math.Min(smallestValue, tempNode.values / tempNode.numValues); largestValue = Math.Max(largestValue, tempNode.values / tempNode.numValues); largestNumValue = Math.Max(largestNumValue, tempNode.numValues); } 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); } 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) { foreach (var node in heatmapNodes) { 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, (node.Key * heatmapSize) + origin, node.Value.orientation, heatmapColor.GetColorFromRange(tempColorValue), (PrimitiveType)heatmapShape, heatmapSize, tempValue); CreateHeatmapObject(tempTelemetryObject); i++; } } else if (heatmapType == (int)Globals.HeatmapType.Population) { foreach (var node in heatmapNodes) { tempValue = node.Value.numValues / HeatmapValueMax; tempColorValue = (float)((node.Value.numValues - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); 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; foreach (var node in heatmapNodes) { 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, (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; foreach (var node in heatmapNodes) { tempValue = node.Value.numValues / HeatmapValueMax; tempColorValue = (float)((node.Value.numValues - HeatmapValueMin) / (HeatmapValueMax - HeatmapValueMin)); tempColorValue = Mathf.Clamp(tempColorValue, 0, 1); tempHeight = (float)tempValue * heatmapSize; 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++; } } } } }
//Generate a heatmap for the range of events 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, subEvent); }