Skip to content

Commit

Permalink
Add dynamically usable event listeners
Browse files Browse the repository at this point in the history
This is quite powerful, since it makes it very easy to listen to js events without writing a lot of code
  • Loading branch information
JohannesDeml committed Dec 20, 2024
1 parent 0d9b8c5 commit 8c3c786
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 5 deletions.
43 changes: 43 additions & 0 deletions Assets/Plugins/WebGL/WebBridge/CommonCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Supyrb.Attributes;
using UnityEngine;
using UnityEngine.Rendering;
Expand Down Expand Up @@ -161,6 +163,47 @@ public void SetTimeTimeScale(float timeScale)
Debug.Log($"Time.timeScale: {Time.timeScale}");
}

/// <summary>
/// Finds GameObject(s) by name and logs the found GameObject(s) and their components
/// </summary>
/// <param name="name">The name of the GameObject to find</param>
[WebCommand(Description = "Find GameObject by name and log its components")]
[ContextMenu(nameof(FindGameObjectByName))]
public void FindGameObjectByName(string name)
{
var gameObjects = GameObject.FindObjectsOfType<GameObject>().Where(go => go.name == name).ToArray();
if (gameObjects.Length == 0)
{
Debug.Log($"No GameObject found with the name: {name}");
}
else
{
StringBuilder sb = new StringBuilder();
foreach (var go in gameObjects)
{
int pathStartIndex = 0;
var currentTransform = go.transform;
sb.Insert(pathStartIndex, currentTransform.name);
currentTransform = currentTransform.parent;
while (currentTransform != null)
{
sb.Insert(pathStartIndex, currentTransform.name + "/");
currentTransform = currentTransform.parent;
}

sb.AppendLine($", Tag: {go.tag}, Layer: {go.layer}, ActiveSelf: {go.activeSelf}, ActiveInHierarchy: {go.activeInHierarchy}");
sb.AppendLine("Attached Components:");
var components = go.GetComponents<Component>();
foreach (var component in components)
{
sb.AppendLine($"- {component.GetType().Name}");
}
Debug.Log(sb.ToString());
sb.Clear();
}
}
}

/// <summary>
/// Toggle the visibility of the info panel in the top right corner
/// Browser Usage: <code>unityGame.SendMessage("WebGL", "ToggleInfoPanel");</code>
Expand Down
11 changes: 6 additions & 5 deletions Assets/Plugins/WebGL/WebBridge/WebBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@

