Files
2025-05-13 03:30:23 +03:00

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 () {
}
}