Skip to content
This repository has been archived by the owner on Nov 9, 2023. It is now read-only.

Commit

Permalink
New stuff
Browse files Browse the repository at this point in the history
New Nodes:


LogiX/Input Devices:

ViveTrackerByBodyNode
ViveTrackerByIndex
ViveTrackerCount

LogiX/Math/Random:

Random Euler Angles

LogiX/Network:

Get Stock Price
RSS Feed

LogiX/String:

HMAC

LogiX/Users:

IsUserEyeTracking
  • Loading branch information
Xlinka committed Jun 18, 2023
2 parents 2a4e834 + be2a44d commit a537e6c
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 0 deletions.
55 changes: 55 additions & 0 deletions NEOSPlus/Logix/Input Devices/TrackerBatteryBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FrooxEngine;
using FrooxEngine.LogiX;

namespace NEOSPlus.Logix.Input_Devices
{
// TODO: check in multiplayer to make sure this all syncs correctly.
// Update 6/17/2023 It Works
public abstract class TrackerBatteryBase : LogixNode
{
public readonly Input<User> User;
public readonly Output<float> BatteryLevel;
public readonly Output<bool> IsBatteryCharging;

internal ViveTracker _lastTracker;
protected readonly SyncRef<ValueStream<float>> _batteryLevelStream;
protected readonly SyncRef<ValueStream<bool>> _batteryChargingStream;

internal abstract ViveTracker GetViveTracker();

protected override void OnCommonUpdate()
{
base.OnCommonUpdate();
User user = User.Evaluate();
if (user == base.LocalUser)
{
ViveTracker device = GetViveTracker();
if (device != _lastTracker)
{
_batteryLevelStream.Target = device?.BatteryLevel.GetStream(base.World);
_batteryChargingStream.Target = device?.BatteryCharging.GetStream(base.World);
_lastTracker = device;
}
}
else
{
_lastTracker = null;
if (base.World.IsAuthority && user == null)
{
_batteryLevelStream.Target = null;
_batteryChargingStream.Target = null;
}
}
}
protected override void OnEvaluate()
{
BatteryLevel.Value = _batteryLevelStream.Target?.Value ?? (-1f);
IsBatteryCharging.Value = _batteryChargingStream.Target?.Value ?? false;
}
}
}
15 changes: 15 additions & 0 deletions NEOSPlus/Logix/Input Devices/ViveTrackerByBodyNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using BaseX;
using FrooxEngine;
using FrooxEngine.LogiX;
using System.Linq;
using System.Collections.Generic;
using NEOSPlus.Logix.Input_Devices;

[Category("LogiX/Input Devices")]
public class ViveTrackerByBodyNode : TrackerBatteryBase
{
public readonly Input<BodyNode> BodyNode;

internal override ViveTracker GetViveTracker() => InputInterface.GetDevices<ViveTracker>().Find((t) => t.CorrespondingBodyNode == BodyNode.Evaluate());
}
25 changes: 25 additions & 0 deletions NEOSPlus/Logix/Input Devices/ViveTrackerByIndex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FrooxEngine;
using FrooxEngine.LogiX;

namespace NEOSPlus.Logix.Input_Devices
{
[Category("LogiX/Input Devices")]
public class ViveTrackerByIndex : TrackerBatteryBase
{
public readonly Input<int> TrackerIndex;

internal override ViveTracker GetViveTracker()
{
var idx = TrackerIndex.Evaluate();
if (idx < 0) return null;
var trackers = InputInterface.GetDevices<ViveTracker>();
if (idx >= trackers.Count) return null;
return trackers[idx];
}
}
}
41 changes: 41 additions & 0 deletions NEOSPlus/Logix/Input Devices/ViveTrackerCount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FrooxEngine;
using FrooxEngine.LogiX;

