Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions Runtime/Dividat/PluginWrapper/Hardware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static void Wire()
#if UNITY_WEBGL && !UNITY_EDITOR
Register(OnStep, OnRelease, OnSensoState);
#else
Debug.LogWarning("SENSO Hardware is not supported on this platform. Plates can be simulated with LEFT, RIGHT, UP, DOWN arrows and SPACE key");
WebsocketAvatar.Register(OnStep, OnRelease, OnSensoState);
#endif
}

Expand Down Expand Up @@ -107,28 +107,16 @@ private static int GetFrameCount(Direction direction)
#endregion

#region EGIBridge
#if UNITY_WEBGL
// Implementation of Bridge to EGI
// Based on ideas from https://forum.unity.com/threads/c-jslib-2-way-communication.323629/#post-2100593

public delegate void DirectionCallback(int direction);
public delegate void PlateCallback(int direction, float x, float y, float f);

[DllImport("__Internal")]
private static extern void Register(DirectionCallback onStep, DirectionCallback onRelease, PlateCallback onSensoState);

[DllImport("__Internal")]
private static extern void SendMotorPreset(string keyword);

private static void SetPlateState(int direction, float x, float y, float f)
{
plates[direction].x = x;
plates[direction].y = y;
plates[direction].f = f;
}



[MonoPInvokeCallback(typeof(DirectionCallback))]
private static void OnStep(int direction)
{
Expand All @@ -146,6 +134,16 @@ private static void OnSensoState(int direction, float x, float y, float f)
{
SetPlateState(direction, x, y, f);
}
#if UNITY_WEBGL
// Implementation of Bridge to EGI
// Based on ideas from https://forum.unity.com/threads/c-jslib-2-way-communication.323629/#post-2100593

[DllImport("__Internal")]
private static extern void Register(DirectionCallback onStep, DirectionCallback onRelease, PlateCallback onSensoState);

[DllImport("__Internal")]
private static extern void SendMotorPreset(string keyword);
#else
#endif
#endregion EGIBridge
}
Expand Down
154 changes: 154 additions & 0 deletions Runtime/Dividat/PluginWrapper/WebsocketAvatar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SimpleJSON;
using Dividat;

using NativeWebSocket;

public class WebsocketAvatar : MonoBehaviour
{
WebSocket _websocket;
[Header("Network Configuration")]
public string serverURL = "wss://rooms.dividat.com/rooms/unity-avatar/join";
public bool automaticReconnect = true;
[Range(0.2f, 10f)]
public float retryEvery = 2f;

public bool Connected {
get { return _connected;}
}
private bool _connected = false;
private float _retryTimer = 0f;

private static Hardware.DirectionCallback _onStep;
private static Hardware.DirectionCallback _onRelease;
private static Hardware.PlateCallback _onSensoState;

// Start is called before the first frame update
void Start()
{
Debug.Log("Starting EGI");
Connect();
}

public static void Register(Hardware.DirectionCallback onStep, Hardware.DirectionCallback onRelease, Hardware.PlateCallback onSensoState)
{
_onStep = onStep;
_onRelease = onRelease;
_onSensoState = onSensoState;
}

///Note that the connection request is asynchronous. You can not expect values right away, but only after connected is true.
public void Connect(){
ConnectSocket();
}
void ConnectSocket(){
Connect(serverURL);
}

async void Connect(string url){
_websocket = new WebSocket(url);

_websocket.OnOpen += () =>
{
Debug.Log("EGI WS avatar connection open!");
_connected = true;

};

_websocket.OnError += (e) =>
{
Debug.Log("Error in EGI WS avatar: " + e);
};

_websocket.OnClose += (e) =>
{
Debug.Log("EGI WS avatar connection closed!");
_connected = false;
_retryTimer = 0f;
};

_websocket.OnMessage += (bytes) =>
{
// Reading a plain text message
var message = System.Text.Encoding.UTF8.GetString(bytes);
var json = JSON.Parse(message);

switch (json["type"].Value)
{
case "Step":
_onStep(1);
break;
case "Release":
_onRelease(1);
break;
case "SensoState":
_onSensoState(0,
json["state"]["center"]["x"].AsFloat,
json["state"]["center"]["y"].AsFloat,
json["state"]["center"]["f"].AsFloat);
_onSensoState(1,
json["state"]["up"]["x"].AsFloat,
json["state"]["up"]["y"].AsFloat,
json["state"]["up"]["f"].AsFloat);
_onSensoState(2,
json["state"]["right"]["x"].AsFloat,
json["state"]["right"]["y"].AsFloat,
json["state"]["right"]["f"].AsFloat);
_onSensoState(3,
json["state"]["down"]["x"].AsFloat,
json["state"]["down"]["y"].AsFloat,
json["state"]["down"]["f"].AsFloat);
_onSensoState(4,
json["state"]["left"]["x"].AsFloat,
json["state"]["left"]["y"].AsFloat,
json["state"]["left"]["f"].AsFloat);
break;
}

_retryTimer = 0f;
};
await _websocket.Connect();
}

void Update()
{
if (_websocket != null){
#if !UNITY_WEBGL || UNITY_EDITOR
_websocket.DispatchMessageQueue();
#endif

if (automaticReconnect && !_connected){
_retryTimer += Time.deltaTime;
if (_retryTimer >= retryEvery){
_retryTimer=0f;
_websocket.Connect();
}
}
}
}

async void SendWebSocketTextMessage(string message)
{
if (_websocket.State == WebSocketState.Open)
{
await _websocket.SendText(message);
}
}

async void SendWebSocketBinaryMessage(byte[] binaryMessage)
{
if (_websocket.State == WebSocketState.Open)
{
// Sending bytes
await _websocket.Send(binaryMessage);
}
}

private async void OnDestroy()
{
await _websocket.Close();
}
}
11 changes: 11 additions & 0 deletions Runtime/Dividat/PluginWrapper/WebsocketAvatar.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.