diff --git a/ProjectObsidian.csproj b/ProjectObsidian.csproj
index 9738e67..646ffcc 100644
--- a/ProjectObsidian.csproj
+++ b/ProjectObsidian.csproj
@@ -40,9 +40,6 @@
$(ResonitePath)Resonite_Data/Managed/Elements.Assets.dll
-
- $(ResonitePath)/Managed/SteamVR.dll
-
diff --git a/ProtoFlux/Bindings/Utility/writetolog.cs b/ProtoFlux/Bindings/Utility/writetolog.cs
new file mode 100644
index 0000000..d40c26b
--- /dev/null
+++ b/ProtoFlux/Bindings/Utility/writetolog.cs
@@ -0,0 +1,96 @@
+using System;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using FrooxEngine.ProtoFlux.Runtimes.Execution;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution.Nodes.Obsidian.Utility;
+
+
+[Category(new string[] { "ProtoFlux/Runtimes/Execution/Nodes/Obsidian/Utility" })]
+public class WriteToLogBinding : AsyncActionNode
+{
+ public readonly SyncRef> Value;
+ public readonly SyncRef> Severity;
+ public readonly SyncRef> Tag;
+ public readonly SyncRef> HandlingUser;
+
+ public readonly SyncRef OnWriteStart;
+ public readonly SyncRef OnWriteComplete;
+
+ public override Type NodeType => typeof(WriteToLogNode);
+
+ public WriteToLogNode TypedNodeInstance { get; private set; }
+
+ public override INode NodeInstance => TypedNodeInstance;
+
+ public override int NodeInputCount => base.NodeInputCount + 4;
+
+ public override int NodeImpulseCount => base.NodeImpulseCount + 2;
+
+ public override N Instantiate()
+ {
+ if (TypedNodeInstance != null)
+ {
+ throw new InvalidOperationException("Node has already been instantiated");
+ }
+ WriteToLogNode writeToLogNode = (TypedNodeInstance = new WriteToLogNode());
+ return writeToLogNode as N;
+ }
+
+ protected override void AssociateInstanceInternal(INode node)
+ {
+ if (node is WriteToLogNode typedNodeInstance)
+ {
+ TypedNodeInstance = typedNodeInstance;
+ return;
+ }
+ throw new ArgumentException("Node instance is not of type " + typeof(WriteToLogNode));
+ }
+
+ public override void ClearInstance()
+ {
+ TypedNodeInstance = null;
+ }
+
+ protected override ISyncRef GetInputInternal(ref int index)
+ {
+ ISyncRef inputInternal = base.GetInputInternal(ref index);
+ if (inputInternal != null)
+ {
+ return inputInternal;
+ }
+ switch (index)
+ {
+ case 0:
+ return Value;
+ case 1:
+ return Severity;
+ case 2:
+ return Tag;
+ case 3:
+ return HandlingUser;
+ default:
+ index -= 4;
+ return null;
+ }
+ }
+
+ protected override ISyncRef GetImpulseInternal(ref int index)
+ {
+ ISyncRef impulseInternal = base.GetImpulseInternal(ref index);
+ if (impulseInternal != null)
+ {
+ return impulseInternal;
+ }
+ switch (index)
+ {
+ case 0:
+ return OnWriteStart;
+ case 1:
+ return OnWriteComplete;
+ default:
+ index -= 2;
+ return null;
+ }
+ }
+}
diff --git a/ProtoFlux/Utility/WriteToLogNode.cs b/ProtoFlux/Utility/WriteToLogNode.cs
new file mode 100644
index 0000000..6d2b38f
--- /dev/null
+++ b/ProtoFlux/Utility/WriteToLogNode.cs
@@ -0,0 +1,51 @@
+using Elements.Core;
+using FrooxEngine;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+using System.Threading.Tasks;
+using FrooxEngine.ProtoFlux;
+
+namespace ProtoFlux.Runtimes.Execution.Nodes.Obsidian.Utility
+{
+ public enum LogSeverity
+ {
+ Log,
+ Warning,
+ Error
+ }
+
+ [NodeCategory("Obsidian/Utility/WriteToLog")]
+ public class WriteToLogNode : AsyncActionNode
+ {
+ public ObjectInput Value;
+ public ValueInput Severity;
+ public ObjectInput Tag;
+ public ObjectInput HandlingUser;
+
+ public AsyncCall OnWriteStart;
+ public Continuation OnWriteComplete;
+
+ protected override async Task RunAsync(FrooxEngineContext context)
+ {
+ User user = HandlingUser.Evaluate(context, context.LocalUser);
+ if (user != null)
+ {
+ await OnWriteStart.ExecuteAsync(context);
+ switch (Severity.Evaluate(context))
+ {
+ case LogSeverity.Log:
+ UniLog.Log(Tag.Evaluate(context) + Value.Evaluate(context)?.ToString());
+ break;
+ case LogSeverity.Warning:
+ UniLog.Warning(Tag.Evaluate(context) + Value.Evaluate(context)?.ToString());
+ break;
+ case LogSeverity.Error:
+ UniLog.Error(Tag.Evaluate(context) + Value.Evaluate(context)?.ToString());
+ break;
+ }
+ return OnWriteComplete.Target;
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file