using System; using UnityEngine; using UnityEngine.UI; using sam; public class ProductVariableHistorgram : MonoBehaviour { public float heightFraction; ScrollRect scrollRect; RectTransform scrollContent; PointVariableSubsession pvls; Canvas canvas; Material mat; ProductData data; int varIndex; ProductProfile profile; ProductVariable prodvar; float minval; float maxval; Texture2D texture; int numSamples; int panelW; // width of panel in pixels int panelH; // height of panel in pixels int hpw; // half panel width (rounded down) float scrollFraction = 0.0f; // current scroll position (0 to 1) float gridSpacing; void Awake() { pvls = GetComponentInParent(); canvas = GetComponentInParent(); mat = GetComponent().material; scrollRect = GetComponentInParent(); scrollContent = scrollRect.content; scrollRect.onValueChanged.AddListener(OnTimeLineScrolled); } public void OnProductSelected(ProductData pdata) { data = pdata; profile = data.profile; numSamples = 3 + (int)(data.actualEndTime - data.actualStartTime).TotalSeconds; //Debug.Log($"Selected Product {data.url} with startTime:{data.actualStartTime} and endTime:{data.actualEndTime}"); texture = new Texture2D(numSamples, 1, TextureFormat.RGBAFloat, false); texture.filterMode = FilterMode.Point; texture.wrapMode = TextureWrapMode.Clamp; mat.mainTexture = texture; } public void OnVariableSelected(int vi) { //Debug.Log($"ProductVariableHistorgram.OnVariableSelected called"); varIndex = vi; prodvar = profile.variables[varIndex]; //minval = (float)(prodvar.MinAsDouble() * prodvar.scale); //maxval = (float)(prodvar.MaxAsDouble() * prodvar.scale); minval = (float)prodvar.scaledMinValue; maxval = (float)prodvar.scaledMaxValue; //if (prodvar.scale < 0.0f) if (maxval < minval) { Debug.Log("Swapping min and max values"); float tmp = minval; minval = maxval; maxval = tmp; } float valrange = maxval - minval; int numFloats = numSamples * 4; int numSeconds = numSamples - 2; float[] buf = new float[numFloats]; for (int i = 0; i < numFloats; i++) buf[i] = 0.0f; foreach (var dp in data.dataPoints) { int s = (int)(dp.time - data.actualStartTime).TotalSeconds; if (s < 0) { Debug.LogWarning($"DataPoint timestamp preceeds file startTime by {-s} seconds (numSamps={numSamples})"); //Debug.Log($"datapoint time: {dp.time} file.startTIme: {data.actualStartTime}"); continue; } else if (s >= numSeconds) { Debug.LogWarning($"DataPoint timestamp is after file endTime by {s - numSeconds + 1} seconds (numSamps={numSamples})"); //Debug.Log($"datapoint time: {dp.time} file.endTIme: {data.actualEndTime}"); continue; } float fv = (dp.variables[varIndex] - minval) / valrange; Color col = pvls.GetDataPointColor(dp); buf[(s + 1) * 4 + 0] = col.r; buf[(s + 1) * 4 + 1] = col.g; buf[(s + 1) * 4 + 2] = col.b; buf[(s + 1) * 4 + 3] = fv; } gameObject.SetActive(false); texture.SetPixelData(buf, 0); texture.Apply(); mat.mainTexture = texture; OnScreenSizeChanged(); ComputeGridSpacing(); gameObject.SetActive(true); scrollRect.normalizedPosition = new Vector2(scrollFraction, 0.0f); OnTimeLineScrolled(scrollRect.normalizedPosition); } void ComputeGridSpacing() { // select an appropriate value for gridSpacing based on MinVal and MaxVal if (prodvar.gridStep > 0.0f) { gridSpacing = prodvar.gridStep; } else { double valrange = maxval - minval; gridSpacing = (float)Math.Pow(10.0, (int)Math.Floor(Math.Log10(valrange))); } } void RecomputeScrollableSize() { float cs = canvas.transform.localScale.x; float tw = (numSamples + Screen.width) / cs; scrollContent.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, tw); } public void OnScreenSizeChanged() { panelW = Screen.width; panelH = (int)(((float)Screen.height) * heightFraction); hpw = panelW / 2; RecomputeScrollableSize(); ComputeGridSpacing(); UpdateUniforms(); } public void OnTimeLineScrolled(Vector2 scrollPos) { scrollFraction = scrollPos.x; int offsetInseconds = (int)(scrollFraction * (numSamples - 4)); DateTime t = data.actualStartTime.AddSeconds(offsetInseconds); pvls.SelectTimeStamp(t); UpdateUniforms(); } void UpdateUniforms() { // histCoordx float left = ((float)(-hpw + 1)) / numSamples; float right = ((float)(numSamples - 3 - hpw)) / numSamples; float histCoordxMIN = Mathf.LerpUnclamped(left, right, scrollFraction); float histCoordxMAX = histCoordxMIN + (((float)panelW) / numSamples); // barCoordx float barcoordxMIN = -hpw; float barcoordxMAX = panelW - hpw; // gridcoordy float unitsPerPixel = ((float)(maxval - minval)) / panelH; int pxSpacing = (int)Math.Round(gridSpacing / unitsPerPixel); mat.SetInt("_gridSpacing", pxSpacing); int gridOffset = (int)((gridSpacing - (minval % gridSpacing)) / unitsPerPixel); float gridcoordyMIN = pxSpacing - gridOffset - 1; while (gridcoordyMIN < 0.0) gridcoordyMIN += pxSpacing; float gridcoordyMAX = gridcoordyMIN + panelH; mat.SetVector("_minCoords", new Vector4( histCoordxMIN, 0.5f, barcoordxMIN, gridcoordyMIN )); mat.SetVector("_maxCoords", new Vector4( histCoordxMAX, 0.5f, barcoordxMAX, gridcoordyMAX )); } }