braille_xr/sk_demo/src/Mono.cs
2024-04-30 17:15:42 -04:00

410 lines
No EOL
8.7 KiB
C#

using System.Security.AccessControl;
namespace Main;
public class Mono {
private static readonly Lazy<Mono> lazy = new(() => new Mono());
public static Mono inst { get { return lazy.Value; } }
public static readonly bool dev = Environment.CommandLine.Contains("--dev");
public MonoNet monoNet = new();
public Rig rig = new();
public Mat mat = new();
Mesh mesh_floor = Mesh.Quad;
Material mat_room = new (Shader.FromFile("shaders/room.hlsl"));
Model model_room = Model.FromFile("room.glb");
Mesh mesh_room = Mesh.Quad;
// key:(char) value:(int[] dots)
Dictionary<char, int[]> char_cell = new Dictionary<char, int[]> {
{ ' ', new int[] {
0, 0,
0, 0,
0, 0
} },
{ '\n', new int[] {
1, 1,
1, 1,
1, 1
} },
{ 'a', new int[] {
1, 0,
0, 0,
0, 0
} },
{ 'b', new int[] {
1, 0,
1, 0,
0, 0
} },
{ 'c', new int[] {
1, 1,
0, 0,
0, 0
} },
{ 'd', new int[] {
1, 1,
0, 1,
0, 0
} },
{ 'e', new int[] {
1, 0,
0, 1,
0, 0
} },
{ 'f', new int[] {
1, 1,
1, 0,
0, 0
} },
{ 'g', new int[] {
1, 1,
1, 1,
0, 0
} },
{ 'h', new int[] {
1, 0,
1, 1,
0, 0
} },
{ 'i', new int[] {
0, 1,
1, 0,
0, 0
} },
{ 'j', new int[] {
0, 1,
1, 1,
0, 0
} },
{ 'k', new int[] {
1, 0,
0, 0,
1, 0
} },
{ 'l', new int[] {
1, 0,
1, 0,
1, 0
} },
{ 'm', new int[] {
1, 1,
0, 0,
1, 0
} },
{ 'n', new int[] {
1, 1,
0, 1,
1, 0
} },
{ 'o', new int[] {
1, 0,
0, 1,
1, 0
} },
{ 'p', new int[] {
1, 1,
1, 0,
1, 0
} },
{ 'q', new int[] {
1, 1,
1, 1,
1, 0
} },
{ 'r', new int[] {
1, 0,
1, 1,
1, 0
} },
{ 's', new int[] {
0, 1,
1, 0,
1, 0
} },
{ 't', new int[] {
0, 1,
1, 1,
1, 0
} },
{ 'u', new int[] {
1, 0,
0, 0,
1, 1
} },
{ 'v', new int[] {
1, 0,
1, 0,
1, 1
} },
{ 'w', new int[] {
0, 1,
1, 1,
0, 1
} },
{ 'x', new int[] {
1, 1,
0, 0,
1, 1
} },
{ 'y', new int[] {
1, 1,
0, 1,
1, 1
} },
{ 'z', new int[] {
1, 0,
0, 1,
1, 1
} },
{ ',', new int[] {
0, 0,
1, 0,
0, 0
} },
{ '.', new int[] {
0, 0,
1, 1,
0, 1
} },
{ '/', new int[] {
0, 1,
0, 0,
1, 0
} },
{ ';', new int[] {
0, 0,
1, 0,
1, 0
} },
};
// enum of layouts
public enum Layout {
Qwerty,
Colemak
}
Dictionary<Layout, char[]> layouts = new Dictionary<Layout, char[]> {
{ Layout.Colemak, new char[] {
'q', 'w', 'f', 'p', 'g', 'j', 'l', 'u', 'y', ';',
'a', 'r', 's', 't', 'd', 'h', 'n', 'e', 'i', 'o',
'z', 'x', 'c', 'v', 'b', 'k', 'm', ',', '.', '/',
} },
{ Layout.Qwerty, new char[] {
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
} },
};
public char KeyToChar(int index) {
return layouts[Layout.Colemak][index];
}
Matrix keyboard_m4 = Matrix.Identity;
Rig.Btn keyboard_btn = new();
Vec3 index_pos = Vec3.Zero;
int index_i = 0;
int last_index_i = 0;
string txt = "hello ";
public void Init() {
rig.Init();
mat.Init();
mesh_floor = Mesh.GenerateCircle(1, 64);
mat_room.SetTexture("diffuse", Tex.FromFile("bake.png"));
mesh_room = model_room.Nodes.First(n => n.Name == "Room").Mesh;
keyboard_btn.held = true;
}
public void Run() {
rig.Run();
keyboard_m4 = Matrix.TRS(
V.XYZ(-0.18f, 1.15f, -0.5f),
Quat.FromAngles(0, 180, 0) * Quat.FromAngles(40, 0, 0),
V.XYZ(-1, -1, 1) * 0.04f
);
// thumb extension
// Matrix palm_ori = rig.hand_1.palm.ToMatrix();
// Vec3 thumb_tip = palm_ori.Inverse * rig.hand_1.Get(FingerId.Thumb, JointId.Tip).position;
// Vec3 thumb_minor = palm_ori.Inverse * rig.hand_1.Get(FingerId.Thumb, JointId.KnuckleMinor).position;
// if (thumb_tip.x < thumb_minor.x - 0f * U.cm) {
// // Log.Info("thumb is out");
// xi = 0;
// }
for (int i = 0; i < keb_keys.Length-1; i++) {
if (Input.Key(keb_keys[i].key).IsJustActive()) {
txt += keb_keys[i].char_;
monoNet.value = keb_keys[i].char_;
monoNet.send = true;
}
}
Vec3 index_tip = keyboard_m4.Inverse * rig.hand_1.Get(FingerId.Index, JointId.Tip).position;
// press
index_pos.z = Math.Clamp(index_tip.z, -0.3f, 0.1f);
keyboard_btn.Frame(index_pos.z > 0.0f, index_pos.z < -0.2f);
if (!keyboard_btn.held) {
// snap to grid
index_pos.x = (float)Math.Clamp(Math.Round(index_tip.x), 0, 10-1);
index_pos.y = (float)Math.Clamp(Math.Round(index_tip.y), 0, 3-1);
index_i = (int)(index_pos.y * 10 + index_pos.x);
if (index_i != last_index_i) {
last_index_i = index_i;
// Log.Info($"index_i: {index_i}");
monoNet.value = KeyToChar(index_i);
monoNet.send = true;
}
}
if (keyboard_btn.frameDown) {
// send haptic input for input confirmation
txt += KeyToChar(index_i);
}
// RENDER RENDER RENDER
// keyboard
Hierarchy.Push(keyboard_m4);
// 3 rows of 10 keys
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 10; x++) {
Vec3 pos = V.XYZ(x, y, 0);
// background quad
Mesh.Quad.Draw(
mat.unlit_clear,
Matrix.TS(pos, 0.9f),
Color.Hex(0x00000040)
);
int index = y * 10 + x;
char keychar = KeyToChar(index);
Text.Add(
keychar.ToString(),
Matrix.TS(
pos + V.XYZ(-0.3f, -0.3f, 0),
V.XYZ(-1, -1, 0) * 8.0f
),
TextAlign.Center,
TextAlign.Center,
0, 0, 0
);
// show the braille dots(spheres) above the text
for (int k = 0; k < 6; k++) {
float spacing = 0.2f;
float x_offset = (k % 2) * spacing;
float y_offset = (k / 2) * -spacing;
if (char_cell[keychar][k] == 1) {
Mesh.Sphere.Draw(
mat.unlit_clear,
Matrix.TS(
V.XYZ(pos.x + x_offset, pos.y - y_offset, 0) + V.XYZ(-0.1f, -0.18f, 0),
0.1f
),
Color.Hex(0xFFFFFFFF)
);
}
}
}
}
Hierarchy.Pop();
// keyboard button
Mesh.Cube.Draw(
mat.unlit_clear,
Matrix.TS(
index_pos * V.XYZ(1, 1, 0.25f),
V.XYZ(0.8f, 0.8f, -index_pos.z * 0.5f)
) * keyboard_m4,
keyboard_btn.held ? Color.Hex(0x00000090) : Color.Hex(0x80808090)
);
// text
// show over the keyboard
Text.Add(
txt,
Matrix.TS(
V.XYZ(0, -1, 0),
V.XYZ(-1, -1, 0) * 20.0f
) * keyboard_m4,
TextAlign.CenterLeft,
TextAlign.CenterLeft,
0, 0, 0
);
// WORLD
mesh_room.Draw(
mat_room,
Matrix.T(V.XYZ(0, 0, 0))
);
mesh_floor.Draw(
mat.unlit,
Matrix.TS(
V.XYZ(0, 0, 0),
1*U.cm
),
Color.Hex(0x666666FF)
);
Vec3[] offsets = new Vec3[] {
V.XYZ(-2, -2f, -2f) * U.cm,
V.XYZ(2, 2f, 2f) * U.cm,
V.XYZ(0, 0, 0)
};
mat.Run();
}
KebKey[] keb_keys = new KebKey[] {
new() { key = Key.Space, char_ = ' ' },
new() { key = Key.Return, char_ = '\n' },
new() { key = Key.A, char_ = 'a' },
new() { key = Key.B, char_ = 'b' },
new() { key = Key.C, char_ = 'c' },
new() { key = Key.D, char_ = 'd' },
new() { key = Key.E, char_ = 'e' },
new() { key = Key.F, char_ = 'f' },
new() { key = Key.G, char_ = 'g' },
new() { key = Key.H, char_ = 'h' },
new() { key = Key.I, char_ = 'i' },
new() { key = Key.J, char_ = 'j' },
new() { key = Key.K, char_ = 'k' },
new() { key = Key.L, char_ = 'l' },
new() { key = Key.M, char_ = 'm' },
new() { key = Key.N, char_ = 'n' },
new() { key = Key.O, char_ = 'o' },
new() { key = Key.P, char_ = 'p' },
new() { key = Key.Q, char_ = 'q' },
new() { key = Key.R, char_ = 'r' },
new() { key = Key.S, char_ = 's' },
new() { key = Key.T, char_ = 't' },
new() { key = Key.U, char_ = 'u' },
new() { key = Key.V, char_ = 'v' },
new() { key = Key.W, char_ = 'w' },
new() { key = Key.X, char_ = 'x' },
new() { key = Key.Y, char_ = 'y' },
new() { key = Key.Z, char_ = 'z' },
};
public struct KebKey {
public Key key;
public char char_;
}
}