410 lines
No EOL
8.7 KiB
C#
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_;
|
|
}
|
|
} |