245 lines
6.1 KiB
C#
245 lines
6.1 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
public class OscilloscopeDisplay : MonoBehaviour {
|
|
public Material displayMaterial;
|
|
private Texture2D diplayBackground;
|
|
public Oscilloscope oscilloscope;
|
|
|
|
public int halfXCellCount = 6;
|
|
public int halfYCellCount = 4;
|
|
public int cellSize = 50;
|
|
public int shortLineSize = 5;
|
|
public Vector2 position;
|
|
|
|
public Color backgroundColor = new Color(0,0,0,0.6f);
|
|
public Color linesColor = new Color(0.27f,0.57f,0.9f, 1.0f);
|
|
|
|
static Material lineMaterial;
|
|
static void CreateLineMaterial() {
|
|
if( !lineMaterial ) {
|
|
lineMaterial = new Material( " Shader \"Lines/Colored Blended\" {" +
|
|
" SubShader { Pass { " +
|
|
" Blend SrcAlpha OneMinusSrcAlpha " +
|
|
" ZWrite Off Cull Off ZTest Off Fog { Mode Off } " +
|
|
" BindChannels {" +
|
|
" Bind \"vertex\", vertex Bind \"color\", color }" +
|
|
"} } }" );
|
|
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
|
|
lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
|
|
}
|
|
}
|
|
|
|
// Use this for initialization
|
|
void Start () {
|
|
|
|
}
|
|
|
|
void GenerateBackground(Texture2D tex){
|
|
if (tex == null) {
|
|
return;
|
|
}
|
|
Debug.Log ("GenerateBackground");
|
|
|
|
Color[] pixels = new Color[tex.width * tex.height];
|
|
|
|
//fill background
|
|
for (int i = 0; i < pixels.Length; ++i) {
|
|
pixels[i] = backgroundColor;
|
|
}
|
|
|
|
//draw grid
|
|
//-horizontal lines
|
|
for (int i = 0; i <= halfYCellCount * 2; ++i) {
|
|
int y = i * cellSize;
|
|
for(int x = 0; x < tex.width; ++x){
|
|
if(y != 0 && y != tex.height - 1){
|
|
if((x % 2) == 1){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
int id = y * tex.width + x;
|
|
pixels[id] = linesColor;
|
|
}
|
|
}
|
|
//-vertical lines
|
|
for (int i = 0; i <= halfXCellCount * 2; ++i) {
|
|
int x = i * cellSize;
|
|
for(int y = 0; y < tex.height; ++y){
|
|
if(x != 0 && x != tex.width - 1){
|
|
if((y % 2) == 1){
|
|
continue;
|
|
}
|
|
}
|
|
int id = y * tex.width + x;
|
|
pixels[id] = linesColor;
|
|
}
|
|
}
|
|
|
|
//draw helper short lines
|
|
//-vertical
|
|
int[] cells = new int[]{0,halfXCellCount, halfXCellCount*2};
|
|
int[] offsets = new int[]{0, -shortLineSize / 2, -shortLineSize + 1 };
|
|
for (int i = 0; i < cells.Length; ++i) {
|
|
int x = cells[i] * cellSize + offsets[i];
|
|
for(int y = 0; y < tex.height; y += (cellSize / 5)){
|
|
for(int j = x; j < (x + shortLineSize); ++j){
|
|
pixels[ y * tex.width + j] = linesColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
//horizontal
|
|
cells = new int[]{0, halfYCellCount, halfYCellCount*2};
|
|
for (int i = 0; i < cells.Length; ++i) {
|
|
int y = cells[i] * cellSize + offsets[i];
|
|
for(int x = 0; x < tex.width; x += (cellSize / 5)){
|
|
for(int j = y; j < (y + shortLineSize); ++j){
|
|
pixels[ j * tex.width + x] = linesColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
tex.SetPixels (pixels);
|
|
tex.Apply ();
|
|
|
|
}
|
|
|
|
void OnValidate(){
|
|
int texWidth = cellSize * halfXCellCount * 2 + 1;
|
|
int texHeight = cellSize * halfYCellCount * 2 + 1;
|
|
|
|
if (diplayBackground == null || diplayBackground.width != texWidth || diplayBackground.height != texHeight) {
|
|
diplayBackground = new Texture2D(texWidth, texHeight, TextureFormat.ARGB32, false, true);
|
|
}
|
|
|
|
GenerateBackground (diplayBackground);
|
|
}
|
|
|
|
|
|
void OnDrawGizmos(){
|
|
|
|
GL.PushMatrix ();
|
|
//GL.LoadPixelMatrix ();
|
|
|
|
GL.LoadPixelMatrix (0, Camera.current.pixelWidth, Camera.current.pixelHeight, 0);
|
|
|
|
|
|
Graphics.DrawTexture (new Rect (position.x, position.y, diplayBackground.width, diplayBackground.height), diplayBackground);
|
|
|
|
if (oscilloscope != null) {
|
|
Vector2 size = new Vector2 (halfXCellCount * 2 * cellSize, halfYCellCount * 2 * cellSize);
|
|
CreateLineMaterial();
|
|
//func
|
|
lineMaterial.SetPass(0);
|
|
GL.Begin(GL.LINES);
|
|
lineMaterial.SetPass(0);
|
|
float verticalOffset = halfYCellCount * cellSize;
|
|
|
|
foreach (var channel in oscilloscope.channels) {
|
|
if(channel == null || !channel.draw){
|
|
continue;
|
|
}
|
|
GL.Color(channel.color);
|
|
|
|
var timeBuffer = channel.SampleTimeBuffer;
|
|
var valueBuffer = channel.SampleValueBuffer;
|
|
var bufferPos = channel.SampleBufferPosition;
|
|
|
|
if(timeBuffer == null || timeBuffer.Length == 0 || valueBuffer == null || valueBuffer.Length == 0){
|
|
|
|
continue;
|
|
}
|
|
|
|
float lastTime = timeBuffer[bufferPos];
|
|
float lastX = size.x;
|
|
float lastY = size.y - ((valueBuffer[bufferPos] / channel.cellValue) * cellSize + verticalOffset);
|
|
|
|
for(int i = 1; i < timeBuffer.Length; ++i){
|
|
if(bufferPos == 0){
|
|
bufferPos = valueBuffer.Length - 1;
|
|
}else{
|
|
bufferPos = bufferPos - 1;
|
|
}
|
|
|
|
float timeOffset = timeBuffer[bufferPos] - lastTime;
|
|
float curX = size.x + (timeOffset / channel.cellTime) * cellSize;
|
|
float curY = size.y - ((valueBuffer[bufferPos] / channel.cellValue) * cellSize + verticalOffset);
|
|
|
|
Vector2 curVector = Vector3.zero;
|
|
Vector2 lastVector = Vector3.zero;
|
|
|
|
if(ClipLine(lastX, lastY, curX, curY, ref curVector, ref lastVector, size)){
|
|
GL.Vertex(new Vector3(curVector.x + position.x, curVector.y + position.y, 0));
|
|
GL.Vertex(new Vector3(lastVector.x + position.x, lastVector.y + position.y, 0));
|
|
}
|
|
|
|
|
|
lastY = curY;
|
|
lastX = curX;
|
|
}
|
|
}
|
|
|
|
GL.End();
|
|
}
|
|
GL.PopMatrix ();
|
|
|
|
}
|
|
|
|
bool ClipLine(float lastX, float lastY, float curX, float curY, ref Vector2 L, ref Vector2 R, Vector2 size){
|
|
|
|
if (lastX < 0) {
|
|
return false;
|
|
}
|
|
L.x = curX;
|
|
L.y = curY;
|
|
|
|
R.x = lastX;
|
|
R.y = lastY;
|
|
|
|
if(R.x < 0){
|
|
float kx = (L.x / (L.x - R.x));
|
|
L.y = L.y + (R.y - L.y) * kx;
|
|
L.x = 0;
|
|
}
|
|
|
|
if (L.y > R.y) {
|
|
var tmp = R;
|
|
R = L;
|
|
L = tmp;
|
|
}
|
|
|
|
//L.y always smaller
|
|
if (R.y <= 0) {
|
|
return false;
|
|
}
|
|
if (L.y >= size.y) {
|
|
return false;
|
|
}
|
|
|
|
if (L.y < 0) { //top clamp
|
|
float kx = L.y / (L.y - R.y);
|
|
L.x = L.x + (R.x - L.x) * kx;
|
|
L.y = 0;
|
|
}
|
|
if (R.y > size.y){ //bottom clamp
|
|
float kx = (R.y - size.y) / (R.y - L.y);
|
|
|
|
R.x = R.x + (L.x - R.x) * kx;
|
|
R.y = size.y;
|
|
}
|
|
|
|
if (R.y > size.y || L.y > size.y) {
|
|
Debug.Log("Fail");
|
|
}
|
|
return true;
|
|
}
|
|
// Update is called once per frame
|
|
void Update () {
|
|
|
|
}
|
|
}
|