namespace NEOSPlus.Logix.Input_Devices
{
[Category("LogiX/Input Devices")]
public class ViveTrackerCount : LogixNode
{
public readonly Input<User> User;
public readonly Output<int> Count;

public readonly Sync<int> _count;

protected override void OnCommonUpdate()
{
base.OnCommonUpdate();
User user = User.Evaluate();
if (user == base.LocalUser)
{
_count.Value = InputInterface.GetDevices<ViveTracker>().Count;
}
else
{
if (World.IsAuthority && user == null)
{
_count.Value = -1;
}
}
}

protected override void OnEvaluate()
{
Count.Value = _count.Value;
}
}
}
25 changes: 25 additions & 0 deletions NEOSPlus/Logix/Math/Random/RandomEuler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using BaseX;
using FrooxEngine;
using FrooxEngine.LogiX;

[Category("LogiX/Math/Random")]
[NodeName("Random Euler Angles")]
public class RandomEulerAngles : LogixNode
{
public readonly Input<float> minPitch;
public readonly Input<float> maxPitch;
public readonly Input<float> minYaw;
public readonly Input<float> maxYaw;
public readonly Input<float> minRoll;
public readonly Input<float> maxRoll;
public readonly Output<float3> euler;

protected override void OnEvaluate()
{
float pitch = RandomX.Range(minPitch.Evaluate(), maxPitch.Evaluate());
float yaw = RandomX.Range(minYaw.Evaluate(), maxYaw.Evaluate());
float roll = RandomX.Range(minRoll.Evaluate(), maxRoll.Evaluate());

euler.Value = new float3(pitch, yaw, roll);
}
}
72 changes: 72 additions & 0 deletions NEOSPlus/Logix/Network/GetStockPrice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using BaseX;
using FrooxEngine;
using FrooxEngine.LogiX;
using Newtonsoft.Json.Linq;

namespace FrooxEngine.LogiX.Network
{
[Category("LogiX/Network")]
[NodeName("Get Stock Price")]
public class GetStockPriceNode : LogixNode
{
public readonly Impulse onSent;
public readonly Impulse onResponse;
public readonly Impulse onError;
public readonly Input<string> stockSymbol;
public readonly Output<decimal> stockPrice;
public readonly Output<int> statusCode;

[ImpulseTarget]
public void SendRequest() => StartTask(new Func<Task>(this.RunRequest));

private async Task RunRequest()
{
string symbol = stockSymbol.Evaluate();
if (string.IsNullOrEmpty(symbol))
{
UniLog.Warning("Stock symbol is empty.");
onError.Trigger();
return;
}

string requestUrl = $"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?interval=1d";

if (await Engine.Security.RequestAccessPermission("query1.finance.yahoo.com", 443, null) != HostAccessPermission.Allowed)
{
UniLog.Warning("Access to the Yahoo Finance API was not granted.");
onError.Trigger();
return;
}

// Send the request to Yahoo Finance API and wait for the response
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(requestUrl))
using (HttpContent content = response.Content)
{
string responseString = await content.ReadAsStringAsync();
JObject jsonResponse = JObject.Parse(responseString);

// Extract the stock price from the response JSON
JArray resultArray = (JArray)jsonResponse["chart"]["result"];
if (resultArray.Count == 0)
{
UniLog.Warning($"Failed to get stock price for symbol '{symbol}'.");
onError.Trigger();
return;
}

JObject result = (JObject)resultArray[0];
JObject meta = (JObject)result["meta"];
decimal price = (decimal)meta["regularMarketPrice"];

// Return the stock price as output
stockPrice.Value = price;
statusCode.Value = (int)response.StatusCode;
onResponse.Trigger();
}
}
}
}
54 changes: 54 additions & 0 deletions NEOSPlus/Logix/Network/RSSFeed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json.Linq;
using FrooxEngine;
using FrooxEngine.LogiX;
using BaseX;
using System.Xml;

