Fixed errors and warnings in generic C#
This commit is contained in:
parent
f28aea5441
commit
0f844f5fad
@ -10,6 +10,10 @@ end_of_line = crlf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
max_line_length = 80
|
||||
|
||||
[*.cs]
|
||||
csharp_new_line_before_open_brace = none
|
||||
csharp_new_line_before_open_brace = none
|
||||
# Suppress warnings everywhere
|
||||
dotnet_diagnostic.IDE1006.severity = none
|
||||
dotnet_diagnostic.IDE0130.severity = none
|
@ -344,179 +344,179 @@ public class Matrix1 {
|
||||
}
|
||||
}
|
||||
|
||||
public class Matrix {
|
||||
private readonly uint rows = 0;
|
||||
private readonly uint cols = 0;
|
||||
private float[] data;
|
||||
// public class Matrix {
|
||||
// private readonly uint rows = 0;
|
||||
// private readonly uint cols = 0;
|
||||
// private float[] data;
|
||||
|
||||
public Matrix(uint rows, uint cols) {
|
||||
this.rows = rows;
|
||||
this.cols = cols;
|
||||
}
|
||||
// public Matrix(uint rows, uint cols) {
|
||||
// this.rows = rows;
|
||||
// this.cols = cols;
|
||||
// }
|
||||
|
||||
public static float[,] Diagonal(float[] v) {
|
||||
float[,] r = new float[v.Length, v.Length];
|
||||
for (int i = 0; i < v.Length; i++) {
|
||||
r[i, i] = v[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
// public static float[,] Diagonal(float[] v) {
|
||||
// float[,] r = new float[v.Length, v.Length];
|
||||
// for (int i = 0; i < v.Length; i++) {
|
||||
// r[i, i] = v[i];
|
||||
// }
|
||||
// return r;
|
||||
// }
|
||||
|
||||
public static float[,] Transpose(float[,] m) {
|
||||
int rows = m.GetLength(0);
|
||||
int cols = m.GetLength(1);
|
||||
float[,] r = new float[cols, rows];
|
||||
for (uint rowIx = 0; rowIx < rows; rowIx++) {
|
||||
for (uint colIx = 0; colIx < cols; colIx++)
|
||||
r[colIx, rowIx] = m[rowIx, colIx];
|
||||
}
|
||||
return r;
|
||||
// double checked code
|
||||
}
|
||||
// public static float[,] Transpose(float[,] m) {
|
||||
// int rows = m.GetLength(0);
|
||||
// int cols = m.GetLength(1);
|
||||
// float[,] r = new float[cols, rows];
|
||||
// for (uint rowIx = 0; rowIx < rows; rowIx++) {
|
||||
// for (uint colIx = 0; colIx < cols; colIx++)
|
||||
// r[colIx, rowIx] = m[rowIx, colIx];
|
||||
// }
|
||||
// return r;
|
||||
// // double checked code
|
||||
// }
|
||||
|
||||
public static void NegateColumn(float[,] m, uint colIx) {
|
||||
for (uint rowIx = 0; rowIx < m.GetLength(0); rowIx++) {
|
||||
m[rowIx, colIx] = -m[rowIx, colIx];
|
||||
}
|
||||
}
|
||||
// public static void NegateColumn(float[,] m, uint colIx) {
|
||||
// for (uint rowIx = 0; rowIx < m.GetLength(0); rowIx++) {
|
||||
// m[rowIx, colIx] = -m[rowIx, colIx];
|
||||
// }
|
||||
// }
|
||||
|
||||
public static float Determinant(float[,] matrix) {
|
||||
int n = matrix.GetLength(0);
|
||||
if (n != matrix.GetLength(1))
|
||||
throw new System.ArgumentException("Matrix must be square.");
|
||||
// public static float Determinant(float[,] matrix) {
|
||||
// int n = matrix.GetLength(0);
|
||||
// if (n != matrix.GetLength(1))
|
||||
// throw new System.ArgumentException("Matrix must be square.");
|
||||
|
||||
if (n == 1)
|
||||
return matrix[0, 0]; // Base case for 1x1 matrix
|
||||
// if (n == 1)
|
||||
// return matrix[0, 0]; // Base case for 1x1 matrix
|
||||
|
||||
if (n == 2) // Base case for 2x2 matrix
|
||||
return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0];
|
||||
// if (n == 2) // Base case for 2x2 matrix
|
||||
// return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0];
|
||||
|
||||
float det = 0;
|
||||
for (int col = 0; col < n; col++)
|
||||
det += (col % 2 == 0 ? 1 : -1) * matrix[0, col] * Determinant(Minor(matrix, 0, col));
|
||||
// float det = 0;
|
||||
// for (int col = 0; col < n; col++)
|
||||
// det += (col % 2 == 0 ? 1 : -1) * matrix[0, col] * Determinant(Minor(matrix, 0, col));
|
||||
|
||||
return det;
|
||||
}
|
||||
// return det;
|
||||
// }
|
||||
|
||||
// Helper function to compute the minor of a matrix
|
||||
private static float[,] Minor(float[,] matrix, int rowToRemove, int colToRemove) {
|
||||
int n = matrix.GetLength(0);
|
||||
float[,] minor = new float[n - 1, n - 1];
|
||||
// // Helper function to compute the minor of a matrix
|
||||
// private static float[,] Minor(float[,] matrix, int rowToRemove, int colToRemove) {
|
||||
// int n = matrix.GetLength(0);
|
||||
// float[,] minor = new float[n - 1, n - 1];
|
||||
|
||||
int r = 0, c = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (i == rowToRemove) continue;
|
||||
// int r = 0, c = 0;
|
||||
// for (int i = 0; i < n; i++) {
|
||||
// if (i == rowToRemove) continue;
|
||||
|
||||
c = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (j == colToRemove) continue;
|
||||
// c = 0;
|
||||
// for (int j = 0; j < n; j++) {
|
||||
// if (j == colToRemove) continue;
|
||||
|
||||
minor[r, c] = matrix[i, j];
|
||||
c++;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
// minor[r, c] = matrix[i, j];
|
||||
// c++;
|
||||
// }
|
||||
// r++;
|
||||
// }
|
||||
|
||||
return minor;
|
||||
}
|
||||
// return minor;
|
||||
// }
|
||||
|
||||
public static float[,] MultiplyMatrices(float[,] A, float[,] B) {
|
||||
int rowsA = A.GetLength(0);
|
||||
int colsA = A.GetLength(1);
|
||||
int rowsB = B.GetLength(0);
|
||||
int colsB = B.GetLength(1);
|
||||
// public static float[,] MultiplyMatrices(float[,] A, float[,] B) {
|
||||
// int rowsA = A.GetLength(0);
|
||||
// int colsA = A.GetLength(1);
|
||||
// int rowsB = B.GetLength(0);
|
||||
// int colsB = B.GetLength(1);
|
||||
|
||||
if (colsA != rowsB)
|
||||
throw new System.ArgumentException("Number of columns in A must match number of rows in B.");
|
||||
// if (colsA != rowsB)
|
||||
// throw new System.ArgumentException("Number of columns in A must match number of rows in B.");
|
||||
|
||||
float[,] result = new float[rowsA, colsB];
|
||||
// float[,] result = new float[rowsA, colsB];
|
||||
|
||||
for (int i = 0; i < rowsA; i++) {
|
||||
for (int j = 0; j < colsB; j++) {
|
||||
float sum = 0.0f;
|
||||
for (int k = 0; k < colsA; k++)
|
||||
sum += A[i, k] * B[k, j];
|
||||
// for (int i = 0; i < rowsA; i++) {
|
||||
// for (int j = 0; j < colsB; j++) {
|
||||
// float sum = 0.0f;
|
||||
// for (int k = 0; k < colsA; k++)
|
||||
// sum += A[i, k] * B[k, j];
|
||||
|
||||
result[i, j] = sum;
|
||||
}
|
||||
}
|
||||
// result[i, j] = sum;
|
||||
// }
|
||||
// }
|
||||
|
||||
return result;
|
||||
// double checked code
|
||||
}
|
||||
// return result;
|
||||
// // double checked code
|
||||
// }
|
||||
|
||||
public static float[] MultiplyMatrixVector(float[,] A, float[] v) {
|
||||
int rows = A.GetLength(0);
|
||||
int cols = A.GetLength(1);
|
||||
float[] result = new float[rows];
|
||||
// public static float[] MultiplyMatrixVector(float[,] A, float[] v) {
|
||||
// int rows = A.GetLength(0);
|
||||
// int cols = A.GetLength(1);
|
||||
// float[] result = new float[rows];
|
||||
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
result[i] += A[i, j] * v[j];
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < rows; i++) {
|
||||
// for (int j = 0; j < cols; j++) {
|
||||
// result[i] += A[i, j] * v[j];
|
||||
// }
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// Vector-matrix multiplication
|
||||
public static Vector3Float MultiplyMatrixVector3(float[,] A, Vector3Float v) {
|
||||
return new Vector3Float(
|
||||
A[0, 0] * v.x + A[0, 1] * v.y + A[0, 2] * v.z,
|
||||
A[1, 0] * v.x + A[1, 1] * v.y + A[1, 2] * v.z,
|
||||
A[2, 0] * v.x + A[2, 1] * v.y + A[2, 2] * v.z
|
||||
);
|
||||
}
|
||||
// // Vector-matrix multiplication
|
||||
// public static Vector3Float MultiplyMatrixVector3(float[,] A, Vector3Float v) {
|
||||
// return new Vector3Float(
|
||||
// A[0, 0] * v.x + A[0, 1] * v.y + A[0, 2] * v.z,
|
||||
// A[1, 0] * v.x + A[1, 1] * v.y + A[1, 2] * v.z,
|
||||
// A[2, 0] * v.x + A[2, 1] * v.y + A[2, 2] * v.z
|
||||
// );
|
||||
// }
|
||||
|
||||
public static float[,] MultiplyMatrixScalar(float[,] A, float s) {
|
||||
int rows = A.GetLength(0);
|
||||
int cols = A.GetLength(1);
|
||||
float[,] result = new float[rows, cols];
|
||||
// public static float[,] MultiplyMatrixScalar(float[,] A, float s) {
|
||||
// int rows = A.GetLength(0);
|
||||
// int cols = A.GetLength(1);
|
||||
// float[,] result = new float[rows, cols];
|
||||
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
result[i, j] += A[i, j] * s;
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < rows; i++) {
|
||||
// for (int j = 0; j < cols; j++) {
|
||||
// result[i, j] += A[i, j] * s;
|
||||
// }
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public static float[] GetColumn(float[,] M, int col) {
|
||||
int rows = M.GetLength(0);
|
||||
float[] column = new float[rows];
|
||||
for (int i = 0; i < rows; i++) {
|
||||
column[i] = M[i, col];
|
||||
}
|
||||
return column;
|
||||
}
|
||||
// public static float[] GetColumn(float[,] M, int col) {
|
||||
// int rows = M.GetLength(0);
|
||||
// float[] column = new float[rows];
|
||||
// for (int i = 0; i < rows; i++) {
|
||||
// column[i] = M[i, col];
|
||||
// }
|
||||
// return column;
|
||||
// }
|
||||
|
||||
public static Vector3Float GetRow3(float[,] M, int rowIx) {
|
||||
int cols = M.GetLength(1);
|
||||
Vector3Float row = new(
|
||||
M[rowIx, 0],
|
||||
M[rowIx, 1],
|
||||
M[rowIx, 2]
|
||||
);
|
||||
return row;
|
||||
}
|
||||
// public static Vector3Float GetRow3(float[,] M, int rowIx) {
|
||||
// int cols = M.GetLength(1);
|
||||
// Vector3Float row = new(
|
||||
// M[rowIx, 0],
|
||||
// M[rowIx, 1],
|
||||
// M[rowIx, 2]
|
||||
// );
|
||||
// return row;
|
||||
// }
|
||||
|
||||
public static void SetRow3(float[,] M, int rowIx, Vector3Float v) {
|
||||
M[rowIx, 0] = v.x;
|
||||
M[rowIx, 1] = v.y;
|
||||
M[rowIx, 2] = v.z;
|
||||
}
|
||||
// public static void SetRow3(float[,] M, int rowIx, Vector3Float v) {
|
||||
// M[rowIx, 0] = v.x;
|
||||
// M[rowIx, 1] = v.y;
|
||||
// M[rowIx, 2] = v.z;
|
||||
// }
|
||||
|
||||
public static float Dot(float[] a, float[] b) {
|
||||
float sum = 0;
|
||||
for (int i = 0; i < a.Length; i++) sum += a[i] * b[i];
|
||||
return sum;
|
||||
}
|
||||
// public static float Dot(float[] a, float[] b) {
|
||||
// float sum = 0;
|
||||
// for (int i = 0; i < a.Length; i++) sum += a[i] * b[i];
|
||||
// return sum;
|
||||
// }
|
||||
|
||||
public static float[,] IdentityMatrix(int size) {
|
||||
float[,] I = new float[size, size];
|
||||
for (int i = 0; i < size; i++) I[i, i] = 1.0f;
|
||||
return I;
|
||||
}
|
||||
// public static float[,] IdentityMatrix(int size) {
|
||||
// float[,] I = new float[size, size];
|
||||
// for (int i = 0; i < size; i++) I[i, i] = 1.0f;
|
||||
// return I;
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
@ -1,3 +1,4 @@
|
||||
#nullable enable
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class CustomMsg : IMessage {
|
||||
@ -23,11 +24,13 @@ namespace Passer.Control.Core {
|
||||
public CustomMsg(byte networkId, Thing thing) : base() {
|
||||
this.networkId = networkId;
|
||||
this.thingId = thing.id;
|
||||
this.bytes = [];
|
||||
}
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
if (bytes == null)
|
||||
if (bytes.Length == 0)
|
||||
return 0;
|
||||
|
||||
byte ix = 0;
|
||||
buffer[ix++] = CustomMsg.Id;
|
||||
buffer[ix++] = this.networkId;
|
||||
|
29
Messages/DestroyMsg.cs
Normal file
29
Messages/DestroyMsg.cs
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class DestroyMsg : IMessage {
|
||||
public const byte Id = 0x20;
|
||||
public const byte length = 3;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public DestroyMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
this.networkId = buffer[0];
|
||||
this.thingId = buffer[1];
|
||||
}
|
||||
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
if (packetSize != length)
|
||||
return false;
|
||||
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
DestroyMsg msg = new(buffer);
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
Messages/InvestigateMsg.cs
Normal file
46
Messages/InvestigateMsg.cs
Normal file
@ -0,0 +1,46 @@
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class InvestigateMsg : IMessage {
|
||||
public const byte Id = 0x81;
|
||||
public const byte length = 3;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public InvestigateMsg(byte networkId, byte thingId) {
|
||||
this.networkId = networkId;
|
||||
this.thingId = thingId;
|
||||
}
|
||||
public InvestigateMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
byte ix = 0;
|
||||
buffer[ix++] = InvestigateMsg.Id;
|
||||
buffer[ix++] = this.networkId;
|
||||
buffer[ix++] = this.thingId;
|
||||
return ix;
|
||||
}
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
uint ix = 0;
|
||||
this.networkId = buffer[ix++];
|
||||
this.thingId = buffer[ix++];
|
||||
}
|
||||
|
||||
//public static bool Send(Participant client, CoreThing thing) {
|
||||
// InvestigateMsg msg = new(thing.networkId, thing.id);
|
||||
// return SendMsg(client, msg);
|
||||
//}
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
if (packetSize != length)
|
||||
return false;
|
||||
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
InvestigateMsg msg = new(buffer);
|
||||
//UnityEngine.Debug.Log($"Receive investigate [{msg.networkId}/{msg.thingId}]");
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,3 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Passer.LinearAlgebra;
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class IMessage {
|
||||
@ -40,214 +36,4 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
}
|
||||
|
||||
#region Investigate
|
||||
|
||||
public class InvestigateMsg : IMessage {
|
||||
public const byte Id = 0x81;
|
||||
public const byte length = 3;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public InvestigateMsg(byte networkId, byte thingId) {
|
||||
this.networkId = networkId;
|
||||
this.thingId = thingId;
|
||||
}
|
||||
public InvestigateMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
byte ix = 0;
|
||||
buffer[ix++] = InvestigateMsg.Id;
|
||||
buffer[ix++] = this.networkId;
|
||||
buffer[ix++] = this.thingId;
|
||||
return ix;
|
||||
}
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
uint ix = 0;
|
||||
this.networkId = buffer[ix++];
|
||||
this.thingId = buffer[ix++];
|
||||
}
|
||||
|
||||
//public static bool Send(Participant client, CoreThing thing) {
|
||||
// InvestigateMsg msg = new(thing.networkId, thing.id);
|
||||
// return SendMsg(client, msg);
|
||||
//}
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
if (packetSize != length)
|
||||
return false;
|
||||
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
InvestigateMsg msg = new(buffer);
|
||||
//UnityEngine.Debug.Log($"Receive investigate [{msg.networkId}/{msg.thingId}]");
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Investigate
|
||||
|
||||
#region Pose
|
||||
|
||||
public class PoseMsg : IMessage {
|
||||
public const byte Id = 0x10;
|
||||
public const byte length = 4 + 4 + 4;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public byte poseType;
|
||||
public const byte Pose_Position = 0x01;
|
||||
public const byte Pose_Orientation = 0x02;
|
||||
public const byte Pose_LinearVelocity = 0x04;
|
||||
public const byte Pose_AngularVelocity = 0x08;
|
||||
|
||||
public Spherical position;
|
||||
public SwingTwist orientation;
|
||||
public Spherical linearVelocity;
|
||||
public Spherical angularVelocity;
|
||||
|
||||
public PoseMsg(byte networkId, byte thingId, Spherical position, SwingTwist orientation) {
|
||||
this.networkId = networkId;
|
||||
this.thingId = thingId;
|
||||
this.position = position;
|
||||
this.orientation = orientation;
|
||||
this.poseType = 0;
|
||||
if (this.position != null)
|
||||
this.poseType |= Pose_Position;
|
||||
else
|
||||
this.position = new Spherical(0, 0, 0);
|
||||
if (this.orientation != null)
|
||||
this.poseType |= Pose_Orientation;
|
||||
else
|
||||
this.orientation = SwingTwist.zero;
|
||||
}
|
||||
public PoseMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
byte ix = 0;
|
||||
buffer[ix++] = PoseMsg.Id;
|
||||
buffer[ix++] = this.networkId;
|
||||
buffer[ix++] = this.thingId;
|
||||
buffer[ix++] = this.poseType;
|
||||
|
||||
if ((poseType & Pose_Position) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.position);
|
||||
if ((poseType & Pose_Orientation) != 0)
|
||||
LowLevelMessages.SendQuat32(buffer, ref ix, this.orientation);
|
||||
if ((poseType & Pose_LinearVelocity) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.linearVelocity);
|
||||
if ((poseType & Pose_AngularVelocity) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.angularVelocity);
|
||||
return ix;
|
||||
}
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
byte ix = 0;
|
||||
this.networkId = buffer[ix++];
|
||||
this.thingId = buffer[ix++];
|
||||
this.poseType = buffer[ix++];
|
||||
|
||||
if ((poseType & Pose_Position) != 0)
|
||||
this.position = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
if ((poseType & Pose_Orientation) != 0)
|
||||
this.orientation = LowLevelMessages.ReceiveSwingTwist(buffer, ref ix);
|
||||
if ((poseType & Pose_LinearVelocity) != 0)
|
||||
this.linearVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
if ((poseType & Pose_AngularVelocity) != 0)
|
||||
this.angularVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
}
|
||||
|
||||
public static bool Send(Participant client, byte thingId, Spherical position, SwingTwist orientation) {
|
||||
PoseMsg msg = new(client.networkId, thingId, position, orientation);
|
||||
return SendMsg(client, msg);
|
||||
}
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
PoseMsg msg = new(buffer);
|
||||
|
||||
// Do no process poses with nwid == 0 (== local)
|
||||
if (msg.networkId == 0)
|
||||
return true;
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SendTo(Participant participant, Thing thing) {
|
||||
if (participant == null || thing == null)
|
||||
return false;
|
||||
|
||||
byte ix = 0;
|
||||
participant.buffer[ix++] = PoseMsg.Id;
|
||||
participant.buffer[ix++] = participant.networkId;
|
||||
participant.buffer[ix++] = thing.id;
|
||||
participant.buffer[ix++] = thing.poseUpdated;
|
||||
|
||||
if ((thing.poseUpdated & Pose_Position) != 0 && thing.position != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.position);
|
||||
if ((thing.poseUpdated & Pose_Orientation) != 0 && thing.orientation != null)
|
||||
LowLevelMessages.SendQuat32(participant.buffer, ref ix, thing.orientation);
|
||||
if ((thing.poseUpdated & Pose_LinearVelocity) != 0 && thing.linearVelocity != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.linearVelocity);
|
||||
if ((thing.poseUpdated & Pose_AngularVelocity) != 0 && thing.angularVelocity != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.angularVelocity);
|
||||
|
||||
return participant.SendBuffer(ix);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Pose
|
||||
|
||||
#region Text
|
||||
|
||||
public class TextMsg : IMessage {
|
||||
public const byte Id = 0xB0;
|
||||
public string text;
|
||||
|
||||
public TextMsg(byte[] buffer) : base(buffer) { }
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
uint ix = 0;
|
||||
uint strlen = buffer[ix++];
|
||||
this.text = System.Text.Encoding.UTF8.GetString(buffer, (int)ix, (int)strlen);
|
||||
}
|
||||
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
TextMsg msg = new(buffer);
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
|
||||
public class DestroyMsg : IMessage {
|
||||
public const byte Id = 0x20;
|
||||
public const byte length = 3;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public DestroyMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
this.networkId = buffer[0];
|
||||
this.thingId = buffer[1];
|
||||
}
|
||||
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
if (packetSize != length)
|
||||
return false;
|
||||
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
DestroyMsg msg = new(buffer);
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion Destroy
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace Passer.Control.Core {
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
public byte len;
|
||||
public string? name = null;
|
||||
public string name = "";
|
||||
|
||||
public NameMsg(byte networkId, Thing thing) {
|
||||
this.networkId = networkId;
|
||||
@ -29,7 +29,7 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
if (this.name == null)
|
||||
if (this.name.Length == 0)
|
||||
return 0;
|
||||
|
||||
byte ix = 0;
|
||||
|
109
Messages/PoseMsg.cs
Normal file
109
Messages/PoseMsg.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using Passer.LinearAlgebra;
|
||||
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class PoseMsg : IMessage {
|
||||
public const byte Id = 0x10;
|
||||
public const byte length = 4 + 4 + 4;
|
||||
public byte networkId;
|
||||
public byte thingId;
|
||||
|
||||
public byte poseType;
|
||||
public const byte Pose_Position = 0x01;
|
||||
public const byte Pose_Orientation = 0x02;
|
||||
public const byte Pose_LinearVelocity = 0x04;
|
||||
public const byte Pose_AngularVelocity = 0x08;
|
||||
|
||||
public Spherical position = Spherical.zero;
|
||||
public SwingTwist orientation = SwingTwist.zero;
|
||||
public Spherical linearVelocity = Spherical.zero;
|
||||
public Spherical angularVelocity = Spherical.zero;
|
||||
|
||||
public PoseMsg(byte networkId, byte thingId, Spherical position, SwingTwist orientation) {
|
||||
this.networkId = networkId;
|
||||
this.thingId = thingId;
|
||||
|
||||
this.position = position;
|
||||
this.orientation = orientation;
|
||||
|
||||
this.poseType = 0;
|
||||
if (this.position != null)
|
||||
this.poseType |= Pose_Position;
|
||||
if (this.orientation != null)
|
||||
this.poseType |= Pose_Orientation;
|
||||
}
|
||||
public PoseMsg(byte[] buffer) : base(buffer) { }
|
||||
|
||||
public override byte Serialize(ref byte[] buffer) {
|
||||
byte ix = 0;
|
||||
buffer[ix++] = PoseMsg.Id;
|
||||
buffer[ix++] = this.networkId;
|
||||
buffer[ix++] = this.thingId;
|
||||
buffer[ix++] = this.poseType;
|
||||
|
||||
if ((poseType & Pose_Position) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.position);
|
||||
if ((poseType & Pose_Orientation) != 0)
|
||||
LowLevelMessages.SendQuat32(buffer, ref ix, this.orientation);
|
||||
if ((poseType & Pose_LinearVelocity) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.linearVelocity);
|
||||
if ((poseType & Pose_AngularVelocity) != 0)
|
||||
LowLevelMessages.SendSpherical(buffer, ref ix, this.angularVelocity);
|
||||
return ix;
|
||||
}
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
byte ix = 0;
|
||||
this.networkId = buffer[ix++];
|
||||
this.thingId = buffer[ix++];
|
||||
this.poseType = buffer[ix++];
|
||||
|
||||
if ((poseType & Pose_Position) != 0)
|
||||
this.position = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
if ((poseType & Pose_Orientation) != 0)
|
||||
this.orientation = LowLevelMessages.ReceiveSwingTwist(buffer, ref ix);
|
||||
if ((poseType & Pose_LinearVelocity) != 0)
|
||||
this.linearVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
if ((poseType & Pose_AngularVelocity) != 0)
|
||||
this.angularVelocity = LowLevelMessages.ReceiveSpherical(buffer, ref ix);
|
||||
}
|
||||
|
||||
public static bool Send(Participant client, byte thingId, Spherical position, SwingTwist orientation) {
|
||||
PoseMsg msg = new(client.networkId, thingId, position, orientation);
|
||||
return SendMsg(client, msg);
|
||||
}
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
PoseMsg msg = new(buffer);
|
||||
|
||||
// Do no process poses with nwid == 0 (== local)
|
||||
if (msg.networkId == 0)
|
||||
return true;
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SendTo(Participant participant, Thing thing) {
|
||||
if (participant == null || thing == null)
|
||||
return false;
|
||||
|
||||
byte ix = 0;
|
||||
participant.buffer[ix++] = PoseMsg.Id;
|
||||
participant.buffer[ix++] = participant.networkId;
|
||||
participant.buffer[ix++] = thing.id;
|
||||
participant.buffer[ix++] = thing.poseUpdated;
|
||||
|
||||
if ((thing.poseUpdated & Pose_Position) != 0 && thing.position != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.position);
|
||||
if ((thing.poseUpdated & Pose_Orientation) != 0 && thing.orientation != null)
|
||||
LowLevelMessages.SendQuat32(participant.buffer, ref ix, thing.orientation);
|
||||
if ((thing.poseUpdated & Pose_LinearVelocity) != 0 && thing.linearVelocity != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.linearVelocity);
|
||||
if ((thing.poseUpdated & Pose_AngularVelocity) != 0 && thing.angularVelocity != null)
|
||||
LowLevelMessages.SendSpherical(participant.buffer, ref ix, thing.angularVelocity);
|
||||
|
||||
return participant.SendBuffer(ix);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
Messages/TextMsg.cs
Normal file
22
Messages/TextMsg.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class TextMsg(byte[] buffer) : IMessage(buffer) {
|
||||
public const byte Id = 0xB0;
|
||||
public string text = "";
|
||||
|
||||
public override void Deserialize(byte[] buffer) {
|
||||
uint ix = 0;
|
||||
uint strlen = buffer[ix++];
|
||||
this.text = System.Text.Encoding.UTF8.GetString(buffer, (int)ix, (int)strlen);
|
||||
}
|
||||
|
||||
public static async Task<bool> Receive(Stream dataStream, Participant client, byte packetSize) {
|
||||
byte[] buffer = await Receive(dataStream, packetSize);
|
||||
TextMsg msg = new(buffer);
|
||||
|
||||
client.messageQueue.Enqueue(msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
@ -13,8 +14,8 @@ namespace Passer.Control.Core {
|
||||
//public byte networkId = 0;
|
||||
public string name = "Participant";
|
||||
|
||||
public IPEndPoint endPoint = null;
|
||||
public UdpClient udpClient = null;
|
||||
public IPEndPoint? endPoint = null;
|
||||
public UdpClient? udpClient = null;
|
||||
public string broadcastIpAddress = "255.255.255.255";
|
||||
|
||||
public readonly ConcurrentQueue<IMessage> messageQueue = new();
|
||||
@ -64,7 +65,7 @@ namespace Passer.Control.Core {
|
||||
|
||||
public List<RemoteParticipant> senders = new();
|
||||
|
||||
public RemoteParticipant GetParticipant(string ipAddress, int port) {
|
||||
public RemoteParticipant? GetParticipant(string ipAddress, int port) {
|
||||
//Console.WriteLine($"Get Participant {ipAddress}:{port}");
|
||||
foreach (RemoteParticipant sender in senders) {
|
||||
if (sender.ipAddress == ipAddress && sender.port == port)
|
||||
@ -81,7 +82,7 @@ namespace Passer.Control.Core {
|
||||
return participant;
|
||||
}
|
||||
|
||||
protected readonly Dictionary<byte, Func<byte, byte, Thing>> thingMsgProcessors = new();
|
||||
protected readonly Dictionary<byte, Func<byte, byte, Thing?>> thingMsgProcessors = new();
|
||||
|
||||
public delegate Thing ThingConstructor(byte networkId, byte thingId);
|
||||
public void Register(byte thingType, ThingConstructor constr) {
|
||||
@ -93,7 +94,7 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
|
||||
public void Register<ThingClass>(byte thingType) where ThingClass : Thing {
|
||||
thingMsgProcessors[thingType] = (byte networkId, byte thingId) =>
|
||||
thingMsgProcessors[thingType] = static (byte networkId, byte thingId) =>
|
||||
Activator.CreateInstance(typeof(ThingClass), networkId, thingId) as ThingClass;
|
||||
Console.WriteLine($"Registering {typeof(ThingClass)} for thing type {thingType}");
|
||||
}
|
||||
@ -103,17 +104,20 @@ namespace Passer.Control.Core {
|
||||
#region Update
|
||||
|
||||
protected void ReceiveUDP(IAsyncResult result) {
|
||||
if (udpClient == null || this.endPoint == null)
|
||||
if (this.udpClient == null || this.endPoint == null)
|
||||
return;
|
||||
|
||||
byte[] data = udpClient.EndReceive(result, ref this.endPoint);
|
||||
byte[] data = this.udpClient.EndReceive(result, ref this.endPoint);
|
||||
// This does not yet take multi-packet messages into account!
|
||||
if (this.endPoint == null)
|
||||
return;
|
||||
|
||||
// We can receive our own publish (broadcast) packages. How do we recognize them????
|
||||
// It is hard to determine our source port
|
||||
RemoteParticipant remoteParticipant = this.GetParticipant(endPoint.Address.ToString(), endPoint.Port);
|
||||
string ipAddress = this.endPoint.Address.ToString();
|
||||
RemoteParticipant? remoteParticipant = GetParticipant(ipAddress, this.endPoint.Port);
|
||||
if (remoteParticipant == null)
|
||||
remoteParticipant = this.AddParticipant(endPoint.Address.ToString(), endPoint.Port);
|
||||
remoteParticipant = AddParticipant(ipAddress, this.endPoint.Port);
|
||||
|
||||
ReceiveData(data, remoteParticipant);
|
||||
|
||||
@ -285,7 +289,7 @@ namespace Passer.Control.Core {
|
||||
|
||||
protected virtual void Process(RemoteParticipant sender, NameMsg msg) {
|
||||
// Console.WriteLine($"Participant: Process name [{msg.networkId}/{msg.thingId}] {msg.name}");
|
||||
Thing thing = sender.Get(msg.networkId, msg.thingId);
|
||||
Thing? thing = sender.Get(msg.networkId, msg.thingId);
|
||||
if (thing != null)
|
||||
thing.name = msg.name;
|
||||
}
|
||||
@ -298,7 +302,7 @@ namespace Passer.Control.Core {
|
||||
|
||||
protected virtual void Process(RemoteParticipant sender, CustomMsg msg) {
|
||||
// Console.WriteLine($"Participant: Process binary [{msg.networkId}/{msg.thingId}]");
|
||||
Thing thing = sender.Get(msg.networkId, msg.thingId);
|
||||
Thing? thing = sender.Get(msg.networkId, msg.thingId);
|
||||
thing?.ProcessBinary(msg.bytes);
|
||||
}
|
||||
|
||||
|
@ -17,18 +17,19 @@ namespace Passer.Control.Core {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
protected readonly List<Thing> things = new();
|
||||
protected readonly List<Thing> things = [];
|
||||
|
||||
public Thing Get(byte networkId, byte thingId) {
|
||||
Thing thing = things.Find(aThing => Thing.IsThing(aThing, networkId, thingId));
|
||||
// if (thing == null)
|
||||
// Console.WriteLine($"Could not find thing {ipAddress}:{port}[{networkId}/{thingId}]");
|
||||
public Thing? Get(byte networkId, byte thingId) {
|
||||
Thing? thing = things.Find(aThing => Thing.IsThing(aThing, networkId, thingId));
|
||||
return thing;
|
||||
}
|
||||
|
||||
// if (thing == null)
|
||||
// Console.WriteLine($"Could not find thing {ipAddress}:{port}[{networkId}/{thingId}]");
|
||||
|
||||
public void Add(Thing thing, bool invokeEvent = true) {
|
||||
// Console.WriteLine($"added thing [{thing.networkId}/{thing.id}]");
|
||||
Thing foundThing = Get(thing.networkId, thing.id);
|
||||
Thing? foundThing = Get(thing.networkId, thing.id);
|
||||
|
||||
if (foundThing == null) {
|
||||
things.Add(thing);
|
||||
|
@ -5,9 +5,9 @@ namespace Passer.Control.Core {
|
||||
public class DistanceSensor : Thing {
|
||||
public float distance = 0;
|
||||
|
||||
public DistanceSensor() : base(true) { }
|
||||
public DistanceSensor(RemoteParticipant participant) : base(participant, true) { }
|
||||
|
||||
public DistanceSensor(byte networkId, byte thingId) : base(null, networkId, thingId, (byte)Type.TemperatureSensor) {
|
||||
public DistanceSensor(RemoteParticipant participant, byte networkId, byte thingId) : base(participant, networkId, thingId, (byte)Type.TemperatureSensor) {
|
||||
}
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
|
@ -2,11 +2,8 @@ using System;
|
||||
|
||||
namespace Passer.Control.Core {
|
||||
|
||||
public class TemperatureSensor : Thing {
|
||||
public class TemperatureSensor(Participant participant, byte networkId, byte thingId) : Thing(participant, networkId, thingId, (byte)Type.TemperatureSensor) {
|
||||
public float temp = 0;
|
||||
|
||||
public TemperatureSensor(byte networkId, byte thingId) : base(null, networkId, thingId, (byte)Type.TemperatureSensor) {
|
||||
}
|
||||
|
||||
public override void ProcessBinary(byte[] bytes) {
|
||||
byte ix = 0;
|
||||
|
@ -1,12 +1,8 @@
|
||||
|
||||
namespace Passer.Control.Core {
|
||||
public class TouchSensor : Thing {
|
||||
//public Thing touchedThing = null;
|
||||
|
||||
public class TouchSensor(RemoteParticipant participant, bool invokeEvent = true) : Thing(participant, invokeEvent) {
|
||||
public bool touchedSomething = false;
|
||||
|
||||
public TouchSensor(bool invokeEvent = true) : base(invokeEvent) {
|
||||
}
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
public override void CreateComponent() {
|
||||
this.component = Unity.TouchSensor.Create(this);
|
||||
|
@ -23,10 +23,10 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
this.udpClient.Close();
|
||||
this.udpClient?.Close();
|
||||
}
|
||||
|
||||
public override void Publish() {
|
||||
public override void Publish() {
|
||||
}
|
||||
|
||||
protected override void Process(RemoteParticipant sender, ClientMsg msg) {
|
||||
@ -40,13 +40,15 @@ namespace Passer.Control.Core {
|
||||
|
||||
protected override void Process(RemoteParticipant sender, ThingMsg msg) {
|
||||
//Console.WriteLine($"SiteServer: Process thing [{msg.networkId}/{msg.thingId}]");
|
||||
Thing thing = sender.Get(msg.networkId, msg.thingId);
|
||||
Thing? thing = sender.Get(msg.networkId, msg.thingId);
|
||||
if (thing == null) {
|
||||
Thing newThing;
|
||||
if (thingMsgProcessors.ContainsKey(msg.thingType))
|
||||
newThing = thingMsgProcessors[msg.thingType](msg.networkId, msg.thingId);
|
||||
else
|
||||
newThing = new Thing(sender, msg.networkId, msg.thingId, msg.thingType);
|
||||
Thing? newThing = null;
|
||||
if (thingMsgProcessors.TryGetValue(msg.thingType, out Func<byte, byte, Thing?>? value)) {
|
||||
if (value != null)
|
||||
newThing = value(msg.networkId, msg.thingId);
|
||||
}
|
||||
newThing ??= new Thing(sender, msg.networkId, msg.thingId, msg.thingType);
|
||||
|
||||
sender.Add(newThing);
|
||||
}
|
||||
}
|
||||
|
43
Thing.cs
43
Thing.cs
@ -41,16 +41,16 @@ namespace Passer.Control.Core {
|
||||
public byte networkId;
|
||||
public byte id;
|
||||
|
||||
public event ChangeHandler OnParentChanged;
|
||||
private Thing _parent;
|
||||
public Thing parent {
|
||||
public event ChangeHandler OnParentChanged = delegate {};
|
||||
private Thing? _parent;
|
||||
public Thing? parent {
|
||||
get => _parent;
|
||||
set {
|
||||
if (_parent == value)
|
||||
return;
|
||||
|
||||
if (value == null) {
|
||||
_parent.RemoveChild(this);
|
||||
_parent?.RemoveChild(this);
|
||||
_parent = null;
|
||||
}
|
||||
else {
|
||||
@ -74,8 +74,8 @@ namespace Passer.Control.Core {
|
||||
public List<Thing> children = new List<Thing>();
|
||||
public byte type;
|
||||
|
||||
public event ChangeHandler OnNameChanged;
|
||||
private string _name;
|
||||
public event ChangeHandler OnNameChanged = delegate {};
|
||||
private string _name = "";
|
||||
public virtual string name {
|
||||
get => _name;
|
||||
set {
|
||||
@ -86,11 +86,11 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
}
|
||||
|
||||
public string modelUrl;
|
||||
public string modelUrl = "";
|
||||
|
||||
public byte poseUpdated = 0x00;
|
||||
public event ChangeHandler OnPositionChanged;
|
||||
private Spherical _position;
|
||||
public event ChangeHandler OnPositionChanged = delegate {};
|
||||
private Spherical _position = Spherical.zero;
|
||||
public Spherical position {
|
||||
get { return _position; }
|
||||
set {
|
||||
@ -101,8 +101,8 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
}
|
||||
|
||||
public event ChangeHandler OnOrientationChanged;
|
||||
private SwingTwist _orientation;
|
||||
public event ChangeHandler OnOrientationChanged = delegate {};
|
||||
private SwingTwist _orientation = SwingTwist.zero;
|
||||
public SwingTwist orientation {
|
||||
get { return _orientation; }
|
||||
set {
|
||||
@ -113,8 +113,8 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
}
|
||||
|
||||
public event SphericalHandler OnLinearVelocityChanged;
|
||||
private Spherical _linearVelocity;
|
||||
public event SphericalHandler OnLinearVelocityChanged = delegate {};
|
||||
private Spherical _linearVelocity = Spherical.zero;
|
||||
public Spherical linearVelocity {
|
||||
get => _linearVelocity;
|
||||
set {
|
||||
@ -124,7 +124,7 @@ namespace Passer.Control.Core {
|
||||
}
|
||||
}
|
||||
}
|
||||
public Spherical angularVelocity;
|
||||
public Spherical angularVelocity = Spherical.zero;
|
||||
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
[NonSerialized]
|
||||
@ -135,12 +135,8 @@ namespace Passer.Control.Core {
|
||||
|
||||
#region Init
|
||||
|
||||
// public virtual void Init(bool invokeEvent = false) {
|
||||
// if (invokeEvent)
|
||||
// InvokeNewThing(this);
|
||||
// }
|
||||
|
||||
public Thing(bool invokeEvent = false) {
|
||||
public Thing(RemoteParticipant participant, bool invokeEvent = false) {
|
||||
this.participant = participant;
|
||||
if (invokeEvent)
|
||||
InvokeNewThing(this);
|
||||
}
|
||||
@ -149,9 +145,6 @@ namespace Passer.Control.Core {
|
||||
this.id = thingId;
|
||||
this.type = thingType;
|
||||
this.networkId = networkId;
|
||||
//this.Init();
|
||||
//OnNewThing?.Invoke(this);
|
||||
//Thing.Add(this);
|
||||
}
|
||||
|
||||
public virtual void CreateComponent() {}
|
||||
@ -195,10 +188,10 @@ namespace Passer.Control.Core {
|
||||
|
||||
//---------- All Things
|
||||
|
||||
private static readonly List<Thing> allThings = new();
|
||||
private static readonly List<Thing> allThings = [];
|
||||
|
||||
public delegate void ThingHandler(Thing t);
|
||||
public static event ThingHandler OnNewThing;
|
||||
public static event ThingHandler OnNewThing = delegate {};
|
||||
public static void InvokeNewThing(Thing thing) {
|
||||
OnNewThing?.Invoke(thing);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ namespace ControlCore.test {
|
||||
public void Test_ThingMsg() {
|
||||
SiteServer siteServer = new();
|
||||
Participant participant = new("127.0.0.1");
|
||||
Thing thing = new() {
|
||||
Thing thing = new(participant) {
|
||||
name = "First Thing",
|
||||
modelUrl = "https://passer.life/extras/ant.jpg"
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user