namespace Supyrb
{

/// <summary>
/// Bridge to Unity to access unity logic through the browser console
/// You can extend your commands by creating a partial class for WebBridge, see WebBridge.Commands as an example
/// </summary>
public class WebBridge : WebCommands
{
private const string WebBridgeGameObjectName = "WebBridge";
private const string GameObjectName = "WebBridge";

private static GameObject bridgeInstance;
private static GameObject instance;
#if UNITY_WEBGL
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void OnBeforeSceneLoadRuntimeMethod()
{
SetGlobalVariables();
bridgeInstance = new GameObject(WebBridgeGameObjectName);
DontDestroyOnLoad(bridgeInstance);
instance = new GameObject(GameObjectName);
DontDestroyOnLoad(instance);
AddAllWebCommands();
}
#endif
Expand All @@ -58,7 +59,7 @@ private static void AddAllWebCommands()
webCommandTypes.Sort((a, b) => a.Name.CompareTo(b.Name));
foreach (var webCommandType in webCommandTypes)
{
bridgeInstance.AddComponent(webCommandType);
instance.AddComponent(webCommandType);
}
}

Expand Down
8 changes: 8 additions & 0 deletions Assets/Plugins/WebGL/WebTools/EventListeners.meta

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WebEventListener.cs">
// Copyright (c) 2024 Johannes Deml. All rights reserved.
// </copyright>
// <author>
// Johannes Deml
// public@deml.io
// </author>
// --------------------------------------------------------------------------------------------------------------------

using UnityEngine;

namespace Supyrb
{
public class CommonWebEventListener : MonoBehaviour
{
private void Start()
{
WebEventListeners.AddEventListener("focus", () =>
{
Debug.Log("WebEvent focus triggered");
});

WebEventListeners.AddEventListener("blur", () =>
{
Debug.Log("WebEvent blur triggered");
});
}
}
}

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

32 changes: 32 additions & 0 deletions Assets/Plugins/WebGL/WebTools/EventListeners/WebEventListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WebEventListener.cs">
// Copyright (c) 2024 Johannes Deml. All rights reserved.
// </copyright>
// <author>
// Johannes Deml
// public@deml.io
// </author>
// --------------------------------------------------------------------------------------------------------------------

using System;
using UnityEngine;

namespace Supyrb
{
public class WebEventListener : MonoBehaviour
{
public event Action OnEvent;

// Called from JavaScript
public void TriggerEvent()
{
OnEvent?.Invoke();
}

private void OnDestroy()
{
// Clean up event handlers when destroyed
OnEvent = null;
}
}
}

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

65 changes: 65 additions & 0 deletions Assets/Plugins/WebGL/WebTools/EventListeners/WebEventListeners.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WebGlBridge.cs">
// Copyright (c) 2021 Johannes Deml. All rights reserved.
// </copyright>
// <author>
// Johannes Deml
// public@deml.io
// </author>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

namespace Supyrb
{
public class WebEventListeners : MonoBehaviour
{

#if UNITY_WEBGL
[DllImport("__Internal")]
private static extern void _AddJsEventListener(string eventName);
#endif
private const string GameObjectName = "WebEventListeners";

private Dictionary<string, WebEventListener> eventListeners = new Dictionary<string, WebEventListener>();
private static WebEventListeners instance;
#if UNITY_WEBGL
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void OnBeforeSceneLoadRuntimeMethod()
{
GameObject instanceGo = new GameObject(GameObjectName);
instance = instanceGo.AddComponent<WebEventListeners>();
DontDestroyOnLoad(instanceGo);
}
#endif

public static void AddEventListener(string eventName, Action callback)
{
instance.AddEventListenerInternal(eventName, callback);
}

private void AddEventListenerInternal(string eventName, Action callback)
{
if(eventListeners.TryGetValue(eventName, out var eventListener))
{
eventListener.OnEvent += callback;
}
else
{
var eventGo = new GameObject("WebEvent-" + eventName);
eventGo.transform.parent = transform;
var eventComponent = eventGo.AddComponent<WebEventListener>();
eventListeners[eventName] = eventComponent;
eventComponent.OnEvent += callback;

#if UNITY_WEBGL
// Add event listener on javascript side
_AddJsEventListener(eventName);
#endif
}
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var WebGlEventListeners =
{
_AddJsEventListener: function(eventNamePtr) {
var eventName = UTF8ToString(eventNamePtr);

// Add the event listener to the window object
window.addEventListener(eventName, function(event) {
if (typeof unityGame === 'undefined') {
console.error('Unity instance "unityGame" not found - cannot send event ' + eventName);
return;
}
unityGame.SendMessage("WebEvent-" + eventName, "TriggerEvent");
});
},
};

mergeInto(LibraryManager.library, WebGlEventListeners);

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

45 changes: 45 additions & 0 deletions Assets/Scenes/Main.unity
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,50 @@ MonoBehaviour:
spawnerCount: 5
spawnerRadius: 0.5
spawnerCoolDown: 0.5
--- !u!1 &1401030096
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1401030098}
- component: {fileID: 1401030097}
m_Layer: 0
m_Name: CommonWebEventListener
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1401030097
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1401030096}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2a36f15dbca612740a4822a71a1d75e1, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!4 &1401030098
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1401030096}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1530667640
GameObject:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -947,3 +991,4 @@ SceneRoots:
- {fileID: 1964540201}
- {fileID: 170076735}
- {fileID: 1530667642}
- {fileID: 1401030098}

0 comments on commit 8c3c786

Please sign in to comment.