namespace LogiX.Network
{
[Category("LogiX/Network")]
[NodeName("RSS Feed")]
public class RSSFeedNode : LogixNode
{
public readonly Input<Uri> FeedURL;
public readonly Output<JArray> FeedItems;

protected override void OnEvaluate()
{
Uri feedURL = FeedURL.Evaluate();
JArray items = new JArray();

try
{
// Retrieve RSS feed content
WebClient client = new WebClient();
string feedContent = client.DownloadString(feedURL);

// Parse the XML content
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(feedContent);

// Extract feed items
XmlNodeList itemNodes = xmlDoc.SelectNodes("//item");
foreach (XmlNode itemNode in itemNodes)
{
JObject item = new JObject();
item["title"] = itemNode.SelectSingleNode("title")?.InnerText;
item["description"] = itemNode.SelectSingleNode("description")?.InnerText;
item["pubDate"] = itemNode.SelectSingleNode("pubDate")?.InnerText;
item["link"] = itemNode.SelectSingleNode("link")?.InnerText;
items.Add(item);
}
}
catch (Exception ex)
{
UniLog.Log("Error retrieving or parsing RSS feed: " + ex.Message);
}

FeedItems.Value = items;
}
}
}
66 changes: 66 additions & 0 deletions NEOSPlus/Logix/String/HMAC.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Security.Cryptography;
using BaseX;
using FrooxEngine;
using FrooxEngine.LogiX;

public enum HashFunction
{
MD5,
SHA1,
SHA256,
SHA384,
SHA512
}

[Category("LogiX/String")]
[NodeName("HMAC")]
public class HMACNode : LogixNode
{
public readonly Input<string> Message;
public readonly Input<string> Key;
public readonly Input<HashFunction> HashAlgorithm;

public readonly Output<string> Result;

protected override void OnEvaluate()
{
string message = Message.Evaluate();
string key = Key.Evaluate();
HashFunction hashFunction = HashAlgorithm.Evaluate();

if (string.IsNullOrEmpty(message) || string.IsNullOrEmpty(key))
{
Result.Value = "";
return;
}

byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(key);
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(message);

using (HMAC hmac = GetHMAC(hashFunction, keyBytes))
{
byte[] hash = hmac.ComputeHash(messageBytes);
Result.Value = BitConverter.ToString(hash).Replace("-", "");
}
}

private HMAC GetHMAC(HashFunction hashFunction, byte[] key)
{
switch (hashFunction)
{
case HashFunction.MD5:
return new HMACMD5(key);
case HashFunction.SHA1:
return new HMACSHA1(key);
case HashFunction.SHA256:
return new HMACSHA256(key);
case HashFunction.SHA384:
return new HMACSHA384(key);
case HashFunction.SHA512:
return new HMACSHA512(key);
default:
throw new ArgumentException($"Unsupported hash function {hashFunction}");
}
}
}
33 changes: 33 additions & 0 deletions NEOSPlus/Logix/Users/IsUserEyeTracking.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using FrooxEngine;
using FrooxEngine.LogiX;

[Category("LogiX/Users")]
[NodeName("IsUserEyeTracking")]
public class IsUserEyeTracking : LogixNode
{
public readonly Input<User> User;
public readonly Input<EyeSide> Side;
public readonly Output<bool> EyeTracking;

private EyeTrackingStreamManager eyeTrackingStreamManager;

protected override void OnAttach()
{
eyeTrackingStreamManager = base.LocalUserRoot.GetRegisteredComponent<EyeTrackingStreamManager>();
}

protected override void OnEvaluate()
{
User user = User.Evaluate();
if (user != null && eyeTrackingStreamManager != null)
{
EyeSide side = Side.Evaluate(); // Get the EyeSide value from the input
bool eyeTracking = eyeTrackingStreamManager.GetIsTracking(side);
EyeTracking.Value = eyeTracking;
}
else
{
EyeTracking.Value = false;
}
}
}

0 comments on commit a537e6c

Please sign in to comment.