├── .gitignore ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Editor.meta ├── Editor ├── HostEditor.cs ├── HostEditor.cs.meta ├── JSONViewer.cs ├── JSONViewer.cs.meta ├── OtherDrawers.meta ├── OtherDrawers │ ├── BackgroundStringDrawer.cs │ └── BackgroundStringDrawer.cs.meta ├── Parameters.meta ├── Parameters │ ├── BaseParameterDrawer.cs │ ├── BaseParameterDrawer.cs.meta │ ├── BoolParameterDrawer.cs │ ├── BoolParameterDrawer.cs.meta │ ├── ChoicesParameterDrawer.cs │ ├── ChoicesParameterDrawer.cs.meta │ ├── ColorParameterDrawer.cs │ ├── ColorParameterDrawer.cs.meta │ ├── IntParameterDrawer.cs │ ├── IntParameterDrawer.cs.meta │ ├── ParameterListDrawer.cs │ ├── ParameterListDrawer.cs.meta │ ├── ParameterListParameterDrawer.cs │ ├── ParameterListParameterDrawer.cs.meta │ ├── SpecialisedDrawers.meta │ ├── SpecialisedDrawers │ │ ├── BackgroundParameterDrawer.cs │ │ ├── BackgroundParameterDrawer.cs.meta │ │ ├── DimensionParameterDrawer.cs │ │ ├── DimensionParameterDrawer.cs.meta │ │ ├── SpecialisedParameterDrawer.cs │ │ ├── SpecialisedParameterDrawer.cs.meta │ │ ├── SpecialisedParameterDrawerLookup.cs │ │ └── SpecialisedParameterDrawerLookup.cs.meta │ ├── StringArrayParameterDrawer.cs │ ├── StringArrayParameterDrawer.cs.meta │ ├── StringParameterDrawer.cs │ └── StringParameterDrawer.cs.meta ├── PropertyDiscovery.cs ├── PropertyDiscovery.cs.meta ├── com.atb.hackbox.Editor.asmdef └── com.atb.hackbox.Editor.asmdef.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── Attributes.meta ├── Attributes │ ├── BackgroundStringAttribute.cs │ └── BackgroundStringAttribute.cs.meta ├── Builders.meta ├── Builders │ ├── ParameterListBuilder.cs │ ├── ParameterListBuilder.cs.meta │ ├── PresetBuilder.cs │ ├── PresetBuilder.cs.meta │ ├── StateBuilder.cs │ ├── StateBuilder.cs.meta │ ├── StyleParameterListBuilder.cs │ ├── StyleParameterListBuilder.cs.meta │ ├── ThemeBuilder.cs │ └── ThemeBuilder.cs.meta ├── Events.cs ├── Events.cs.meta ├── Extensions.meta ├── Extensions │ ├── ColorExtensions.cs │ ├── ColorExtensions.cs.meta │ ├── MarkdownExtensions.cs │ └── MarkdownExtensions.cs.meta ├── Helpers.meta ├── Helpers │ ├── BackgroundHelpers.cs │ ├── BackgroundHelpers.cs.meta │ ├── MarkdownHelpers.cs │ └── MarkdownHelpers.cs.meta ├── Host.cs ├── Host.cs.meta ├── Member.cs ├── Member.cs.meta ├── Message.cs ├── Message.cs.meta ├── MessageEventCollection.cs ├── MessageEventCollection.cs.meta ├── MessageEventQueue.cs ├── MessageEventQueue.cs.meta ├── Parameters.meta ├── Parameters │ ├── BoolParameter.cs │ ├── BoolParameter.cs.meta │ ├── ChoicesParameter.cs │ ├── ChoicesParameter.cs.meta │ ├── ColorParameter.cs │ ├── ColorParameter.cs.meta │ ├── DefaultParameters.cs │ ├── DefaultParameters.cs.meta │ ├── IParameterList.cs │ ├── IParameterList.cs.meta │ ├── IStyleParameterList.cs │ ├── IStyleParameterList.cs.meta │ ├── IntParameter.cs │ ├── IntParameter.cs.meta │ ├── Parameter.cs │ ├── Parameter.cs.meta │ ├── ParameterList.cs │ ├── ParameterList.cs.meta │ ├── ParameterListAttributes.cs │ ├── ParameterListAttributes.cs.meta │ ├── ParameterListParameter.cs │ ├── ParameterListParameter.cs.meta │ ├── StringArrayParameter.cs │ ├── StringArrayParameter.cs.meta │ ├── StringParameter.cs │ └── StringParameter.cs.meta ├── Sockets.meta ├── Sockets │ ├── ISocketIO.cs │ ├── ISocketIO.cs.meta │ ├── Standalone.meta │ ├── Standalone │ │ ├── SocketIOClient.meta │ │ ├── SocketIOClient │ │ │ ├── SocketIOClient.Newtonsoft.Json.dll │ │ │ ├── SocketIOClient.Newtonsoft.Json.dll.meta │ │ │ ├── SocketIOClient.dll │ │ │ ├── SocketIOClient.dll.meta │ │ │ ├── SocketIOClient.xml │ │ │ └── SocketIOClient.xml.meta │ │ ├── StandaloneSocketIO.cs │ │ └── StandaloneSocketIO.cs.meta │ ├── WebGL.meta │ └── WebGL │ │ ├── WebGLSocketIO.cs │ │ ├── WebGLSocketIO.cs.meta │ │ ├── WebGLSocketIO.jslib │ │ └── WebGLSocketIO.jslib.meta ├── State.cs ├── State.cs.meta ├── StateAsset.cs ├── StateAsset.cs.meta ├── UI.meta ├── UI │ ├── IUIElement.cs │ ├── IUIElement.cs.meta │ ├── Preset.cs │ ├── Preset.cs.meta │ ├── Theme.cs │ ├── Theme.cs.meta │ ├── UIComponent.cs │ └── UIComponent.cs.meta ├── com.atb.hackbox.Runtime.asmdef └── com.atb.hackbox.Runtime.asmdef.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). 5 | 6 | ## [v0.12.0] - 2024-09-15 7 | 8 | ### Added 9 | - The Sort component is now supported since the last official version change - essentially a Choices component where the player must drag and drop the options into a sorted order before submitting. Thanks to [theoryofgame](https://github.com/theoryofgame) for adding this support! 10 | - New `Hackbox.Builders` namespace with some convenience builder-style classes to much more quickly and reliably configure Presets, Components, and States in code. All lower-level code remains intact - this namespace just provides a more friendly higher-level interface to the system. 11 | - Added very basic image-based background property mode in the Editor. Should be more friendly now to specify a image with a URL to use as the background for the State or Components. 12 | 13 | ## [v0.11.0] - 2024-08-27 14 | 15 | ### Added 16 | - Add `ConnectExisting` to Host to allow connecting to an existing room on Hackbox with a given room code and host user ID. 17 | 18 | ## [v0.10.0] - 2024-08-12 19 | 20 | ### Added 21 | - Add handling of `change` member events (they occur as the user makes changes to a component, debounced by some interval). Use `OnValueChange` or `ValueChangeEvents` to listen for these value change events. 22 | 23 | ### Changed 24 | - Updated the parameter defaults for TextInput preset to allow specifying a `type` of `number` for constricting to numeric input only (and also allow `min`/`max`/`step` parameters). 25 | - More exception handling code in place to more reliably catch unexpected behaviour should it happen. 26 | 27 | ## [v0.9.1] - 2024-04-13 28 | 29 | ### Added 30 | - Add `Create` methods to Theme, Preset, UIComponent, and State to avoid having to use ScriptableObject.CreateInstance() each time. (The `State.Create()` isn't strictly needed as it doesn't derive from ScriptableObject, but it's implemented to maintain a consistent creation method naming scheme.) 31 | - Add `HeaderBackgroundColor` and `MainBackgroundColor` properties to Theme to make it easier to set the backgrounds to solid colors. 32 | - Add `HeaderText`, `HeaderColor` and `HeaderBackground` properties to State to make it easier to initialise/set those parameters. `GetHeaderText()` and `SetHeaderText()` methods will remain to maintain backwards compatibility. 33 | 34 | ### Changed 35 | - Compressed the event foldout in the Host inspector into a scrollview. 36 | 37 | ## [v0.9.0] - 2024-04-10 38 | 39 | ### Added 40 | - Added `TryGetComponent` on State to access a component much in the same vein as `Dictionary.TryGetValue`. 41 | - Add the `persistent` parameter to TextInput presets & components (https://github.com/devanhurst/hackbox/pull/9). 42 | 43 | ### Changed 44 | - Add slightly better room code validation and ownership verification in so it can error out more meaningfully before trying to connect to a non-existent or non-owned room. 45 | 46 | ### Fixed 47 | - Tweak the regular expression used on the dimension parameter. 48 | 49 | ## [v0.8.0] - 2024-02-06 50 | 51 | ### Added 52 | - Add new fields (`ConnectOnStart`, `ReconnectOnEnable`, `DisconnectOnEnable`) to control automatic connect/disconnect behaviour. 53 | 54 | ### Fixed 55 | - Fix Disconnect event on JavaScript on WebGL builds. 56 | 57 | ## [v0.7.0] - 2023-11-09 58 | 59 | ### Added 60 | - New tooltips added to help describe parameters. 61 | - Supports new Choices grid display (`grid`, `gridColumns`, `gridGap`, `gridRowHeight`). 62 | - Supports `minWidth`/`maxWidth` on main part of theme, and `minHeight`/`maxHeight` on header part. 63 | 64 | ### Changed 65 | - Updated parameters in line with latest Hackbox changes. 66 | 67 | ### Fixed 68 | - Fix for the dimension magic regex. 69 | - Limit hover style parameters to `background` and `color` only as those are the only ones supported. 70 | 71 | ## [v0.6.0] - 2023-09-23 72 | 73 | ### Added 74 | - Custom fonts are now supported! Setup the font names in the theme, and then use them as you wish in the preset and component objects! 75 | 76 | ## [v0.5.0] - 2023-09-23 77 | 78 | ### Changed 79 | - Background 'string' drawer now extracted and made more use in other places in the package (namely the Theme main and header backgrounds). 80 | - Helper methods in UIComponent and ParameterList are far more feature complete now. Can get/set parameter and style parameter values far more easily. 81 | - Set the default version for new instances of the Host component to 2 as version 2 is far more feature rich and also fairly stable. 82 | - ParameterList drawer is now foldable, meaning that the inspector doesn't get completely overwhelmed with all of the parameter properties drawing at all times. 83 | - Parameter creation in code is far more friendly now, accepting parameterless constructors and typed constructors for the appropriate types the parameters box around. 84 | - Can now construct states, parameter lists, etc. with object initializers and collection initializers, meaning that code-created elements can take up just a few lines of code now instead of lots of boilerplate-style code being required. The older construction methods are still 100% supported and backwards compatible alongside this new initializer interface. 85 | 86 | ## [v0.4.6] - 2023-08-12 87 | 88 | ### Changed 89 | - Add implicit operator for simple StateAsset to State conversion. 90 | 91 | ### Fixed 92 | - Fix performance issues on serializing/deserializing JSON. 93 | - Add newer syntax to reduce warnings about deprecated/obsolete APIs on UnityWebRequest. 94 | - Try and fix some style properties not being combined correctly. 95 | 96 | ## [v0.4.5] - 2023-07-09 97 | 98 | ### Fixed 99 | - Fix the Host Editor script to allow the new Twitch Required feature to work!! 100 | 101 | ## [v0.4.3] - 2023-07-09 102 | 103 | ### Added 104 | - Add `twitchRequired` to the room creation POST request, restricting room to only members that have Twitch credentials authenticated. 105 | 106 | ## [v0.4.2] - 2023-02-25 107 | 108 | ### Fixed 109 | - Fix components not getting local style being applied in V2 hosted rooms. 110 | 111 | ## [v0.4.1] - 2023-02-16 112 | 113 | ### Changed 114 | - Updated to reflect the new Member data structure proposed by Dev with regards to new Twitch metadata. 115 | 116 | ## [v0.4.0] - 2023-02-08 117 | 118 | ### Added 119 | - The inspectors for Presets and Components will be more intelligent in the offerings of what parameters are available and where, according to the latest supported fields in Hackbox. 120 | - The Range component is now supported since the last official version change, allowing integer based input, either typed in or as a horizontal slider. 121 | - Hackbox now supports Twitch identity provisioning - the Unity side of things now parses this information and makes it available in each Member if they have logged in with Twitch. 122 | 123 | ### Changed 124 | - You can now control the level of debugging from Minimal, to Full, or to Off if you don't want any debugging at all (thanks Royal_Flu$h for the suggestion!). There's also a crude JSON viewer to help debug Member states and how they are getting constructed in the Hackbox Unity system. Oh and, if you're doing really funky debugging stuff, you can also point to a local development URL right in the Host inspector now, rather than having to spelunk into the code to do that! 125 | 126 | ## [v0.3.0] - 2023-01-14 127 | 128 | ### Added 129 | - Added WebGL implementation for socketio via jslib. 130 | 131 | ### Changed 132 | - Slight update to Host component Editor appearance. 133 | 134 | ### Fixed 135 | - JSON construction/deconstruction rewritten in places to support non-reflection platforms like WebGL. 136 | - Refactored SocketIO code to now have platform implementations for Standalone, Editor, and WebGL. 137 | 138 | ## [v0.2.4] - 2022-12-27 139 | 140 | ### Added 141 | - Added debugging option to log some extra information out, such as ping/pong event calls and raw JSON that is sent/received. 142 | - Added `OnRoomReconnecting`, `OnRoomReconnectFailed`, and `OnPingPong` events. 143 | 144 | ### Changed 145 | - Now depends on updated socket.io-client-csharp v3.0.6 (newtonsoft-json branch). 146 | 147 | ### Fixed 148 | - Updated version now correctly makes disconnect and reconnect calls. 149 | - Updated reconnect logic to send latest updated member states on reconnecting. 150 | - Updated logging. 151 | 152 | ## [v0.2.3] - 2022-12-18 153 | 154 | ### Fixed 155 | - Fixed style parameters not being correctly cloned in state objects, which lead to UIComponents not inheriting their styling. 156 | 157 | ## [v0.2.2] - 2022-12-09 158 | 159 | ### Added 160 | - Added `key` member to UIComponent, so that individual component state can be persisted across a full state change. Will only populate the "key" value in the JSON if the value is not empty and not null. 161 | 162 | ## [v0.2.1] - 2022-09-26 163 | 164 | ### Changed 165 | - Style parameters have been migrated to a new fields in the serialized data. Checking through your StateAsset objects should be enough to migrate the appropriate parameters into the style parameters field. 166 | - `hover` has been moved to a style parameter. 167 | - In version 2+ hosting, each individual Choice can now be styled with the new style field per choice. 168 | 169 | ### Fixed 170 | - Fixed state payload definition so that it now sends a correctly versioned payload. (Reminder: Change the version field on the Host component to change what version state payload is sent.) 171 | - `hover`, `submit`, and other ParameterList parameter inspectors have been fixed and should now be visible. 172 | 173 | ## [v0.2.0] - 2022-09-26 174 | 175 | ### Added 176 | - Initial update to attempt version 2 state payloads. Change the version field on the Host component to change what version state payload is sent. 177 | 178 | ### Changed 179 | - Style parameters have been migrated to a new fields in the serialized data. Checking through your StateAsset objects should be enough to migrate the appropriate parameters into the style parameters field. 180 | 181 | ### Fixed 182 | - Fix a bug in GetMemberByID which compared against the gameobject name instead of the userID parameter. 183 | 184 | ## [v0.1.4] - 2022-09-26 185 | 186 | ### Added 187 | - Added `padding` and `margin` styling parameters. 188 | 189 | ### Fixed 190 | - Fixed assembly definitions so that the package should be more "plug & play" and should no longer complain about Unity Editor dependencies for runtime builds. 191 | 192 | ## [v0.1.3] - 2022-09-26 193 | 194 | ### Added 195 | - First release with fixes to Unity Editor inspector problems. 196 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6415e5242abefb41bd9c4007d629e2b 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b23b4fec99e92bf45af3ca914c647475 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/HostEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | namespace Hackbox 6 | { 7 | [CustomEditor(typeof(Host))] 8 | public class HostEditor : Editor 9 | { 10 | private static GUIStyle _foldoutHeader = null; 11 | private static GUIStyle _foldoutBox = null; 12 | 13 | private Host _obj = null; 14 | 15 | private bool _eventsFoldout = true; 16 | private bool _settingsFoldout = true; 17 | private bool _roomStateFoldout = true; 18 | private bool _memberStateFoldout = true; 19 | 20 | private Vector2 _eventsScroll = Vector2.zero; 21 | 22 | private void OnEnable() 23 | { 24 | _obj = target as Host; 25 | } 26 | 27 | private void OnDisable() 28 | { 29 | _obj = null; 30 | } 31 | 32 | public override bool RequiresConstantRepaint() 33 | { 34 | return true; 35 | } 36 | 37 | public override void OnInspectorGUI() 38 | { 39 | EditorGUI.BeginChangeCheck(); 40 | 41 | DrawFoldoutBox("Settings", ref _settingsFoldout, DrawSettingsGroup); 42 | DrawFoldoutBox("Events", ref _eventsFoldout, DrawEventGroup); 43 | DrawFoldoutBox("Room State", ref _roomStateFoldout, DrawRoomStateGroup); 44 | DrawFoldoutBox("Member State", ref _memberStateFoldout, DrawMemberStateGroup); 45 | 46 | if (EditorGUI.EndChangeCheck()) 47 | { 48 | serializedObject.ApplyModifiedProperties(); 49 | EditorUtility.SetDirty(serializedObject.targetObject); 50 | } 51 | } 52 | 53 | private void DrawFoldoutBox(string header, ref bool foldoutState, Action onDraw) 54 | { 55 | if (_foldoutHeader == null) 56 | { 57 | _foldoutHeader = new GUIStyle(EditorStyles.foldoutHeader); 58 | _foldoutHeader.fontSize = 16; 59 | _foldoutHeader.fontStyle = FontStyle.Bold; 60 | _foldoutHeader.fixedHeight = 20; 61 | } 62 | 63 | if (_foldoutBox == null) 64 | { 65 | _foldoutBox = new GUIStyle(EditorStyles.helpBox); 66 | _foldoutBox.margin = new RectOffset(0, 0, 5, 5); 67 | _foldoutBox.padding = new RectOffset(15, 5, 5, 5); 68 | _foldoutBox.overflow = new RectOffset(0, 0, 0, 0); 69 | } 70 | 71 | EditorGUILayout.BeginVertical(_foldoutBox); 72 | foldoutState = EditorGUILayout.BeginFoldoutHeaderGroup(foldoutState, header, _foldoutHeader); 73 | if (foldoutState) 74 | { 75 | onDraw.Invoke(); 76 | } 77 | EditorGUILayout.EndFoldoutHeaderGroup(); 78 | EditorGUILayout.EndVertical(); 79 | } 80 | 81 | private void DrawSimpleProperty(string name) 82 | { 83 | EditorGUILayout.PropertyField(serializedObject.FindProperty(name)); 84 | } 85 | 86 | private void DrawEventGroup() 87 | { 88 | _eventsScroll = EditorGUILayout.BeginScrollView(_eventsScroll, false, true, GUILayout.ExpandWidth(true), GUILayout.Height(300)); 89 | DrawSimpleProperty(nameof(Host.OnRoomCreated)); 90 | DrawSimpleProperty(nameof(Host.OnRoomConnected)); 91 | DrawSimpleProperty(nameof(Host.OnRoomDisconnected)); 92 | DrawSimpleProperty(nameof(Host.OnRoomReconnecting)); 93 | DrawSimpleProperty(nameof(Host.OnRoomReconnectFailed)); 94 | DrawSimpleProperty(nameof(Host.OnMemberJoined)); 95 | DrawSimpleProperty(nameof(Host.OnMemberKicked)); 96 | DrawSimpleProperty(nameof(Host.OnMessage)); 97 | DrawSimpleProperty(nameof(Host.OnPingPong)); 98 | EditorGUILayout.EndScrollView(); 99 | } 100 | 101 | private void DrawSettingsGroup() 102 | { 103 | DrawSimpleProperty(nameof(Host.URL)); 104 | DrawSimpleProperty(nameof(Host.HostName)); 105 | DrawSimpleProperty(nameof(Host.HostVersion)); 106 | DrawSimpleProperty(nameof(Host.ReloadHost)); 107 | DrawSimpleProperty(nameof(Host.TwitchRequired)); 108 | DrawSimpleProperty(nameof(Host.ConnectOnStart)); 109 | DrawSimpleProperty(nameof(Host.ReconnectOnEnable)); 110 | DrawSimpleProperty(nameof(Host.DisconnectOnDisable)); 111 | DrawSimpleProperty(nameof(Host.Debugging)); 112 | } 113 | 114 | private void DrawRoomStateGroup() 115 | { 116 | if (_obj.Connected) 117 | { 118 | EditorGUILayout.LabelField("Server", _obj.URL); 119 | EditorGUILayout.LabelField("Room Code", _obj.RoomCode); 120 | EditorGUILayout.LabelField("Host User ID", _obj.UserID); 121 | GUI.enabled = Application.isPlaying; 122 | if (GUILayout.Button("Disconnect")) 123 | { 124 | _obj.Disconnect(); 125 | } 126 | GUI.enabled = true; 127 | } 128 | else 129 | { 130 | EditorGUILayout.LabelField("Disconnected"); 131 | GUI.enabled = Application.isPlaying; 132 | if (GUILayout.Button("Connect")) 133 | { 134 | _obj.Connect(); 135 | } 136 | GUI.enabled = true; 137 | } 138 | } 139 | 140 | private void DrawMemberStateGroup() 141 | { 142 | if (_obj.HasMembers) 143 | { 144 | foreach (Member member in _obj.AllMembers) 145 | { 146 | EditorGUILayout.BeginVertical(_foldoutBox); 147 | 148 | EditorGUILayout.LabelField($"{member.Name} [{member.UserID}]", EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); 149 | 150 | if (member.Twitch != null) 151 | { 152 | EditorGUILayout.LabelField($"Twitch: {member.Twitch}", EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); 153 | } 154 | 155 | if (GUILayout.Button("View State JSON")) 156 | { 157 | JSONViewer.ViewJSON(member.State.GenerateJSON(_obj.HostVersion)); 158 | } 159 | EditorGUILayout.EndVertical(); 160 | } 161 | } 162 | else 163 | { 164 | EditorGUILayout.LabelField(""); 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Editor/HostEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0424db91dbde0a646b17038d93c0ea41 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/JSONViewer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | using Newtonsoft.Json.Linq; 5 | 6 | namespace Hackbox 7 | { 8 | public class JSONViewer : EditorWindow 9 | { 10 | private Dictionary _foldouts = new Dictionary(); 11 | private Vector2 _scroll = Vector2.zero; 12 | private JToken _jsonRoot = null; 13 | 14 | public static void ViewJSON(string json) 15 | { 16 | ViewJSON(JObject.Parse(json)); 17 | } 18 | 19 | public static void ViewJSON(JToken jsonRoot) 20 | { 21 | JSONViewer window = EditorWindow.GetWindow("JSON Viewer"); 22 | window._foldouts.Clear(); 23 | window._jsonRoot = jsonRoot; 24 | window.ShowUtility(); 25 | } 26 | 27 | private void OnGUI() 28 | { 29 | _scroll = EditorGUILayout.BeginScrollView(_scroll, true, true); 30 | DrawToken("", null, _jsonRoot); 31 | EditorGUILayout.EndScrollView(); 32 | } 33 | 34 | private void DrawToken(string fullName, string name, JToken jToken) 35 | { 36 | fullName = $"{fullName}.{name}"; 37 | if (jToken is JObject jObject) 38 | { 39 | DrawObject(fullName, name, jObject); 40 | } 41 | else if (jToken is JArray jArray) 42 | { 43 | DrawArray(fullName, name, jArray); 44 | } 45 | else if (jToken is JValue jValue) 46 | { 47 | DrawValue(fullName, name, jValue); 48 | } 49 | } 50 | 51 | private void DrawObject(string fullName, string name, JObject jObject) 52 | { 53 | if (!_foldouts.TryGetValue(fullName, out bool foldout)) 54 | { 55 | _foldouts[fullName] = false; 56 | } 57 | if (!string.IsNullOrEmpty(name)) 58 | { 59 | foldout = EditorGUILayout.Foldout(foldout, name); 60 | _foldouts[fullName] = foldout; 61 | } 62 | else 63 | { 64 | foldout = true; 65 | } 66 | 67 | if (foldout) 68 | { 69 | EditorGUI.indentLevel++; 70 | foreach (JProperty property in jObject.Properties()) 71 | { 72 | DrawToken(fullName, $"{property.Name}", property.Value); 73 | } 74 | EditorGUI.indentLevel--; 75 | } 76 | } 77 | 78 | private void DrawArray(string fullName, string name, JArray jArray) 79 | { 80 | if (!_foldouts.TryGetValue(fullName, out bool foldout)) 81 | { 82 | _foldouts[fullName] = false; 83 | } 84 | if (!string.IsNullOrEmpty(name)) 85 | { 86 | foldout = EditorGUILayout.Foldout(foldout, name); 87 | _foldouts[fullName] = foldout; 88 | } 89 | else 90 | { 91 | foldout = true; 92 | } 93 | 94 | if (foldout) 95 | { 96 | EditorGUI.indentLevel++; 97 | for (int arrayIndex = 0; arrayIndex < jArray.Count; ++arrayIndex) 98 | { 99 | DrawToken(fullName, $"[{arrayIndex}]", jArray[arrayIndex]); 100 | } 101 | EditorGUI.indentLevel--; 102 | } 103 | } 104 | 105 | private void DrawValue(string fullName, string name, JValue jValue) 106 | { 107 | switch (jValue.Type) 108 | { 109 | case JTokenType.String: 110 | EditorGUILayout.LabelField(name, $"\"{jValue}\""); 111 | break; 112 | 113 | default: 114 | EditorGUILayout.LabelField(name, jValue.ToString()); 115 | break; 116 | } 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Editor/JSONViewer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f28834866ecfb54eb9d1ab6b48c1819 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/OtherDrawers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02329d78ae8ae1043be962eea00095fa 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/OtherDrawers/BackgroundStringDrawer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashbash1987/hackbox-unity/2c69018ade8fc478c15a8f760360229f951532c4/Editor/OtherDrawers/BackgroundStringDrawer.cs -------------------------------------------------------------------------------- /Editor/OtherDrawers/BackgroundStringDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a9980de60ec62c24c86fbd7535fa5676 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ba5293b36ce30c4c8a4d3491158d723 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Parameters/BaseParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | public abstract class BaseParameterDrawer : PropertyDrawer 8 | { 9 | private readonly Dictionary _specialisedDrawers = new Dictionary(); 10 | 11 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 12 | { 13 | BaseParameterDrawer specialisedDrawer = GetSpecialisedDrawer(property); 14 | if (specialisedDrawer != null) 15 | { 16 | return specialisedDrawer.GetPropertyHeight(property, label); 17 | } 18 | 19 | return EditorGUIUtility.singleLineHeight; 20 | } 21 | 22 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 23 | { 24 | BaseParameterDrawer specialisedDrawer = GetSpecialisedDrawer(property); 25 | if (specialisedDrawer != null) 26 | { 27 | specialisedDrawer.OnGUI(position, property, label); 28 | return; 29 | } 30 | 31 | string name = GetName(property); 32 | SerializedObject serializedObject = BeginProperty(position, property, label, name); 33 | 34 | string tooltip = ""; 35 | if (DefaultParameters.AllParameterInfo.TryGetValue(name, out DefaultParameters.ParameterInfoEntry parameterInfo)) 36 | { 37 | tooltip = parameterInfo.HelpText; 38 | } 39 | 40 | OnParameterGUI(position, property, name, tooltip, GetValue(property)); 41 | EndProperty(serializedObject); 42 | } 43 | 44 | protected abstract void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value); 45 | 46 | protected string GetName(SerializedProperty property) 47 | { 48 | return property.FindPropertyRelative("Name").stringValue; 49 | } 50 | 51 | protected SerializedProperty GetValue(SerializedProperty property) 52 | { 53 | return property.FindPropertyRelative("_value"); 54 | } 55 | 56 | protected SerializedObject BeginProperty(Rect position, SerializedProperty property, GUIContent label, string name) 57 | { 58 | SerializedObject serializedObject = property.serializedObject; 59 | EditorGUI.BeginChangeCheck(); 60 | EditorGUI.BeginProperty(position, label, property); 61 | 62 | return serializedObject; 63 | } 64 | 65 | protected void EndProperty(SerializedObject serializedObject) 66 | { 67 | EditorGUI.EndProperty(); 68 | if (EditorGUI.EndChangeCheck()) 69 | { 70 | serializedObject.ApplyModifiedProperties(); 71 | } 72 | } 73 | 74 | private BaseParameterDrawer GetSpecialisedDrawer(SerializedProperty property) 75 | { 76 | if (!_specialisedDrawers.ContainsKey(property.propertyPath)) 77 | { 78 | _specialisedDrawers[property.propertyPath] = SpecialisedParameterDrawerLookup.CreateSpecialisedParameterDrawer(GetName(property)); 79 | } 80 | 81 | return _specialisedDrawers[property.propertyPath]; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Editor/Parameters/BaseParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b964272a0a15cf046920f81e9497b5a1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/BoolParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(BoolParameter))] 7 | public class BoolParameterDrawer : BaseParameterDrawer 8 | { 9 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 10 | { 11 | value.boolValue = EditorGUI.Toggle(position, new GUIContent(name, tooltip), value.boolValue); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Editor/Parameters/BoolParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 188aa829644e8af498bb38be03dc464d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/ChoicesParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(ChoicesParameter))] 7 | public class ChoicesParameterDrawer : BaseParameterDrawer 8 | { 9 | private ChoicesParameter _obj = null; 10 | 11 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 12 | { 13 | return EditorGUI.GetPropertyHeight(GetValue(property)); 14 | } 15 | 16 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 17 | { 18 | if (_obj == null) 19 | { 20 | _obj = (ChoicesParameter)PropertyDiscovery.GetValue(property); 21 | } 22 | 23 | EditorGUI.indentLevel++; 24 | EditorGUI.PropertyField(position, value, new GUIContent(name, tooltip), true); 25 | EditorGUI.indentLevel--; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Editor/Parameters/ChoicesParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67a543291f6fc4c4fbee9254010212c7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/ColorParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(ColorParameter))] 7 | public class ColorParameterDrawer : BaseParameterDrawer 8 | { 9 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 10 | { 11 | value.colorValue = EditorGUI.ColorField(position, new GUIContent(name, tooltip), value.colorValue); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Editor/Parameters/ColorParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77deb06ac057f1d4d90dd88ac6805b0b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/IntParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(IntParameter))] 7 | public class IntParameterDrawer : BaseParameterDrawer 8 | { 9 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 10 | { 11 | value.intValue = EditorGUI.IntField(position, new GUIContent(name, tooltip), value.intValue); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Editor/Parameters/IntParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 266a0cc50f1f7264c9481924107c0d42 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/ParameterListDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using UnityEditorInternal; 6 | using Hackbox.UI; 7 | 8 | namespace Hackbox.Parameters 9 | { 10 | [CustomPropertyDrawer(typeof(AnyParameterListAttribute))] 11 | [CustomPropertyDrawer(typeof(ParameterList))] 12 | public class ParameterListDrawer : PropertyDrawer 13 | { 14 | private class Setup 15 | { 16 | public ParameterList List 17 | { 18 | get; 19 | set; 20 | } 21 | 22 | public ReorderableList Reorder 23 | { 24 | get; 25 | set; 26 | } 27 | 28 | public string[] ParameterNames 29 | { 30 | get; 31 | set; 32 | } = null; 33 | 34 | public int ParameterIndex 35 | { 36 | get; 37 | set; 38 | } = 0; 39 | } 40 | 41 | private readonly Dictionary _setups = new Dictionary(); 42 | 43 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 44 | { 45 | CheckInitialize(property); 46 | return _setups[property.propertyPath].Reorder.GetHeight(); 47 | } 48 | 49 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 50 | { 51 | CheckInitialize(property); 52 | 53 | position = EditorGUI.IndentedRect(position); 54 | 55 | SerializedObject serializedObject = property.serializedObject; 56 | 57 | EditorGUI.BeginChangeCheck(); 58 | EditorGUI.BeginProperty(position, label, property); 59 | 60 | Setup setup = _setups[property.propertyPath]; 61 | 62 | if (setup.ParameterNames != null) 63 | { 64 | setup.ParameterIndex = EditorGUI.Popup(new Rect(position.x, position.yMax - setup.Reorder.footerHeight, EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight), setup.ParameterIndex, setup.ParameterNames); 65 | if (GUI.Button(new Rect(position.x + EditorGUIUtility.labelWidth, position.yMax - setup.Reorder.footerHeight, 20, EditorGUIUtility.singleLineHeight), "+")) 66 | { 67 | Parameter parameter = CreateParameter(property, setup.ParameterNames[setup.ParameterIndex]); 68 | if (parameter == null) 69 | { 70 | parameter = DefaultParameters.CreateDefaultAnyParameter(setup.ParameterNames[setup.ParameterIndex]); 71 | } 72 | setup.List.Parameters.Add(parameter); 73 | } 74 | } 75 | 76 | setup.Reorder.DoList(position); 77 | 78 | EditorGUI.EndProperty(); 79 | 80 | if (EditorGUI.EndChangeCheck()) 81 | { 82 | serializedObject.ApplyModifiedProperties(); 83 | EditorUtility.SetDirty(serializedObject.targetObject); 84 | } 85 | } 86 | 87 | protected virtual IEnumerable GetParameterNames(SerializedProperty property) 88 | { 89 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 90 | Dictionary normalParameters = DefaultParameters.GetDefaultParameters(parent, parameterChain); 91 | if (normalParameters != null) 92 | { 93 | return normalParameters.Keys; 94 | } 95 | Dictionary styleParameters = DefaultParameters.GetDefaultStyleParameters(parent, parameterChain); 96 | if (styleParameters != null) 97 | { 98 | return styleParameters.Keys; 99 | } 100 | 101 | return null; 102 | } 103 | 104 | protected virtual Parameter CreateParameter(SerializedProperty property, string name) 105 | { 106 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 107 | Parameter normalParameter = DefaultParameters.CreateDefaultParameter(name, parent, parameterChain); 108 | if (normalParameter != null) 109 | { 110 | return normalParameter; 111 | } 112 | 113 | Parameter styleParameter = DefaultParameters.CreateDefaultStyleParameter(name, parent, parameterChain); 114 | if (styleParameter != null) 115 | { 116 | return styleParameter; 117 | } 118 | 119 | return null; 120 | } 121 | 122 | protected void GetParameterChain(SerializedProperty property, out object parent, out Parameter[] parameterChain) 123 | { 124 | List parameters = new List(); 125 | object[] parents = PropertyDiscovery.GetAllParents(property); 126 | parent = parents.First(x => x is Preset || x is UIComponent || x is ParameterListParameter); 127 | 128 | foreach (object propertyParent in parents) 129 | { 130 | if (propertyParent is Parameter parentParameter) 131 | { 132 | parameters.Add(parentParameter); 133 | } 134 | } 135 | 136 | parameterChain = parameters.ToArray(); 137 | } 138 | 139 | private void CheckInitialize(SerializedProperty property) 140 | { 141 | if (!_setups.ContainsKey(property.propertyPath)) 142 | { 143 | Initialize(property); 144 | } 145 | 146 | _setups[property.propertyPath].ParameterNames = GetParameterNames(property)?.ToArray(); 147 | if (_setups[property.propertyPath].ParameterNames == null) 148 | { 149 | _setups[property.propertyPath].ParameterNames = DefaultParameters.AllParameterLookup.Keys.ToArray(); 150 | } 151 | } 152 | 153 | private void Initialize(SerializedProperty property) 154 | { 155 | ParameterList obj = (ParameterList)PropertyDiscovery.GetValue(property); 156 | if (obj.Parameters == null) 157 | { 158 | obj.Parameters = new List(); 159 | } 160 | 161 | ReorderableList reorder = new ReorderableList(obj.Parameters, typeof(Parameter), true, true, false, true); 162 | reorder.headerHeight = EditorGUIUtility.singleLineHeight; 163 | 164 | _setups[property.propertyPath] = new Setup() { List = obj, Reorder = reorder, ParameterIndex = 0 }; 165 | 166 | reorder.drawHeaderCallback = (Rect rect) => 167 | { 168 | EditorGUI.LabelField(rect, property.displayName, EditorStyles.boldLabel); 169 | }; 170 | 171 | reorder.footerHeight = EditorGUIUtility.singleLineHeight * 2; 172 | 173 | SerializedProperty parametersProperty = property.FindPropertyRelative("Parameters"); 174 | List heights = new List(Enumerable.Range(0, parametersProperty.arraySize).Select(_ => 0.0f)); 175 | 176 | reorder.elementHeightCallback = (int index) => 177 | { 178 | while (heights.Count <= index) 179 | { 180 | heights.Add(0.0f); 181 | } 182 | 183 | if (index < 0 || index >= parametersProperty.arraySize) 184 | { 185 | heights[index] = EditorGUIUtility.singleLineHeight; 186 | } 187 | else 188 | { 189 | SerializedProperty parameterProperty = parametersProperty.GetArrayElementAtIndex(index); 190 | if (parameterProperty != null) 191 | { 192 | heights[index] = EditorGUI.GetPropertyHeight(parameterProperty); 193 | } 194 | else 195 | { 196 | heights[index] = EditorGUIUtility.singleLineHeight; 197 | } 198 | } 199 | 200 | return heights[index]; 201 | }; 202 | 203 | reorder.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => 204 | { 205 | if (index < 0 || index >= parametersProperty.arraySize) 206 | { 207 | return; 208 | } 209 | 210 | SerializedProperty parameterProperty = parametersProperty.GetArrayElementAtIndex(index); 211 | SerializedProperty nameProperty = parameterProperty.FindPropertyRelative("Name"); 212 | string parameterName = nameProperty != null ? nameProperty.stringValue : ""; 213 | 214 | Color color = GUI.color; 215 | float normalWidth = EditorGUIUtility.labelWidth; 216 | EditorGUIUtility.labelWidth = Mathf.Min(normalWidth, 100); 217 | 218 | if (!_setups[property.propertyPath].ParameterNames.Contains(parameterName)) 219 | { 220 | GUI.color = Color.yellow; 221 | GUIContent icon = EditorGUIUtility.IconContent("Warning", "This parameter is not expected in this section."); 222 | icon.tooltip = "This parameter is not expected in this section."; 223 | EditorGUI.LabelField(rect, icon); 224 | rect.x += 20; 225 | rect.width -= 20; 226 | } 227 | 228 | EditorGUI.PropertyField(rect, parameterProperty, true); 229 | EditorGUIUtility.labelWidth = normalWidth; 230 | GUI.color = color; 231 | }; 232 | 233 | reorder.drawElementBackgroundCallback = (Rect rect, int index, bool isActive, bool isFocused) => 234 | { 235 | if (index < 0 || index >= parametersProperty.arraySize) 236 | { 237 | return; 238 | } 239 | 240 | rect.height = heights[index]; 241 | Texture2D tex = new Texture2D(1, 1); 242 | tex.SetPixel(0, 0, isFocused ? GUI.skin.settings.selectionColor : new Color(0, 0, 0, 0.2f)); 243 | tex.Apply(); 244 | if (isFocused || (index % 2) == 1) 245 | { 246 | GUI.DrawTexture(rect, tex as Texture); 247 | } 248 | }; 249 | } 250 | } 251 | 252 | [CustomPropertyDrawer(typeof(StyleParameterListAttribute))] 253 | public class StyleParameterListDrawer : ParameterListDrawer 254 | { 255 | protected override IEnumerable GetParameterNames(SerializedProperty property) 256 | { 257 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 258 | return DefaultParameters.GetDefaultStyleParameters(parent, parameterChain)?.Keys; 259 | } 260 | 261 | protected override Parameter CreateParameter(SerializedProperty property, string name) 262 | { 263 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 264 | return DefaultParameters.CreateDefaultStyleParameter(name, parent, parameterChain); 265 | } 266 | } 267 | 268 | [CustomPropertyDrawer(typeof(NormalParameterListAttribute))] 269 | public class NormalParameterListDrawer : ParameterListDrawer 270 | { 271 | protected override IEnumerable GetParameterNames(SerializedProperty property) 272 | { 273 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 274 | return DefaultParameters.GetDefaultParameters(parent, parameterChain)?.Keys; 275 | } 276 | 277 | protected override Parameter CreateParameter(SerializedProperty property, string name) 278 | { 279 | GetParameterChain(property, out object parent, out Parameter[] parameterChain); 280 | return DefaultParameters.CreateDefaultParameter(name, parent, parameterChain); 281 | } 282 | } 283 | 284 | [CustomPropertyDrawer(typeof(HeaderParameterListAttribute))] 285 | public class HeaderParameterListDrawer : ParameterListDrawer 286 | { 287 | protected override IEnumerable GetParameterNames(SerializedProperty property) 288 | { 289 | return DefaultParameters.HeaderParameterLookup.Keys; 290 | } 291 | 292 | protected override Parameter CreateParameter(SerializedProperty property, string name) 293 | { 294 | return DefaultParameters.CreateDefaultHeaderParameter(name); 295 | } 296 | } 297 | 298 | [CustomPropertyDrawer(typeof(MainParameterListAttribute))] 299 | public class MainParameterListDrawer : ParameterListDrawer 300 | { 301 | protected override IEnumerable GetParameterNames(SerializedProperty property) 302 | { 303 | return DefaultParameters.MainParameterLookup.Keys; 304 | } 305 | 306 | protected override Parameter CreateParameter(SerializedProperty property, string name) 307 | { 308 | return DefaultParameters.CreateDefaultMainParameter(name); 309 | } 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /Editor/Parameters/ParameterListDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e7ede3858af76244a0c3b0227906e8c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/ParameterListParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(ParameterListParameter))] 7 | public class ParameterListParameterDrawer : BaseParameterDrawer 8 | { 9 | private ParameterListParameter _obj = null; 10 | private bool _foldout = false; 11 | 12 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 13 | { 14 | if (_foldout) 15 | { 16 | return EditorGUI.GetPropertyHeight(GetValue(property)) + EditorGUIUtility.singleLineHeight; 17 | } 18 | 19 | return EditorGUIUtility.singleLineHeight; 20 | } 21 | 22 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 23 | { 24 | if (_obj == null) 25 | { 26 | _obj = (ParameterListParameter)PropertyDiscovery.GetValue(property); 27 | } 28 | 29 | EditorGUI.indentLevel++; 30 | _foldout = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), _foldout, new GUIContent(name, tooltip)); 31 | if (_foldout) 32 | { 33 | EditorGUI.PropertyField(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, position.height - EditorGUIUtility.singleLineHeight), value, new GUIContent("", tooltip), true); 34 | } 35 | EditorGUI.indentLevel--; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Editor/Parameters/ParameterListParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3165bcf7e2262c4e9af681aa06800ef 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a9d62cfb2f4b4144baff764448afdbdb 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/BackgroundParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | public class BackgroundParameterDrawer : SpecialisedParameterDrawer 7 | { 8 | private BackgroundStringDrawer.Mode? _mode = null; 9 | 10 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 11 | { 12 | return EditorGUIUtility.singleLineHeight * 2; 13 | } 14 | 15 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 16 | { 17 | if (_mode == null) 18 | { 19 | _mode = BackgroundStringDrawer.DetermineMode(value.stringValue); 20 | } 21 | 22 | _mode = (BackgroundStringDrawer.Mode)EditorGUI.EnumPopup(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), new GUIContent(name, tooltip), _mode); 23 | position.y += EditorGUIUtility.singleLineHeight; 24 | position.height -= EditorGUIUtility.singleLineHeight; 25 | 26 | position.x += EditorGUIUtility.labelWidth; 27 | position.width -= EditorGUIUtility.labelWidth; 28 | 29 | value.stringValue = BackgroundStringDrawer.DoModeGUI(position, _mode, value.stringValue); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/BackgroundParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aa60bc472eb34764288191e05f2c7d7c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/DimensionParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | public class DimensionParameterDrawer : SpecialisedParameterDrawer 8 | { 9 | private static readonly string[] UNITS = new[] 10 | { 11 | "%", 12 | "px", 13 | "em", 14 | "fr", 15 | "rem", 16 | "vw", 17 | "vh", 18 | "vmin", 19 | "vmax", 20 | "custom" 21 | }; 22 | 23 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 24 | { 25 | Regex regex = new Regex(@"^(?[\d.]+)\s*(?%|px|em|rem|vw|vh|vmin|vmax)$"); 26 | Match match = regex.Match(value.stringValue); 27 | 28 | Rect unitPosition = position; 29 | unitPosition.x += unitPosition.width - 40; 30 | unitPosition.width = 40; 31 | position.width -= 40; 32 | 33 | if (match.Success) 34 | { 35 | float dimensionValue = float.Parse(match.Groups["value"].Value); 36 | string dimensionUnit = match.Groups["unit"].Value; 37 | int dimensionUnitIndex = ArrayUtility.IndexOf(UNITS, dimensionUnit); 38 | 39 | dimensionValue = EditorGUI.FloatField(position, new GUIContent(name, tooltip), dimensionValue); 40 | dimensionUnit = UNITS[EditorGUI.Popup(unitPosition, dimensionUnitIndex, UNITS)]; 41 | 42 | value.stringValue = dimensionUnit != "custom" ? $"{dimensionValue}{dimensionUnit}" : dimensionValue.ToString(); 43 | } 44 | else 45 | { 46 | string dimensionValue = EditorGUI.TextField(position, new GUIContent(name, tooltip), value.stringValue); 47 | int dimensionUnitIndex = EditorGUI.Popup(unitPosition, ArrayUtility.IndexOf(UNITS, "custom"), UNITS); 48 | string dimensionUnit = UNITS[EditorGUI.Popup(unitPosition, dimensionUnitIndex, UNITS)]; 49 | 50 | value.stringValue = dimensionUnit != "custom" ? $"{dimensionValue}{dimensionUnit}" : dimensionValue.ToString(); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/DimensionParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fda7143742fc41d4faa507d05e70acd7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/SpecialisedParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | public abstract class SpecialisedParameterDrawer : BaseParameterDrawer 7 | { 8 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 9 | { 10 | return EditorGUIUtility.singleLineHeight; 11 | } 12 | 13 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 14 | { 15 | string name = GetName(property); 16 | SerializedObject serializedObject = BeginProperty(position, property, label, name); 17 | 18 | string tooltip = ""; 19 | if (DefaultParameters.AllParameterInfo.TryGetValue(name, out DefaultParameters.ParameterInfoEntry parameterInfo)) 20 | { 21 | tooltip = parameterInfo.HelpText; 22 | } 23 | 24 | OnParameterGUI(position, property, name, tooltip, GetValue(property)); 25 | EndProperty(serializedObject); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/SpecialisedParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5902f1ceed45e8a4b8af6502a7e3fd4f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/SpecialisedParameterDrawerLookup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | public static class SpecialisedParameterDrawerLookup 7 | { 8 | public static readonly Dictionary AllParameterDrawerLookup = new Dictionary() 9 | { 10 | ["background"] = typeof(BackgroundParameterDrawer), 11 | ["borderRadius"] = typeof(DimensionParameterDrawer), 12 | ["fontSize"] = typeof(DimensionParameterDrawer), 13 | ["gridGap"] = typeof(DimensionParameterDrawer), 14 | ["gridRowHeight"] = typeof(DimensionParameterDrawer), 15 | ["height"] = typeof(DimensionParameterDrawer), 16 | ["minHeight"] = typeof(DimensionParameterDrawer), 17 | ["maxHeight"] = typeof(DimensionParameterDrawer), 18 | ["minWidth"] = typeof(DimensionParameterDrawer), 19 | ["maxWidth"] = typeof(DimensionParameterDrawer), 20 | ["radius"] = typeof(DimensionParameterDrawer), 21 | ["width"] = typeof(DimensionParameterDrawer), 22 | }; 23 | 24 | public static BaseParameterDrawer CreateSpecialisedParameterDrawer(Parameter parameter) 25 | { 26 | return CreateSpecialisedParameterDrawer(parameter.Name); 27 | } 28 | 29 | public static BaseParameterDrawer CreateSpecialisedParameterDrawer(string parameterName) 30 | { 31 | if (AllParameterDrawerLookup.TryGetValue(parameterName, out Type parameterDrawerType)) 32 | { 33 | return (BaseParameterDrawer)Activator.CreateInstance(parameterDrawerType); 34 | } 35 | 36 | return null; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Editor/Parameters/SpecialisedDrawers/SpecialisedParameterDrawerLookup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d9eecdc65f4caa14983feb131e8501e3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/StringArrayParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(StringArrayParameter))] 7 | public class StringArrayParameterDrawer : BaseParameterDrawer 8 | { 9 | public override float GetPropertyHeight(SerializedProperty property, GUIContent label) 10 | { 11 | return EditorGUI.GetPropertyHeight(GetValue(property)); 12 | } 13 | 14 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 15 | { 16 | EditorGUI.indentLevel++; 17 | EditorGUI.PropertyField(position, value, new GUIContent(name, tooltip), true); 18 | EditorGUI.indentLevel--; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Editor/Parameters/StringArrayParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee80b840ad028404ab5929e06e875a18 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Parameters/StringParameterDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [CustomPropertyDrawer(typeof(StringParameter))] 7 | public class StringParameterDrawer : BaseParameterDrawer 8 | { 9 | protected override void OnParameterGUI(Rect position, SerializedProperty property, string name, string tooltip, SerializedProperty value) 10 | { 11 | value.stringValue = EditorGUI.TextField(position, new GUIContent(name, tooltip), value.stringValue); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Editor/Parameters/StringParameterDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 398031f7ac8077a4db5c80e2eba4e81c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/PropertyDiscovery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Reflection; 5 | using UnityEditor; 6 | using System.Collections.Generic; 7 | 8 | namespace Hackbox 9 | { 10 | internal static class PropertyDiscovery 11 | { 12 | public static object GetParent(SerializedProperty prop) 13 | { 14 | var path = prop.propertyPath.Replace(".Array.data[", "["); 15 | object obj = prop.serializedObject.targetObject; 16 | var elements = path.Split('.'); 17 | foreach (var element in elements.Take(elements.Length - 1)) 18 | { 19 | if (element.Contains("[")) 20 | { 21 | var elementName = element.Substring(0, element.IndexOf("[")); 22 | var index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); 23 | obj = GetValue(obj, elementName, index); 24 | } 25 | else 26 | { 27 | obj = GetValue(obj, element); 28 | } 29 | } 30 | return obj; 31 | } 32 | 33 | public static object[] GetAllParents(SerializedProperty prop) 34 | { 35 | var path = prop.propertyPath.Replace(".Array.data[", "["); 36 | List parents = new List(); 37 | object obj = prop.serializedObject.targetObject; 38 | parents.Add(obj); 39 | var elements = path.Split('.'); 40 | foreach (var element in elements.Take(elements.Length - 1)) 41 | { 42 | if (element.Contains("[")) 43 | { 44 | var elementName = element.Substring(0, element.IndexOf("[")); 45 | var index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); 46 | obj = GetValue(obj, elementName, index); 47 | } 48 | else 49 | { 50 | obj = GetValue(obj, element); 51 | } 52 | parents.Add(obj); 53 | } 54 | return parents.ToArray(); 55 | } 56 | 57 | public static object GetValue(object source, string name) 58 | { 59 | if (source == null) 60 | return null; 61 | var type = source.GetType(); 62 | var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 63 | if (f == null) 64 | { 65 | var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); 66 | if (p == null) 67 | return null; 68 | return p.GetValue(source, null); 69 | } 70 | return f.GetValue(source); 71 | } 72 | 73 | public static object GetValue(object source, string name, int index) 74 | { 75 | var enumerable = GetValue(source, name) as IEnumerable; 76 | var enm = enumerable.GetEnumerator(); 77 | while (index-- >= 0) 78 | enm.MoveNext(); 79 | return enm.Current; 80 | } 81 | 82 | public static object GetValue(SerializedProperty prop) 83 | { 84 | string path = prop.propertyPath.Replace(".Array.data[", "["); 85 | object obj = prop.serializedObject.targetObject; 86 | string[] elements = path.Split('.'); 87 | 88 | foreach (string element in elements.Take(elements.Length)) 89 | { 90 | if (element.Contains("[")) 91 | { 92 | string elementName = element.Substring(0, element.IndexOf("[")); 93 | int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", "")); 94 | obj = GetValue(obj, elementName, index); 95 | } 96 | else 97 | { 98 | obj = GetValue(obj, element); 99 | } 100 | } 101 | 102 | return obj; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Editor/PropertyDiscovery.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 571200f8f2f47d8479888064865f6b38 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/com.atb.hackbox.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hackbox Editor", 3 | "references": [ 4 | "GUID:6fe8d6e668b30ef43af6d49072f7c997" 5 | ], 6 | "includePlatforms": [ 7 | "Editor" 8 | ], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": false, 11 | "overrideReferences": true, 12 | "precompiledReferences": [ 13 | "Newtonsoft.Json.dll", 14 | "SocketIOClient.dll", 15 | "websocket-sharp.dll" 16 | ], 17 | "autoReferenced": true, 18 | "defineConstraints": [], 19 | "versionDefines": [], 20 | "noEngineReferences": false 21 | } -------------------------------------------------------------------------------- /Editor/com.atb.hackbox.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d4e51c711080baa4e839a877d744a1c8 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ashley Muncaster / Devan Hurst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fa1bce0d960ddf04290dacd3110d5da3 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hackbox Unity 2 | 3 | A Unity Package that leverages [Hackbox](https://github.com/devanhurst/hackbox) to provide Jackbox-style interactive gameplay for Unity games. 4 | 5 | ## What is Hackbox.ca? 6 | 7 | [Hackbox.ca](https://hackbox.ca) is a web service provided by [devanhurst](https://github.com/devanhurst) that makes it super simple to create player interactions across the internet. In the simplest case, this could be basic buzzer functionality for online quizzes. In a complex case, this can be a social deduction game with individual player states and actions all happening simultaneously in the same room. 8 | 9 | ## What is Hackbox Unity? 10 | 11 | *Hackbox Unity* provides a Unity-friendly interface for interacting with Hackbox.ca servers, making it super simple to create online player interactions. 12 | 13 | ## Installing Hackbox Unity 14 | 15 | Unity 2019.3 and above is required. See the wiki page on [how to install Hackbox Unity](https://github.com/ashbash1987/hackbox-unity/wiki/Installation). 16 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd434b2cfd442b640890d6e900af50dc 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68d10ea47857b8040bb5d1769734476b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Attributes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 00741c59c859ccc41ab067884a8330dd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Attributes/BackgroundStringAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Hackbox 4 | { 5 | public class BackgroundStringAttribute : PropertyAttribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Runtime/Attributes/BackgroundStringAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9b828ea5c37fd7242a44a66b39bfd84e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Builders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 523bf96b06eef8a4e9dd7f8b3c804243 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Builders/ParameterListBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Hackbox.Parameters; 3 | 4 | namespace Hackbox.Builders 5 | { 6 | /// 7 | /// Builder class for constructing a ParameterList with various parameters. 8 | /// 9 | public sealed class ParameterListBuilder 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | public ParameterListBuilder() 15 | { 16 | ParameterList = new ParameterList(); 17 | } 18 | 19 | /// 20 | /// Gets the ParameterList being built. 21 | /// 22 | public ParameterList ParameterList 23 | { 24 | get; 25 | private set; 26 | } 27 | 28 | #region Public Methods 29 | /// 30 | /// Creates a new instance of the class. 31 | /// 32 | /// A new instance of . 33 | public static ParameterListBuilder Create() 34 | { 35 | return new ParameterListBuilder(); 36 | } 37 | 38 | /// 39 | /// Sets the 'choices' parameter. 40 | /// 41 | /// The list of choices to set. 42 | /// The current instance of . 43 | public ParameterListBuilder SetChoices(List choices) 44 | { 45 | ParameterList.SetParameterValue("choices", choices); 46 | return this; 47 | } 48 | 49 | /// 50 | /// Sets the 'event' parameter. 51 | /// 52 | /// The event name to set. 53 | /// The current instance of . 54 | public ParameterListBuilder SetEvent(string eventName) 55 | { 56 | ParameterList.SetParameterValue("event", eventName); 57 | return this; 58 | } 59 | 60 | /// 61 | /// Sets the 'label' parameter. 62 | /// 63 | /// The label to set. 64 | /// The current instance of . 65 | public ParameterListBuilder SetLabel(string label) 66 | { 67 | ParameterList.SetParameterValue("label", label); 68 | return this; 69 | } 70 | 71 | /// 72 | /// Sets the 'min' (minimum value) parameter. 73 | /// 74 | /// The minimum value to set. 75 | /// The current instance of . 76 | public ParameterListBuilder SetMinimum(int minimumValue) 77 | { 78 | ParameterList.SetParameterValue("min", minimumValue); 79 | return this; 80 | } 81 | 82 | /// 83 | /// Sets the 'max' (maximum value) parameter. 84 | /// 85 | /// The maximum value to set. 86 | /// The current instance of . 87 | public ParameterListBuilder SetMaximum(int maximumValue) 88 | { 89 | ParameterList.SetParameterValue("max", maximumValue); 90 | return this; 91 | } 92 | 93 | /// 94 | /// Sets the 'multiSelect' parameter. 95 | /// 96 | /// The multi-select value to set. 97 | /// The current instance of . 98 | public ParameterListBuilder SetMultiSelect(bool multiSelect) 99 | { 100 | ParameterList.SetParameterValue("multiSelect", multiSelect); 101 | return this; 102 | } 103 | 104 | /// 105 | /// Sets the 'min' and 'max' range parameters. 106 | /// 107 | /// The minimum value to set. 108 | /// The maximum value to set. 109 | /// The current instance of . 110 | public ParameterListBuilder SetRange(int minimumValue, int maximumValue) 111 | { 112 | SetMinimum(minimumValue); 113 | return SetMaximum(maximumValue); 114 | } 115 | 116 | /// 117 | /// Sets the 'persistent' parameter. 118 | /// 119 | /// The persistent value to set. 120 | /// The current instance of . 121 | public ParameterListBuilder SetPersistent(bool persistent) 122 | { 123 | ParameterList.SetParameterValue("persistent", persistent); 124 | return this; 125 | } 126 | 127 | /// 128 | /// Sets the 'step' parameter. 129 | /// 130 | /// The step value to set. 131 | /// The current instance of . 132 | public ParameterListBuilder SetStep(int step) 133 | { 134 | ParameterList.SetParameterValue("step", step); 135 | return this; 136 | } 137 | 138 | /// 139 | /// Sets the 'style' parameter. 140 | /// 141 | /// The style parameter list to set. 142 | /// The current instance of . 143 | public ParameterListBuilder SetStyle(ParameterList parameterList) 144 | { 145 | ParameterList.SetParameterValue("style", parameterList); 146 | return this; 147 | } 148 | 149 | /// 150 | /// Sets the 'submit' parameter. 151 | /// 152 | /// The submit parameter list to set. 153 | /// The current instance of . 154 | public ParameterListBuilder SetSubmit(ParameterList parameterList) 155 | { 156 | ParameterList.SetParameterValue("submit", parameterList); 157 | return this; 158 | } 159 | 160 | /// 161 | /// Sets the 'text' parameter. 162 | /// 163 | /// The text to set. 164 | /// The current instance of . 165 | public ParameterListBuilder SetText(string text) 166 | { 167 | ParameterList.SetParameterValue("text", text); 168 | return this; 169 | } 170 | 171 | /// 172 | /// Sets the 'type' parameter. 173 | /// 174 | /// The type to set. 175 | /// The current instance of . 176 | public ParameterListBuilder SetType(string type) 177 | { 178 | ParameterList.SetParameterValue("type", type); 179 | return this; 180 | } 181 | 182 | /// 183 | /// Implicitly converts a to a . 184 | /// 185 | /// The builder to convert. 186 | public static implicit operator ParameterList(ParameterListBuilder builder) => builder.ParameterList; 187 | #endregion 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Runtime/Builders/ParameterListBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad4c8609e231ab549a2ca37c7840c81e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Builders/PresetBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7a1e13dcbffc434b8e7e268917919eb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Builders/StateBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87e92c46f3527dd4f9a7b8d6a5d0d505 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Builders/StyleParameterListBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6500fecae235b44cb12a11e95533743 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Builders/ThemeBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UnityEngine; 3 | using Hackbox.UI; 4 | 5 | namespace Hackbox.Builders 6 | { 7 | /// 8 | /// A builder class for creating and configuring a . 9 | /// 10 | public sealed class ThemeBuilder 11 | { 12 | /// 13 | /// Initializes a new instance of the class with the specified name. 14 | /// 15 | /// The name of the theme. 16 | public ThemeBuilder(string name) 17 | { 18 | Theme = Theme.Create(name); 19 | } 20 | 21 | /// 22 | /// Gets the instance being built. 23 | /// 24 | public Theme Theme 25 | { 26 | get; 27 | private set; 28 | } 29 | 30 | #region Public Methods 31 | /// 32 | /// Creates a new instance with the specified name. 33 | /// 34 | /// The name of the theme. 35 | /// A new instance. 36 | public static ThemeBuilder Create(string name) 37 | { 38 | return new ThemeBuilder(name); 39 | } 40 | 41 | #region Header 42 | /// 43 | /// Sets the header color of the theme. 44 | /// 45 | /// The color to set. 46 | /// The current instance. 47 | public ThemeBuilder SetHeaderColor(Color color) 48 | { 49 | Theme.HeaderColor = color; 50 | return this; 51 | } 52 | 53 | /// 54 | /// Sets the header background of the theme. 55 | /// 56 | /// The background to set. 57 | /// The current instance. 58 | public ThemeBuilder SetHeaderBackground(string background) 59 | { 60 | Theme.HeaderBackground = background; 61 | return this; 62 | } 63 | 64 | /// 65 | /// Sets the header background using a solid color. 66 | /// 67 | /// The background color to set. 68 | /// The current instance. 69 | public ThemeBuilder SetHeaderBackgroundColor(Color backgroundColor) 70 | { 71 | return SetHeaderBackground(backgroundColor.ToColorString()); 72 | } 73 | 74 | /// 75 | /// Sets the header background using a linear gradient. 76 | /// 77 | /// The gradient to set. 78 | /// The angle of the gradient. 79 | /// The current instance. 80 | public ThemeBuilder SetHeaderBackgroundLinearGradient(Gradient gradient, float gradientAngle = 0.0f) 81 | { 82 | return SetHeaderBackground(gradient.ToLinearGradientString(gradientAngle)); 83 | } 84 | 85 | /// 86 | /// Sets the header background using a radial gradient. 87 | /// 88 | /// The gradient to set. 89 | /// The positioning of the gradient. 90 | /// The current instance. 91 | public ThemeBuilder SetHeaderBackgroundRadialGradient(Gradient gradient, string positioning = "circle at center") 92 | { 93 | return SetHeaderBackground(gradient.ToRadialGradientString(positioning)); 94 | } 95 | 96 | /// 97 | /// Sets the header background using an image. 98 | /// 99 | /// The URL of the image. 100 | /// The scaling and positioning of the image. 101 | /// The current instance of . 102 | public ThemeBuilder SetHeaderBackgroundImage(string url, string scalingAndPositioning = "no-repeat center / cover") 103 | { 104 | return SetHeaderBackground(url.ToImageString(scalingAndPositioning)); 105 | } 106 | 107 | /// 108 | /// Sets the minimum height of the header. 109 | /// 110 | /// The minimum height to set. 111 | /// The current instance. 112 | public ThemeBuilder SetHeaderMinimumHeight(string height = "50px") 113 | { 114 | Theme.HeaderMinHeight = height; 115 | return this; 116 | } 117 | 118 | /// 119 | /// Sets the minimum height of the header. 120 | /// 121 | /// The minimum height to set. 122 | /// The unit of the height. 123 | /// The current instance. 124 | public ThemeBuilder SetHeaderMinimumHeight(float height = 50, string dimensionUnit = "px") 125 | { 126 | return SetHeaderMinimumHeight($"{height}{dimensionUnit}"); 127 | } 128 | 129 | /// 130 | /// Sets the maximum height of the header. 131 | /// 132 | /// The maximum height to set. 133 | /// The current instance. 134 | public ThemeBuilder SetHeaderMaximumHeight(string height = "50px") 135 | { 136 | Theme.HeaderMaxHeight = height; 137 | return this; 138 | } 139 | 140 | /// 141 | /// Sets the maximum height of the header. 142 | /// 143 | /// The maximum height to set. 144 | /// The unit of the height. 145 | /// The current instance. 146 | public ThemeBuilder SetHeaderMaximumHeight(float height = 50, string dimensionUnit = "px") 147 | { 148 | return SetHeaderMaximumHeight($"{height}{dimensionUnit}"); 149 | } 150 | 151 | /// 152 | /// Sets the font family of the header. 153 | /// 154 | /// The font families to set. 155 | /// The current instance. 156 | public ThemeBuilder SetHeaderFontFamily(params string[] fontFamilies) 157 | { 158 | Theme.HeaderFontFamily = string.Join(", ", fontFamilies); 159 | return this; 160 | } 161 | #endregion 162 | 163 | #region Main 164 | /// 165 | /// Sets the main color of the theme. 166 | /// 167 | /// The color to set. 168 | /// The current instance. 169 | public ThemeBuilder SetMainColor(Color color) 170 | { 171 | Theme.MainColor = color; 172 | return this; 173 | } 174 | 175 | /// 176 | /// Sets the main background of the theme. 177 | /// 178 | /// The background to set. 179 | /// The current instance. 180 | public ThemeBuilder SetMainBackground(string background) 181 | { 182 | Theme.MainBackground = background; 183 | return this; 184 | } 185 | 186 | /// 187 | /// Sets the main background using a solid color. 188 | /// 189 | /// The background color to set. 190 | /// The current instance. 191 | public ThemeBuilder SetMainBackgroundColor(Color backgroundColor) 192 | { 193 | return SetMainBackground(backgroundColor.ToColorString()); 194 | } 195 | 196 | /// 197 | /// Sets the main background using a linear gradient. 198 | /// 199 | /// The gradient to set. 200 | /// The angle of the gradient. 201 | /// The current instance. 202 | public ThemeBuilder SetMainBackgroundLinearGradient(Gradient gradient, float gradientAngle = 0.0f) 203 | { 204 | return SetMainBackground(gradient.ToLinearGradientString(gradientAngle)); 205 | } 206 | 207 | /// 208 | /// Sets the main background using a radial gradient. 209 | /// 210 | /// The gradient to set. 211 | /// The positioning of the gradient. 212 | /// The current instance. 213 | public ThemeBuilder SetMainBackgroundRadialGradient(Gradient gradient, string positioning = "circle at center") 214 | { 215 | return SetMainBackground(gradient.ToRadialGradientString(positioning)); 216 | } 217 | 218 | /// 219 | /// Sets the main background using an image. 220 | /// 221 | /// The URL of the image. 222 | /// The scaling and positioning of the image. 223 | /// The current instance of . 224 | public ThemeBuilder SetMainBackgroundImage(string url, string scalingAndPositioning = "no-repeat center / cover") 225 | { 226 | return SetMainBackground(url.ToImageString(scalingAndPositioning)); 227 | } 228 | 229 | /// 230 | /// Sets the minimum width of the main section. 231 | /// 232 | /// The minimum width to set. 233 | /// The current instance. 234 | public ThemeBuilder SetMainMinimumWidth(string width = "300px") 235 | { 236 | Theme.MainMinWidth = width; 237 | return this; 238 | } 239 | 240 | /// 241 | /// Sets the minimum width of the main section. 242 | /// 243 | /// The minimum width to set. 244 | /// The unit of the width. 245 | /// The current instance. 246 | public ThemeBuilder SetMainMinimumWidth(float width = 300, string dimensionUnit = "px") 247 | { 248 | return SetMainMinimumWidth($"{width}{dimensionUnit}"); 249 | } 250 | 251 | /// 252 | /// Sets the maximum width of the main section. 253 | /// 254 | /// The maximum width to set. 255 | /// The current instance. 256 | public ThemeBuilder SetMainMaximumWidth(string width = "300px") 257 | { 258 | Theme.MainMaxWidth = width; 259 | return this; 260 | } 261 | 262 | /// 263 | /// Sets the maximum width of the main section. 264 | /// 265 | /// The maximum width to set. 266 | /// The unit of the width. 267 | /// The current instance. 268 | public ThemeBuilder SetMainMaximumWidth(float width = 350, string dimensionUnit = "px") 269 | { 270 | return SetMainMaximumWidth($"{width}{dimensionUnit}"); 271 | } 272 | #endregion 273 | 274 | /// 275 | /// Sets the fonts of the theme. 276 | /// 277 | /// The fonts to set. 278 | /// The current instance. 279 | public ThemeBuilder SetFonts(params string[] fonts) 280 | { 281 | Theme.Fonts = fonts.ToList(); 282 | return this; 283 | } 284 | 285 | /// 286 | /// Implicitly converts a to a . 287 | /// 288 | /// The instance to convert. 289 | /// The instance. 290 | public static implicit operator Theme(ThemeBuilder builder) => builder.Theme; 291 | #endregion 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /Runtime/Builders/ThemeBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1fa65e4161fb314faf5b8dd84c1c0d0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Events.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine.Events; 3 | 4 | namespace Hackbox 5 | { 6 | [Serializable] 7 | public class RoomCodeEvent : UnityEvent 8 | { 9 | public RoomCodeEvent() 10 | { 11 | } 12 | } 13 | 14 | [Serializable] 15 | public class MemberEvent : UnityEvent 16 | { 17 | public MemberEvent() 18 | { 19 | } 20 | } 21 | 22 | [Serializable] 23 | public class MessageEvent : UnityEvent 24 | { 25 | public MessageEvent() 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Runtime/Events.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ebd53c04370efff4a9483c4f3a8931cd 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Extensions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0c53fcfdc0d31b44b924cb941af4ba4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Extensions/ColorExtensions.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Hackbox 4 | { 5 | public static class ColorExtensions 6 | { 7 | public static string ToHTMLString(this Color color) 8 | { 9 | return $"#{ColorUtility.ToHtmlStringRGB(color)}"; 10 | } 11 | 12 | public static string ToHTMLStringWithAlpha(this Color color) 13 | { 14 | return $"#{ColorUtility.ToHtmlStringRGBA(color)}"; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Runtime/Extensions/ColorExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b1c5193dc15d193458037aa5ab1cb33e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Extensions/MarkdownExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c7503206033b7847913b6c0e09b3316 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Helpers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f05ff3412116c774291511cc24b16811 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Helpers/BackgroundHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using UnityEngine; 6 | 7 | namespace Hackbox 8 | { 9 | public static class BackgroundHelpers 10 | { 11 | #region Solid Color 12 | public static bool TryParseColor(this string value, out Color color) 13 | { 14 | return ColorUtility.TryParseHtmlString(value, out color); 15 | } 16 | 17 | public static string ToColorString(this Color color) 18 | { 19 | return color.ToHTMLStringWithAlpha(); 20 | } 21 | #endregion 22 | 23 | #region Linear Gradients 24 | public static bool TryParseLinearGradient(this string value, out Gradient gradient, out float gradientAngle) 25 | { 26 | Regex regex = new Regex(@"linear-gradient\((?[\d.]+)deg, (?(?#[\dA-Fa-f]+)\s+(?[\d.]+)%,?\s*)*\)"); 27 | Match match = regex.Match(value); 28 | 29 | if (match.Success) 30 | { 31 | gradientAngle = float.Parse(match.Groups["angle"].Value); 32 | gradient = new Gradient(); 33 | 34 | List colors = new List(); 35 | foreach (Capture capture in match.Groups["color"].Captures) 36 | { 37 | if (!ColorUtility.TryParseHtmlString(capture.Value, out Color color)) 38 | { 39 | color = Color.black; 40 | } 41 | 42 | colors.Add(color); 43 | } 44 | 45 | List progresses = new List(); 46 | foreach (Capture capture in match.Groups["progress"].Captures) 47 | { 48 | if (!float.TryParse(capture.Value, out float progress)) 49 | { 50 | progress = 0.0f; 51 | } 52 | 53 | progresses.Add(progress); 54 | } 55 | 56 | gradient.SetKeys(colors.Select((x, i) => new GradientColorKey(x, progresses[i] * 0.01f)).ToArray(), 57 | colors.Select((x, i) => new GradientAlphaKey(x.a, progresses[i] * 0.01f)).ToArray()); 58 | 59 | return true; 60 | } 61 | else 62 | { 63 | gradientAngle = 0.0f; 64 | gradient = new Gradient(); 65 | 66 | return false; 67 | } 68 | } 69 | 70 | public static string ToLinearGradientString(this Gradient gradient, float gradientAngle = 0.0f) 71 | { 72 | StringBuilder outputBuilder = new StringBuilder(); 73 | outputBuilder.Append($"linear-gradient({gradientAngle}deg, "); 74 | outputBuilder.Append(string.Join(", ", gradient.colorKeys.Select(x => x.time).Concat(gradient.alphaKeys.Select(x => x.time)).Distinct().OrderBy(x => x).Select(x => 75 | { 76 | Color keyColor = gradient.Evaluate(x); 77 | return $"{keyColor.ToHTMLStringWithAlpha()} {x * 100}%"; 78 | }))); 79 | outputBuilder.Append(")"); 80 | 81 | return outputBuilder.ToString(); 82 | } 83 | #endregion 84 | 85 | #region Radial Gradients 86 | public static bool TryParseRadialGradient(this string value, out Gradient gradient, out string positioning) 87 | { 88 | Regex regex = new Regex(@"radial-gradient\((?[^,]+), (?(?#[\dA-Fa-f]+)\s+(?[\d.]+)%,?\s*)*\)"); 89 | Match match = regex.Match(value); 90 | 91 | if (match.Success) 92 | { 93 | positioning = match.Groups["positioning"].Value; 94 | gradient = new Gradient(); 95 | 96 | List colors = new List(); 97 | foreach (Capture capture in match.Groups["color"].Captures) 98 | { 99 | if (!ColorUtility.TryParseHtmlString(capture.Value, out Color color)) 100 | { 101 | color = Color.black; 102 | } 103 | 104 | colors.Add(color); 105 | } 106 | 107 | List progresses = new List(); 108 | foreach (Capture capture in match.Groups["progress"].Captures) 109 | { 110 | if (!float.TryParse(capture.Value, out float progress)) 111 | { 112 | progress = 0.0f; 113 | } 114 | 115 | progresses.Add(progress); 116 | } 117 | 118 | gradient.SetKeys(colors.Select((x, i) => new GradientColorKey(x, progresses[i] * 0.01f)).ToArray(), 119 | colors.Select((x, i) => new GradientAlphaKey(x.a, progresses[i] * 0.01f)).ToArray()); 120 | 121 | return true; 122 | } 123 | else 124 | { 125 | positioning = "circle at center"; 126 | gradient = new Gradient(); 127 | 128 | return false; 129 | } 130 | } 131 | 132 | public static string ToRadialGradientString(this Gradient gradient, string positioning = "circle at center") 133 | { 134 | StringBuilder outputBuilder = new StringBuilder(); 135 | outputBuilder.Append($"radial-gradient({positioning}, "); 136 | outputBuilder.Append(string.Join(", ", gradient.colorKeys.Select(x => x.time).Concat(gradient.alphaKeys.Select(x => x.time)).Distinct().OrderBy(x => x).Select(x => 137 | { 138 | Color keyColor = gradient.Evaluate(x); 139 | return $"{keyColor.ToHTMLStringWithAlpha()} {x * 100}%"; 140 | }))); 141 | outputBuilder.Append(")"); 142 | 143 | return outputBuilder.ToString(); 144 | } 145 | #endregion 146 | 147 | #region Images 148 | public static bool TryParseImage(this string value, out string url, out string scalingAndPositioning) 149 | { 150 | Regex regex = new Regex(@"url\((?[^)]+)\) (?[^)]+)"); 151 | Match match = regex.Match(value); 152 | 153 | if (match.Success) 154 | { 155 | url = match.Groups["url"].Value.Replace("\"", "").Replace("'", ""); 156 | scalingAndPositioning = match.Groups["scalingAndPositioning"].Value; 157 | 158 | return true; 159 | } 160 | else 161 | { 162 | url = string.Empty; 163 | scalingAndPositioning = string.Empty; 164 | 165 | return false; 166 | } 167 | } 168 | 169 | public static string ToImageString(this string url, string scalingAndPositioning = "no-repeat center / cover") 170 | { 171 | return $"url(\"{url}\") {scalingAndPositioning}"; 172 | } 173 | #endregion 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /Runtime/Helpers/BackgroundHelpers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8fa430f26e75a644b9efb898c712454 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Helpers/MarkdownHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | 4 | namespace Hackbox 5 | { 6 | /// 7 | /// Helper class for generating Markdown formatted strings. 8 | /// 9 | public static class MarkdownHelpers 10 | { 11 | /// 12 | /// Generates a Markdown H1 header. 13 | /// 14 | /// The text to format as an H1 header. 15 | /// A Markdown formatted H1 header string. 16 | public static string H1(string text) => $"# {text}\n"; 17 | 18 | /// 19 | /// Generates a Markdown H2 header. 20 | /// 21 | /// The text to format as an H2 header. 22 | /// A Markdown formatted H2 header string. 23 | public static string H2(string text) => $"## {text}\n"; 24 | 25 | /// 26 | /// Generates a Markdown H3 header. 27 | /// 28 | /// The text to format as an H3 header. 29 | /// A Markdown formatted H3 header string. 30 | public static string H3(string text) => $"### {text}\n"; 31 | 32 | /// 33 | /// Formats text as bold in Markdown. 34 | /// 35 | /// The text to format as bold. 36 | /// A Markdown formatted bold string. 37 | public static string Bold(string text) => $"**{text}**"; 38 | 39 | /// 40 | /// Formats text as italics in Markdown. 41 | /// 42 | /// The text to format as italics. 43 | /// A Markdown formatted italics string. 44 | public static string Italics(string text) => $"*{text}*"; 45 | 46 | /// 47 | /// Formats text with strikethrough in Markdown. 48 | /// 49 | /// The text to format with strikethrough. 50 | /// A Markdown formatted strikethrough string. 51 | public static string Strikethrough(string text) => $"~~{text}~~"; 52 | 53 | /// 54 | /// Formats text as a blockquote in Markdown. 55 | /// 56 | /// The text to format as a blockquote. 57 | /// A Markdown formatted blockquote string. 58 | public static string Blockquote(string text) => $"> {text}"; 59 | 60 | /// 61 | /// Generates a Markdown ordered list. 62 | /// 63 | /// The list entries. 64 | /// A Markdown formatted ordered list string. 65 | public static string OrderedList(string[] entries) => string.Join("", entries.Select((x, i) => $"{i + 1}. {x} \n")); 66 | 67 | /// 68 | /// Generates a Markdown unordered list. 69 | /// 70 | /// The list entries. 71 | /// A Markdown formatted unordered list string. 72 | public static string UnorderedList(string[] entries) => string.Join("", entries.Select(x => $"- {x} \n")); 73 | 74 | /// 75 | /// Formats text as inline code in Markdown. 76 | /// 77 | /// The text to format as inline code. 78 | /// A Markdown formatted inline code string. 79 | public static string Code(string text) => $"`{text}`"; 80 | 81 | /// 82 | /// Formats text as a code block in Markdown. 83 | /// 84 | /// The text to format as a code block. 85 | /// A Markdown formatted code block string. 86 | public static string CodeBlock(string text) => $"```\n{text}\n```\n"; 87 | 88 | /// 89 | /// Generates a Markdown link. 90 | /// 91 | /// The link title. 92 | /// The URL of the link. 93 | /// A Markdown formatted link string. 94 | public static string Link(string title, string link) => $"[{title}]({link})"; 95 | 96 | /// 97 | /// Generates a Markdown image. 98 | /// 99 | /// The alt text for the image. 100 | /// The URL of the image. 101 | /// A Markdown formatted image string. 102 | public static string Image(string altText, string link) => $"![{altText}]({link})"; 103 | 104 | /// 105 | /// Joins multiple lines into a single Markdown formatted string with line breaks. 106 | /// 107 | /// The lines to join. 108 | /// A Markdown formatted string with line breaks. 109 | public static string Multiline(params string[] lines) => string.Join(LineBreak, lines); 110 | 111 | /// 112 | /// Generates a Markdown table. 113 | /// 114 | /// The table headers. 115 | /// The table data. 116 | /// A Markdown formatted table string. 117 | public static string Table(string[] headers, string[,] data) 118 | { 119 | StringBuilder sb = new StringBuilder(); 120 | sb.Append($"| {string.Join(" | ", headers)} |\n"); 121 | sb.Append($"| {string.Join(" | ", headers.Select(_ => "---"))} |\n"); 122 | 123 | int rowCount = data.GetLength(0); 124 | int columnCount = data.GetLength(1); 125 | for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) 126 | { 127 | sb.Append($"| {string.Join(" | ", Enumerable.Range(0, columnCount).Select(x => data[rowIndex, x]))} |\n"); 128 | } 129 | 130 | return sb.ToString(); 131 | } 132 | 133 | /// 134 | /// Formats text with custom styling using a span element. 135 | /// 136 | /// The styling properties and values. 137 | /// The text to format. 138 | /// A Markdown formatted string with custom styling. 139 | public static string Span((string property, string value)[] styling, string text) => $" $"{x.property}: {x.value}"))}\">{text}"; 140 | 141 | /// 142 | /// Formats text with custom styling using a div element. 143 | /// 144 | /// The styling properties and values. 145 | /// The text to format. 146 | /// A Markdown formatted string with custom styling. 147 | public static string Div((string property, string value)[] styling, string text) => $"
$"{x.property}: {x.value}"))}\">{text}
"; 148 | 149 | /// 150 | /// Gets a Markdown line break. 151 | /// 152 | public static string LineBreak => "
"; 153 | 154 | /// 155 | /// Gets a Markdown horizontal rule. 156 | /// 157 | public static string HorizontalRule => "
"; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Runtime/Helpers/MarkdownHelpers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 807fd06ab07523548a908ca3ddb458d7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Host.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7783147471dfc748939757a8440123d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Member.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json.Linq; 3 | 4 | namespace Hackbox 5 | { 6 | public class Member 7 | { 8 | #region Identity Types 9 | public class TwitchIdentity : IEquatable 10 | { 11 | internal TwitchIdentity(JObject data) 12 | { 13 | Update(data); 14 | } 15 | 16 | public string ID 17 | { 18 | get; 19 | private set; 20 | } 21 | 22 | public string UserName 23 | { 24 | get; 25 | private set; 26 | } 27 | 28 | public string AvatarURL 29 | { 30 | get; 31 | private set; 32 | } 33 | 34 | public void Update(JObject data) 35 | { 36 | ID = (string)data["id"]; 37 | UserName = (string)data["username"]; 38 | AvatarURL = (string)data["photo"]; 39 | } 40 | 41 | public override string ToString() 42 | { 43 | if (string.IsNullOrEmpty(ID)) 44 | { 45 | return ""; 46 | } 47 | 48 | return $"{UserName} [{ID}]"; 49 | } 50 | 51 | public override bool Equals(object obj) 52 | { 53 | if (obj is TwitchIdentity other) 54 | { 55 | if (!string.IsNullOrEmpty(ID)) 56 | { 57 | return ID.Equals(other.ID); 58 | } 59 | 60 | return string.IsNullOrEmpty(other.ID); 61 | } 62 | 63 | return false; 64 | } 65 | 66 | public bool Equals(TwitchIdentity other) 67 | { 68 | if (!string.IsNullOrEmpty(ID)) 69 | { 70 | return ID.Equals(other.ID); 71 | } 72 | 73 | return string.IsNullOrEmpty(other.ID); 74 | } 75 | 76 | public override int GetHashCode() 77 | { 78 | return ID?.GetHashCode() ?? UserName?.GetHashCode() ?? 0; 79 | } 80 | 81 | public static bool operator == (TwitchIdentity lhs, TwitchIdentity rhs) 82 | { 83 | if (Object.ReferenceEquals(lhs, null) && Object.ReferenceEquals(rhs, null)) 84 | { 85 | return true; 86 | } 87 | 88 | if ((Object.ReferenceEquals(lhs, null) && !Object.ReferenceEquals(rhs, null)) || 89 | (Object.ReferenceEquals(rhs, null) && !Object.ReferenceEquals(lhs, null))) 90 | { 91 | return false; 92 | } 93 | 94 | return lhs.Equals(rhs); 95 | } 96 | 97 | public static bool operator != (TwitchIdentity lhs, TwitchIdentity rhs) 98 | { 99 | return !(lhs == rhs); 100 | } 101 | } 102 | #endregion 103 | 104 | internal Member(JObject data) 105 | { 106 | Update(data); 107 | State = new State(); 108 | } 109 | 110 | public MessageEvent OnMessage = new MessageEvent(); 111 | public MessageEvent OnValueChange = new MessageEvent(); 112 | 113 | public readonly MessageEventCollection MessageEvents = new MessageEventCollection(); 114 | public readonly MessageEventCollection ValueChangeEvents = new MessageEventCollection(); 115 | 116 | public string UserID 117 | { 118 | get; 119 | private set; 120 | } 121 | 122 | public string Name 123 | { 124 | get; 125 | set; 126 | } 127 | 128 | public TwitchIdentity Twitch 129 | { 130 | get; 131 | private set; 132 | } 133 | 134 | public State State 135 | { 136 | get; 137 | internal set; 138 | } 139 | 140 | public void Update(JObject data) 141 | { 142 | UserID = (string)data["id"]; 143 | Name = (string)data["name"]; 144 | 145 | if (data.ContainsKey("metadata")) 146 | { 147 | UpdateMetadata((JObject)data["metadata"]); 148 | } 149 | } 150 | 151 | public override int GetHashCode() 152 | { 153 | return UserID.GetHashCode(); 154 | } 155 | 156 | public override bool Equals(object obj) 157 | { 158 | if (obj is Member otherMember) 159 | { 160 | return UserID == otherMember.UserID; 161 | } 162 | 163 | return false; 164 | } 165 | 166 | private void UpdateMetadata(JObject metaData) 167 | { 168 | if (metaData.ContainsKey("twitch")) 169 | { 170 | JObject twitchData = (JObject)metaData["twitch"]; 171 | if (Twitch == null) 172 | { 173 | Twitch = new TwitchIdentity(twitchData); 174 | } 175 | else 176 | { 177 | Twitch.Update(twitchData); 178 | } 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Runtime/Member.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 09a42e87dc08c2f4193df13f3e0d1e38 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox 6 | { 7 | public sealed class Message 8 | { 9 | internal Message(Member member, string id, DateTimeOffset time, JObject messageData) 10 | { 11 | Member = member; 12 | ID = id; 13 | Timestamp = time; 14 | MessageData = messageData; 15 | } 16 | 17 | public readonly Member Member; 18 | public readonly string ID; 19 | public readonly DateTimeOffset Timestamp; 20 | public readonly JObject MessageData; 21 | 22 | public string Event 23 | { 24 | get => MessageData.ContainsKey("event") ? (string)MessageData["event"] : null; 25 | } 26 | 27 | public int Milliseconds 28 | { 29 | get => MessageData.ContainsKey("ms") ? (int)MessageData["ms"] : 0; 30 | } 31 | 32 | public string Value 33 | { 34 | get 35 | { 36 | string[] values = Values; 37 | if (values == null || values.Length == 0) 38 | { 39 | return null; 40 | } 41 | if (values.Length == 1) 42 | { 43 | return values[0]; 44 | } 45 | 46 | return string.Join(",", values); 47 | } 48 | } 49 | 50 | public string[] Values 51 | { 52 | get 53 | { 54 | if (!MessageData.TryGetValue("value", out JToken value)) 55 | { 56 | return null; 57 | } 58 | 59 | if (value is JArray valueArray) 60 | { 61 | return valueArray.Values().ToArray(); 62 | } 63 | 64 | if (value is JValue) 65 | { 66 | return new[] { (string)value }; 67 | } 68 | 69 | if (value is JObject) 70 | { 71 | return new[] { value.ToString() }; 72 | } 73 | 74 | return null; 75 | } 76 | } 77 | 78 | public override string ToString() 79 | { 80 | if (string.IsNullOrEmpty(Value)) 81 | { 82 | return $"[{Timestamp}|{ID}]: {Event}"; 83 | } 84 | 85 | return $"[{Timestamp}|{ID}]: {Event}=[{Value}]"; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Runtime/Message.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5c80ac69102e264984b6b08064a896b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/MessageEventCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine.Events; 3 | 4 | namespace Hackbox 5 | { 6 | public sealed class MessageEventCollection 7 | { 8 | public MessageEvent this[string eventName] 9 | { 10 | get => GetMessageEvent(eventName); 11 | } 12 | 13 | private readonly Dictionary Events = new Dictionary(); 14 | 15 | public void AddListener(string eventName, UnityAction listener) 16 | { 17 | GetMessageEvent(eventName).AddListener(listener); 18 | } 19 | 20 | public void RemoveListener(string eventName, UnityAction listener) 21 | { 22 | GetMessageEvent(eventName).RemoveListener(listener); 23 | } 24 | 25 | public void RemoveAllListeners(string eventName) 26 | { 27 | GetMessageEvent(eventName).RemoveAllListeners(); 28 | } 29 | 30 | public void Invoke(string eventName, Message message) 31 | { 32 | GetMessageEvent(eventName, false)?.Invoke(message); 33 | } 34 | 35 | private MessageEvent GetMessageEvent(string eventName, bool create = true) 36 | { 37 | if (!Events.TryGetValue(eventName, out MessageEvent messageEvent)) 38 | { 39 | messageEvent = new MessageEvent(); 40 | Events[eventName] = messageEvent; 41 | } 42 | 43 | return messageEvent; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Runtime/MessageEventCollection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 214b19e884b025748919b551f6e9574e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/MessageEventQueue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Hackbox 5 | { 6 | public class MessageEventQueue : MonoBehaviour 7 | { 8 | public Host Host = null; 9 | public Member[] Members = null; 10 | public string[] EventNames = null; 11 | 12 | public bool ClearOnEnable = false; 13 | public bool ClearOnDisable = false; 14 | 15 | public bool HasMessages => MessageQueue.Count > 0; 16 | 17 | private readonly Queue MessageQueue = new Queue(); 18 | private Member[] _currentMembers = null; 19 | 20 | private void OnEnable() 21 | { 22 | if (ClearOnEnable) 23 | { 24 | Clear(); 25 | } 26 | CreateListeners(); 27 | } 28 | 29 | private void OnDisable() 30 | { 31 | if (ClearOnDisable) 32 | { 33 | Clear(); 34 | } 35 | DestroyListeners(); 36 | } 37 | 38 | private void OnDestroy() 39 | { 40 | DestroyListeners(); 41 | } 42 | 43 | private void Update() 44 | { 45 | if (Members != _currentMembers) 46 | { 47 | DestroyListeners(); 48 | _currentMembers = Members; 49 | CreateListeners(); 50 | } 51 | } 52 | 53 | /// 54 | /// Returns the next message in the queue, and removes it from the queue collection. 55 | /// 56 | /// The next message in the queue. 57 | public Message Dequeue() 58 | { 59 | return MessageQueue.Dequeue(); 60 | } 61 | 62 | /// 63 | /// Returns the next message in the queue, but does not remove it from the queue collection. 64 | /// 65 | /// The next message in the queue. 66 | public Message Peek() 67 | { 68 | return MessageQueue.Peek(); 69 | } 70 | 71 | /// 72 | /// Clears the message queue. 73 | /// 74 | public void Clear() 75 | { 76 | MessageQueue.Clear(); 77 | } 78 | 79 | private void CreateListeners() 80 | { 81 | foreach (string eventName in EventNames) 82 | { 83 | if (_currentMembers != null) 84 | { 85 | foreach (Member member in _currentMembers) 86 | { 87 | member.MessageEvents.AddListener(eventName, OnMessage); 88 | } 89 | } 90 | else 91 | { 92 | Host.MessageEvents.AddListener(eventName, OnMessage); 93 | } 94 | } 95 | } 96 | 97 | private void DestroyListeners() 98 | { 99 | foreach (string eventName in EventNames) 100 | { 101 | if (_currentMembers != null) 102 | { 103 | foreach (Member member in _currentMembers) 104 | { 105 | member.MessageEvents.RemoveListener(eventName, OnMessage); 106 | } 107 | } 108 | else 109 | { 110 | Host.MessageEvents.RemoveListener(eventName, OnMessage); 111 | } 112 | } 113 | } 114 | 115 | private void OnMessage(Message message) 116 | { 117 | MessageQueue.Enqueue(message); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Runtime/MessageEventQueue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c05d6d284f6621f45959d9e815b0a0e3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b80a61712712a945a43d3ac1517d5be 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Parameters/BoolParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class BoolParameter : Parameter 9 | { 10 | public BoolParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public BoolParameter(bool value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public BoolParameter(BoolParameter from) : 22 | base(from) 23 | { 24 | Value = from.Value; 25 | } 26 | 27 | public override bool Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | public bool _value; 35 | 36 | public override void ApplyValueToJObject(JObject parent, int version) 37 | { 38 | parent[Name] = Value; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Parameters/BoolParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c63052a5206da4843bb4412b2c3506c2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/ChoicesParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Hackbox.Parameters 8 | { 9 | using ChoiceList = List; 10 | 11 | [Serializable] 12 | public class ChoicesParameter : Parameter 13 | { 14 | [Serializable] 15 | public class Choice 16 | { 17 | public Choice() 18 | { 19 | } 20 | 21 | public Choice(Choice other) 22 | { 23 | Label = other.Label; 24 | Value = other.Value; 25 | Keys = new string[other.Keys.Length]; 26 | Array.Copy(other.Keys, Keys, other.Keys.Length); 27 | StyleParameterList = new ParameterList(other.StyleParameterList); 28 | } 29 | 30 | [Tooltip("The text that is shown to the user in the choice button.")] 31 | public string Label = ""; 32 | [Tooltip("The value that is returned if the user selects this choice button.")] 33 | public string Value = ""; 34 | [Tooltip("The keys on a keyboard that can be pressed to select this choice button.")] 35 | public string[] Keys = new string[0]; 36 | 37 | public ParameterList StyleParameterList = new ParameterList(); 38 | 39 | internal JObject GenerateJSON(int version) 40 | { 41 | JObject choiceObject = new JObject(); 42 | 43 | choiceObject["label"] = Label; 44 | choiceObject["value"] = Value; 45 | choiceObject["keys"] = new JArray(Keys); 46 | 47 | if (Keys != null) 48 | { 49 | choiceObject["keys"] = new JArray(Keys); 50 | } 51 | 52 | if (StyleParameterList != null && StyleParameterList.Parameters.Count > 0 && version >= 2) 53 | { 54 | choiceObject["style"] = GenerateStyleProps(version); 55 | } 56 | 57 | return choiceObject; 58 | } 59 | 60 | private JObject GenerateStyleProps(int version) 61 | { 62 | JObject props = new JObject(); 63 | foreach (Parameter parameter in StyleParameterList.Parameters) 64 | { 65 | parameter.ApplyValueToJObject(props, version); 66 | } 67 | 68 | return props; 69 | } 70 | } 71 | 72 | public ChoicesParameter() : 73 | base() 74 | { 75 | Value = new ChoiceList(); 76 | } 77 | 78 | public ChoicesParameter(ChoiceList value) : 79 | base() 80 | { 81 | Value = value; 82 | } 83 | 84 | public ChoicesParameter(ChoicesParameter from): 85 | base(from) 86 | { 87 | Value = new ChoiceList(from.Value.Select(x => new Choice(x))); 88 | } 89 | 90 | public override ChoiceList Value 91 | { 92 | get => _value; 93 | set => _value = value; 94 | } 95 | 96 | [SerializeField] 97 | public ChoiceList _value = new ChoiceList(); 98 | 99 | public override void ApplyValueToJObject(JObject parent, int version) 100 | { 101 | parent[Name] = new JArray(Value.Select(x => x.GenerateJSON(version)).ToArray()); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /Runtime/Parameters/ChoicesParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bbb01fef88245a647afc8128d7dc7684 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/ColorParameter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using UnityEngine; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class ColorParameter : Parameter 9 | { 10 | public ColorParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public ColorParameter(Color value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public ColorParameter(ColorParameter from) : 22 | base(from) 23 | { 24 | Value = from.Value; 25 | } 26 | 27 | public override Color Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | public Color _value; 35 | 36 | public override void ApplyValueToJObject(JObject parent, int version) 37 | { 38 | parent[Name] = Value.ToHTMLString(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Parameters/ColorParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ba64e362ab0a954da5cc69ce6d5cd4c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/DefaultParameters.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6920ce43367e77f48a82cdf6a071c1b1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/IParameterList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Hackbox.Parameters 4 | { 5 | public interface IParameterList : IEnumerable 6 | { 7 | Parameter this[string parameterName] 8 | { 9 | get; 10 | } 11 | 12 | Parameter GetGenericParameter(string parameterName); 13 | ParamT GetParameter(string parameterName) where ParamT : Parameter, new(); 14 | ValueT GetParameterValue(string parameterName); 15 | void SetParameterValue(string parameterName, ValueT value); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Runtime/Parameters/IParameterList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6b0d7a24a69bd048b69c1abaa41a160 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/IStyleParameterList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Hackbox.Parameters 4 | { 5 | public interface IStyleParameterList : IEnumerable 6 | { 7 | Parameter GetGenericStyleParameter(string parameterName); 8 | ParamT GetStyleParameter(string parameterName) where ParamT : Parameter, new(); 9 | ValueT GetStyleParameterValue(string parameterName); 10 | void SetStyleParameterValue(string parameterName, ValueT value); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Runtime/Parameters/IStyleParameterList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38d988a53774c4242aaa1a271c2ead4f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/IntParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class IntParameter : Parameter 9 | { 10 | public IntParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public IntParameter(int value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public IntParameter(IntParameter from) : 22 | base(from) 23 | { 24 | Value = from.Value; 25 | } 26 | 27 | public override int Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | public int _value; 35 | 36 | public override void ApplyValueToJObject(JObject parent, int version) 37 | { 38 | parent[Name] = Value; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Parameters/IntParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdfc9834217eba94885b7e399e9c8049 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/Parameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json.Linq; 3 | 4 | namespace Hackbox.Parameters 5 | { 6 | [Serializable] 7 | public class Parameter 8 | { 9 | public Parameter() 10 | { 11 | } 12 | 13 | public Parameter(Parameter from) 14 | { 15 | Name = from.Name; 16 | } 17 | 18 | public string Name = ""; 19 | 20 | public virtual void ApplyValueToJObject(JObject parent, int version) 21 | { 22 | } 23 | } 24 | 25 | [Serializable] 26 | public class Parameter : Parameter 27 | { 28 | public Parameter() 29 | { 30 | } 31 | 32 | public Parameter(T value) 33 | { 34 | Value = value; 35 | } 36 | 37 | public virtual T Value 38 | { 39 | get; 40 | set; 41 | } 42 | 43 | public Parameter(Parameter from): 44 | base(from) 45 | { 46 | Value = from.Value; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Runtime/Parameters/Parameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 58264ebe3ec173046ab777d8aef40634 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | 7 | namespace Hackbox.Parameters 8 | { 9 | [Serializable] 10 | public sealed class ParameterList : IParameterList 11 | { 12 | public ParameterList() 13 | { 14 | } 15 | 16 | public ParameterList(ParameterList from) 17 | { 18 | Parameters = new List(from.Parameters.Select(x => (Parameter)Activator.CreateInstance(x.GetType(), x))); 19 | } 20 | 21 | [HideInInspector] 22 | [SerializeReference] 23 | public List Parameters = new List(); 24 | 25 | public Parameter this[int parameterIndex] => Parameters[parameterIndex]; 26 | public Parameter this[string parameterName] => Parameters.Find(x => x.Name == parameterName); 27 | 28 | #region IEnumerable Interface & Collection Initialiser Implementation 29 | public IEnumerator GetEnumerator() 30 | { 31 | return Parameters.GetEnumerator(); 32 | } 33 | 34 | public void Add(string parameterName, T value) 35 | { 36 | if (value is Parameter parameter) 37 | { 38 | int existingIndex = Parameters.FindIndex(x => x.Name == parameterName); 39 | parameter.Name = parameterName; 40 | if (existingIndex >= 0) 41 | { 42 | Parameters[existingIndex] = parameter; 43 | } 44 | else 45 | { 46 | Parameters.Add(parameter); 47 | } 48 | } 49 | else 50 | { 51 | SetParameterValue(parameterName, value); 52 | } 53 | } 54 | #endregion 55 | 56 | #region Public Methods 57 | public Parameter GetGenericParameter(string parameterName) 58 | { 59 | Parameter parameter = this[parameterName]; 60 | if (parameter is Parameter typedParameter) 61 | { 62 | return typedParameter; 63 | } 64 | 65 | if (parameter != null) 66 | { 67 | throw new Exception($"Trying to get parameter {parameterName} but using the wrong parameter type. Expected {parameter.GetType().Name}, asking for {typeof(ValueT).Name}"); 68 | } 69 | 70 | Parameter newParameter = DefaultParameters.CreateDefaultAnyParameter(parameterName); 71 | if (newParameter is Parameter newTypedParameter) 72 | { 73 | Parameters.Add(newTypedParameter); 74 | return newTypedParameter; 75 | } 76 | 77 | return null; 78 | } 79 | 80 | public ParamT GetParameter(string parameterName) where ParamT: Parameter, new() 81 | { 82 | Parameter parameter = this[parameterName]; 83 | if (parameter is ParamT typedParameter) 84 | { 85 | return typedParameter; 86 | } 87 | 88 | if (parameter != null) 89 | { 90 | throw new Exception($"Trying to get parameter {parameterName} but using the wrong parameter type. Expected {parameter.GetType().Name}, asking for {typeof(ParamT).Name}"); 91 | } 92 | 93 | Parameter newParameter = DefaultParameters.CreateDefaultAnyParameter(parameterName); 94 | if (newParameter is ParamT newTypedParameter) 95 | { 96 | Parameters.Add(newTypedParameter); 97 | return newTypedParameter; 98 | } 99 | 100 | return null; 101 | } 102 | 103 | public ValueT GetParameterValue(string parameterName) 104 | { 105 | return GetGenericParameter(parameterName).Value; 106 | } 107 | 108 | public void SetParameterValue(string parameterName, ValueT value) 109 | { 110 | GetGenericParameter(parameterName).Value = value; 111 | } 112 | #endregion 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c51e432e519fbdb459efa67abd93be0d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterListAttributes.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Hackbox.Parameters 4 | { 5 | public class StyleParameterListAttribute : PropertyAttribute 6 | { 7 | } 8 | 9 | public class NormalParameterListAttribute : PropertyAttribute 10 | { 11 | } 12 | 13 | public class HeaderParameterListAttribute : PropertyAttribute 14 | { 15 | } 16 | 17 | public class MainParameterListAttribute : PropertyAttribute 18 | { 19 | } 20 | 21 | public class AnyParameterListAttribute : PropertyAttribute 22 | { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterListAttributes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d944c1c5b59276245be7e5c046cc3d26 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterListParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class ParameterListParameter : Parameter 9 | { 10 | public ParameterListParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public ParameterListParameter(ParameterList value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public ParameterListParameter(ParameterListParameter from): 22 | base(from) 23 | { 24 | Value = new ParameterList(from.Value); 25 | } 26 | 27 | public override ParameterList Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | [SerializeReference] 35 | public ParameterList _value = new ParameterList(); 36 | 37 | public override void ApplyValueToJObject(JObject parent, int version) 38 | { 39 | JObject parametersObject = new JObject(); 40 | foreach (Parameter parameter in Value.Parameters) 41 | { 42 | parameter.ApplyValueToJObject(parametersObject, version); 43 | } 44 | 45 | parent[Name] = parametersObject; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Runtime/Parameters/ParameterListParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcf1bdd327b0d9c45a84976812b5b768 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/StringArrayParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class StringArrayParameter : Parameter 9 | { 10 | public StringArrayParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public StringArrayParameter(string[] value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public StringArrayParameter(StringArrayParameter from) : 22 | base(from) 23 | { 24 | Value = from.Value; 25 | } 26 | 27 | public override string[] Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | public string[] _value; 35 | 36 | public override void ApplyValueToJObject(JObject parent, int version) 37 | { 38 | parent[Name] = new JArray(Value); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Parameters/StringArrayParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c8d2ce66b87f901498cece4317bef4b4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Parameters/StringParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox.Parameters 6 | { 7 | [Serializable] 8 | public class StringParameter : Parameter 9 | { 10 | public StringParameter() : 11 | base() 12 | { 13 | } 14 | 15 | public StringParameter(string value) : 16 | base() 17 | { 18 | Value = value; 19 | } 20 | 21 | public StringParameter(StringParameter from) : 22 | base(from) 23 | { 24 | Value = from.Value; 25 | } 26 | 27 | public override string Value 28 | { 29 | get => _value; 30 | set => _value = value; 31 | } 32 | 33 | [SerializeField] 34 | public string _value; 35 | 36 | public override void ApplyValueToJObject(JObject parent, int version) 37 | { 38 | parent[Name] = Value; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Parameters/StringParameter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 434fad60775e5d043b094324ea3ed711 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Sockets.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 871b75f648fccda4ea45284c21335305 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Sockets/ISocketIO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Hackbox 6 | { 7 | internal interface ISocketIO 8 | { 9 | event Action OnConnected; 10 | event Action OnError; 11 | event Action OnDisconnected; 12 | event Action OnReconnectAttempt; 13 | event Action OnReconnected; 14 | event Action OnReconnectFailed; 15 | event Action OnPing; 16 | event Action OnPong; 17 | 18 | bool Connected { get; } 19 | bool Disconnected { get; } 20 | 21 | Task Connect(); 22 | Task Disconnect(); 23 | 24 | Task Emit(string eventName, JObject message); 25 | 26 | void On(string eventName, Action messageHandler); 27 | void Off(string eventName); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Runtime/Sockets/ISocketIO.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b483538c60e3e554daa8fcd43b250303 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d2e3ad802b25964c8258b9758efabdc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ec99353fb987cf41b3415d2b280d04c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashbash1987/hackbox-unity/2c69018ade8fc478c15a8f760360229f951532c4/Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.Newtonsoft.Json.dll -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.Newtonsoft.Json.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3dd545eb8bbe9eb4d96b44c2c3a1968b 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | : Any 16 | second: 17 | enabled: 0 18 | settings: 19 | Exclude Android: 1 20 | Exclude Editor: 0 21 | Exclude Linux64: 0 22 | Exclude OSXUniversal: 0 23 | Exclude WebGL: 1 24 | Exclude Win: 0 25 | Exclude Win64: 0 26 | Exclude iOS: 1 27 | Exclude tvOS: 1 28 | - first: 29 | Android: Android 30 | second: 31 | enabled: 0 32 | settings: 33 | CPU: ARMv7 34 | - first: 35 | Any: 36 | second: 37 | enabled: 0 38 | settings: {} 39 | - first: 40 | Editor: Editor 41 | second: 42 | enabled: 1 43 | settings: 44 | CPU: AnyCPU 45 | DefaultValueInitialized: true 46 | OS: AnyOS 47 | - first: 48 | Standalone: Linux64 49 | second: 50 | enabled: 1 51 | settings: 52 | CPU: AnyCPU 53 | - first: 54 | Standalone: OSXUniversal 55 | second: 56 | enabled: 1 57 | settings: 58 | CPU: x86_64 59 | - first: 60 | Standalone: Win 61 | second: 62 | enabled: 1 63 | settings: 64 | CPU: x86 65 | - first: 66 | Standalone: Win64 67 | second: 68 | enabled: 1 69 | settings: 70 | CPU: x86_64 71 | - first: 72 | Windows Store Apps: WindowsStoreApps 73 | second: 74 | enabled: 0 75 | settings: 76 | CPU: AnyCPU 77 | - first: 78 | iPhone: iOS 79 | second: 80 | enabled: 0 81 | settings: 82 | AddToEmbeddedBinaries: false 83 | CPU: AnyCPU 84 | CompileFlags: 85 | FrameworkDependencies: 86 | - first: 87 | tvOS: tvOS 88 | second: 89 | enabled: 0 90 | settings: 91 | CPU: AnyCPU 92 | CompileFlags: 93 | FrameworkDependencies: 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashbash1987/hackbox-unity/2c69018ade8fc478c15a8f760360229f951532c4/Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.dll -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f142cd5e1c375b40bb6a6055ae4041d 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | : Any 16 | second: 17 | enabled: 0 18 | settings: 19 | Exclude Android: 1 20 | Exclude Editor: 0 21 | Exclude Linux64: 0 22 | Exclude OSXUniversal: 0 23 | Exclude WebGL: 1 24 | Exclude Win: 0 25 | Exclude Win64: 0 26 | Exclude iOS: 1 27 | Exclude tvOS: 1 28 | - first: 29 | Android: Android 30 | second: 31 | enabled: 0 32 | settings: 33 | CPU: ARMv7 34 | - first: 35 | Any: 36 | second: 37 | enabled: 0 38 | settings: {} 39 | - first: 40 | Editor: Editor 41 | second: 42 | enabled: 1 43 | settings: 44 | CPU: AnyCPU 45 | DefaultValueInitialized: true 46 | OS: AnyOS 47 | - first: 48 | Standalone: Linux64 49 | second: 50 | enabled: 1 51 | settings: 52 | CPU: AnyCPU 53 | - first: 54 | Standalone: OSXUniversal 55 | second: 56 | enabled: 1 57 | settings: 58 | CPU: x86_64 59 | - first: 60 | Standalone: Win 61 | second: 62 | enabled: 1 63 | settings: 64 | CPU: x86 65 | - first: 66 | Standalone: Win64 67 | second: 68 | enabled: 1 69 | settings: 70 | CPU: x86_64 71 | - first: 72 | Windows Store Apps: WindowsStoreApps 73 | second: 74 | enabled: 0 75 | settings: 76 | CPU: AnyCPU 77 | - first: 78 | iPhone: iOS 79 | second: 80 | enabled: 0 81 | settings: 82 | AddToEmbeddedBinaries: false 83 | CPU: AnyCPU 84 | CompileFlags: 85 | FrameworkDependencies: 86 | - first: 87 | tvOS: tvOS 88 | second: 89 | enabled: 0 90 | settings: 91 | CPU: AnyCPU 92 | CompileFlags: 93 | FrameworkDependencies: 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SocketIOClient 5 | 6 | 7 | 8 | 9 | The server calls the client's callback 10 | 11 | 12 | 13 | 14 | The server calls the client's callback with binary 15 | 16 | 17 | 18 | 19 | The client calls the server's callback 20 | 21 | 22 | 23 | 24 | The client calls the server's callback with binary 25 | 26 | 27 | 28 | 29 | Eio3 ping is sent by the client 30 | Eio4 ping is sent by the server 31 | 32 | 33 | 34 | 35 | 36 | socket.io client class 37 | 38 | 39 | 40 | 41 | Create SocketIO object with default options 42 | 43 | 44 | 45 | 46 | 47 | Create SocketIO object with options 48 | 49 | 50 | 51 | 52 | 53 | Create SocketIO object with options 54 | 55 | 56 | 57 | 58 | 59 | 60 | Create SocketIO object with options 61 | 62 | 63 | 64 | 65 | 66 | 67 | An unique identifier for the socket session. Set after the connect event is triggered, and updated after the reconnect event. 68 | 69 | 70 | 71 | 72 | Whether or not the socket is connected to the server. 73 | 74 | 75 | 76 | 77 | Gets current attempt of reconnection. 78 | 79 | 80 | 81 | 82 | Whether or not the socket is disconnected from the server. 83 | 84 | 85 | 86 | 87 | Fired upon a successful reconnection. 88 | 89 | 90 | 91 | 92 | Fired upon an attempt to reconnect. 93 | 94 | 95 | 96 | 97 | Fired upon a reconnection attempt error. 98 | 99 | 100 | 101 | 102 | Fired when couldn’t reconnect within reconnectionAttempts 103 | 104 | 105 | 106 | 107 | Register a new handler for the given event. 108 | 109 | 110 | 111 | 112 | 113 | 114 | Unregister a new handler for the given event. 115 | 116 | 117 | 118 | 119 | 120 | Emits an event to the socket 121 | 122 | 123 | Any other parameters can be included. All serializable datastructures are supported, including byte[] 124 | 125 | 126 | 127 | 128 | Emits an event to the socket 129 | 130 | 131 | will be called with the server answer. 132 | Any other parameters can be included. All serializable datastructures are supported, including byte[] 133 | 134 | 135 | 136 | 137 | Whether to allow reconnection if accidentally disconnected 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/SocketIOClient/SocketIOClient.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b0b7dffd89bce724cacb0cb40b7a75e9 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/StandaloneSocketIO.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR || UNITY_STANDALONE 2 | using System; 3 | using System.Threading.Tasks; 4 | using System.Collections.Generic; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Linq; 7 | using Newtonsoft.Json.Serialization; 8 | using SocketIOClient; 9 | using SocketIOClient.Newtonsoft.Json; 10 | 11 | namespace Hackbox 12 | { 13 | internal class StandaloneSocketIO : ISocketIO 14 | { 15 | internal StandaloneSocketIO(string uri, int engineVersion, Dictionary queryParameters) 16 | { 17 | Socket = new SocketIO(uri, new SocketIOOptions() { EIO = engineVersion, Query = queryParameters }); 18 | 19 | NewtonsoftJsonSerializer serializer = new NewtonsoftJsonSerializer(); 20 | serializer.OptionsProvider = SerializerSettingsProvider; 21 | Socket.JsonSerializer = serializer; 22 | 23 | Socket.OnConnected += (sender, e) => OnConnected?.Invoke(); 24 | Socket.OnError += (sender, e) => OnError?.Invoke(e); 25 | Socket.OnDisconnected += (sender, e) => OnDisconnected?.Invoke(e); 26 | Socket.OnReconnectAttempt += (sender, e) => OnReconnectAttempt?.Invoke(e); 27 | Socket.OnReconnected += (sender, e) => OnReconnected?.Invoke(e); 28 | Socket.OnReconnectFailed += (sender, e) => OnReconnectFailed?.Invoke(); 29 | Socket.OnPing += (sender, e) => OnPing?.Invoke(); 30 | Socket.OnPong += (sender, e) => OnPong?.Invoke(e); 31 | } 32 | 33 | private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() 34 | { 35 | Formatting = Formatting.None, 36 | ContractResolver = new DefaultContractResolver() 37 | { 38 | NamingStrategy = new CamelCaseNamingStrategy() 39 | } 40 | }; 41 | 42 | private readonly SocketIO Socket; 43 | 44 | public event Action OnConnected; 45 | public event Action OnError; 46 | public event Action OnDisconnected; 47 | public event Action OnReconnectAttempt; 48 | public event Action OnReconnected; 49 | public event Action OnReconnectFailed; 50 | public event Action OnPing; 51 | public event Action OnPong; 52 | 53 | public bool Connected => Socket.Connected; 54 | public bool Disconnected => Socket.Disconnected; 55 | 56 | public async Task Connect() 57 | { 58 | await Socket.ConnectAsync(); 59 | } 60 | 61 | public async Task Disconnect() 62 | { 63 | await Socket.DisconnectAsync(); 64 | } 65 | 66 | public async Task Emit(string eventName, JObject message) 67 | { 68 | await Socket.EmitAsync(eventName, message); 69 | } 70 | 71 | public void On(string eventName, Action messageHandler) 72 | { 73 | Socket.On(eventName, x => 74 | { 75 | messageHandler?.Invoke(x.GetValue()); 76 | }); 77 | } 78 | 79 | public void Off(string eventName) 80 | { 81 | Socket.Off(eventName); 82 | } 83 | 84 | private static JsonSerializerSettings SerializerSettingsProvider() 85 | { 86 | return SerializerSettings; 87 | } 88 | } 89 | } 90 | #endif 91 | -------------------------------------------------------------------------------- /Runtime/Sockets/Standalone/StandaloneSocketIO.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15eea67bce295984da45feeb85acbba4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Sockets/WebGL.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b80c0e10af0ef74595fa425e7017fa3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Sockets/WebGL/WebGLSocketIO.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_WEBGL && !UNITY_EDITOR 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json.Linq; 7 | using AOT; 8 | 9 | namespace Hackbox 10 | { 11 | internal class WebGLSocketIO : ISocketIO 12 | { 13 | private static readonly Dictionary> MessageHandlers = new Dictionary>(); 14 | private static readonly List WebSockets = new List(); 15 | 16 | internal WebGLSocketIO(string uri, int engineVersion, Dictionary queryParameters) 17 | { 18 | WebSockets.Add(this); 19 | JObject queryObject = new JObject(); 20 | foreach (KeyValuePair queryParameter in queryParameters) 21 | { 22 | queryObject[queryParameter.Key] = queryParameter.Value; 23 | } 24 | 25 | WebSocketInit(uri, 26 | engineVersion, 27 | queryObject.ToString(), 28 | DelegateOnConnect, 29 | DelegateOnError, 30 | DelegateOnDisconnect, 31 | DelegateOnReconnectAttempt, 32 | DelegateOnReconnect, 33 | DelegateOnReconnectFail, 34 | DelegateOnPing, 35 | DelegateOnPong); 36 | } 37 | 38 | ~WebGLSocketIO() 39 | { 40 | WebSockets.Remove(this); 41 | } 42 | 43 | public event Action OnConnected; 44 | public event Action OnError; 45 | public event Action OnDisconnected; 46 | public event Action OnReconnectAttempt; 47 | public event Action OnReconnected; 48 | public event Action OnReconnectFailed; 49 | public event Action OnPing; 50 | public event Action OnPong; 51 | 52 | public bool Connected => WebSocketConnected(); 53 | public bool Disconnected => WebSocketDisconnected(); 54 | 55 | public Task Connect() 56 | { 57 | WebSocketConnect(); 58 | return Task.CompletedTask; 59 | } 60 | 61 | public Task Disconnect() 62 | { 63 | WebSocketDisconnect(); 64 | return Task.CompletedTask; 65 | } 66 | 67 | public Task Emit(string eventName, JObject message) 68 | { 69 | WebSocketEmit(eventName, message.ToString()); 70 | return Task.CompletedTask; 71 | } 72 | 73 | public void On(string eventName, Action messageHandler) 74 | { 75 | int handleIndex = MessageHandlers.Count; 76 | MessageHandlers[handleIndex] = messageHandler; 77 | 78 | WebSocketOn(eventName, handleIndex, DelegateOnMessage); 79 | } 80 | 81 | public void Off(string eventName) 82 | { 83 | WebSocketOff(eventName); 84 | } 85 | 86 | [MonoPInvokeCallback(typeof(VoidCallback))] 87 | public static void DelegateOnConnect() 88 | { 89 | foreach (WebGLSocketIO webSocket in WebSockets) 90 | { 91 | webSocket.OnConnected?.Invoke(); 92 | } 93 | } 94 | 95 | [MonoPInvokeCallback(typeof(ErrorCallback))] 96 | public static void DelegateOnError(string error) 97 | { 98 | foreach (WebGLSocketIO webSocket in WebSockets) 99 | { 100 | webSocket.OnError?.Invoke(error); 101 | } 102 | } 103 | 104 | [MonoPInvokeCallback(typeof(ErrorCallback))] 105 | public static void DelegateOnDisconnect(string error) 106 | { 107 | foreach (WebGLSocketIO webSocket in WebSockets) 108 | { 109 | webSocket.OnDisconnected?.Invoke(error); 110 | } 111 | } 112 | 113 | [MonoPInvokeCallback(typeof(ReconnectCallback))] 114 | public static void DelegateOnReconnectAttempt(int attempt) 115 | { 116 | foreach (WebGLSocketIO webSocket in WebSockets) 117 | { 118 | webSocket.OnReconnectAttempt?.Invoke(attempt); 119 | } 120 | } 121 | 122 | [MonoPInvokeCallback(typeof(ReconnectCallback))] 123 | public static void DelegateOnReconnect(int attempt) 124 | { 125 | foreach (WebGLSocketIO webSocket in WebSockets) 126 | { 127 | webSocket.OnReconnected?.Invoke(attempt); 128 | } 129 | } 130 | 131 | [MonoPInvokeCallback(typeof(VoidCallback))] 132 | public static void DelegateOnReconnectFail() 133 | { 134 | foreach (WebGLSocketIO webSocket in WebSockets) 135 | { 136 | webSocket.OnReconnectFailed?.Invoke(); 137 | } 138 | } 139 | 140 | [MonoPInvokeCallback(typeof(VoidCallback))] 141 | public static void DelegateOnPing() 142 | { 143 | foreach (WebGLSocketIO webSocket in WebSockets) 144 | { 145 | webSocket.OnPing?.Invoke(); 146 | } 147 | } 148 | 149 | [MonoPInvokeCallback(typeof(VoidCallback))] 150 | public static void DelegateOnPong() 151 | { 152 | foreach (WebGLSocketIO webSocket in WebSockets) 153 | { 154 | webSocket.OnPong?.Invoke(TimeSpan.Zero); 155 | } 156 | } 157 | 158 | [MonoPInvokeCallback(typeof(MessageCallback))] 159 | public static void DelegateOnMessage(int handleIndex, string message) 160 | { 161 | if (MessageHandlers.TryGetValue(handleIndex, out Action messageHandler)) 162 | { 163 | messageHandler?.Invoke(JObject.Parse(message)); 164 | } 165 | } 166 | 167 | private delegate void VoidCallback(); 168 | private delegate void ErrorCallback(string error); 169 | private delegate void ReconnectCallback(int attempt); 170 | private delegate void MessageCallback(int handleIndex, string message); 171 | 172 | [DllImport("__Internal")] 173 | private static extern void WebSocketInit(string uri, int protocol, string query, VoidCallback onConnect, ErrorCallback onError, ErrorCallback onDisconnect, ReconnectCallback onReconnectAttempt, ReconnectCallback onReconnect, VoidCallback onReconnectFail, VoidCallback onPing, VoidCallback onPong); 174 | 175 | [DllImport("__Internal")] 176 | private static extern void WebSocketConnect(); 177 | 178 | [DllImport("__Internal")] 179 | private static extern void WebSocketDisconnect(); 180 | 181 | [DllImport("__Internal")] 182 | private static extern void WebSocketEmit(string eventName, string message); 183 | 184 | [DllImport("__Internal")] 185 | private static extern void WebSocketOn(string eventName, int handleIndex, MessageCallback callback); 186 | 187 | [DllImport("__Internal")] 188 | private static extern void WebSocketOff(string eventName); 189 | 190 | [DllImport("__Internal")] 191 | private static extern bool WebSocketConnected(); 192 | 193 | [DllImport("__Internal")] 194 | private static extern bool WebSocketDisconnected(); 195 | } 196 | } 197 | #endif 198 | -------------------------------------------------------------------------------- /Runtime/Sockets/WebGL/WebGLSocketIO.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56ba0615c27290a4a88ccc279959a3ea 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Sockets/WebGL/WebGLSocketIO.jslib: -------------------------------------------------------------------------------- 1 | var LibraryWebSocket = 2 | { 3 | $wss: 4 | { 5 | socket: null 6 | }, 7 | 8 | WebSocketInit: function(uri, protocol, query, onConnect, onError, onDisconnect, onReconnectAttempt, onReconnect, onReconnectFail, onPing, onPong) 9 | { 10 | var queryObject = JSON.parse(Pointer_stringify(query)); 11 | var socket = io(Pointer_stringify(uri), { query: queryObject }); 12 | socket.protocol = protocol; 13 | 14 | socket.on('connect', function() { Module.dynCall_v(onConnect); }); 15 | socket.on('disconnect', function(reason, details) 16 | { 17 | var bufferLength = lengthBytesUTF8(reason) + 1; 18 | var buffer = _malloc(bufferLength); 19 | stringToUTF8(reason, buffer, bufferLength); 20 | 21 | Module.dynCall_vi(onDisconnect, buffer); 22 | }); 23 | socket.on('connect_error', function(error) 24 | { 25 | var bufferLength = lengthBytesUTF8(error) + 1; 26 | var buffer = _malloc(bufferLength); 27 | stringToUTF8(error, buffer, bufferLength); 28 | 29 | Module.dynCall_vi(onError, buffer); 30 | }); 31 | 32 | socket.io.on('error', function(error) 33 | { 34 | var bufferLength = lengthBytesUTF8(error) + 1; 35 | var buffer = _malloc(bufferLength); 36 | stringToUTF8(error, buffer, bufferLength); 37 | 38 | Module.dynCall_vi(onError, buffer); 39 | }); 40 | 41 | socket.io.on('ping', function() { Module.dynCall_v(onPing); }); 42 | socket.io.on('pong', function() { Module.dynCall_v(onPong); }); 43 | 44 | socket.io.on('reconnect_attempt', function(attempt) { Module.dynCall_vi(onReconnectAttempt, attempt); }); 45 | socket.io.on('reconnect', function(attempt) { Module.dynCall_vi(onReconnect, attempt); }); 46 | socket.io.on('reconnect_error', function(error) { Module.dynCall_v(onReconnectFail); }); 47 | 48 | wss.socket = socket; 49 | }, 50 | 51 | WebSocketConnect: function() 52 | { 53 | wss.socket.connect(); 54 | }, 55 | 56 | WebSocketDisconnect: function() 57 | { 58 | wss.socket.disconnect(); 59 | }, 60 | 61 | WebSocketEmit: function(eventName, message) 62 | { 63 | wss.socket.emit(Pointer_stringify(eventName), JSON.parse(Pointer_stringify(message))); 64 | }, 65 | 66 | WebSocketOn: function(eventName, handleIndex, onMessage) 67 | { 68 | wss.socket.on(Pointer_stringify(eventName), function(data) 69 | { 70 | var dataString = JSON.stringify(data); 71 | var bufferSize = lengthBytesUTF8(dataString) + 1; 72 | var buffer = _malloc(bufferSize); 73 | stringToUTF8(dataString, buffer, bufferSize); 74 | Module.dynCall_vii(onMessage, handleIndex, buffer); 75 | }); 76 | }, 77 | 78 | WebSocketOff: function(eventName) 79 | { 80 | wss.socket.off(Pointer_stringify(eventName)); 81 | }, 82 | 83 | WebSocketConnected: function() 84 | { 85 | return wss.socket.connected; 86 | }, 87 | 88 | WebSocketDisconnected: function() 89 | { 90 | return wss.socket.disconnected; 91 | }, 92 | }; 93 | 94 | autoAddDeps(LibraryWebSocket, '$wss'); 95 | mergeInto(LibraryManager.library, LibraryWebSocket); 96 | -------------------------------------------------------------------------------- /Runtime/Sockets/WebGL/WebGLSocketIO.jslib.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 58b5d3bf78cfd9a42bb648a8287167eb 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | WebGL: WebGL 27 | second: 28 | enabled: 1 29 | settings: {} 30 | userData: 31 | assetBundleName: 32 | assetBundleVariant: 33 | -------------------------------------------------------------------------------- /Runtime/State.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | using Newtonsoft.Json.Linq; 7 | using Hackbox.UI; 8 | using Hackbox.Parameters; 9 | 10 | namespace Hackbox 11 | { 12 | [Serializable] 13 | public class State : IEnumerable 14 | { 15 | public State() 16 | { 17 | } 18 | 19 | public State(Theme theme) 20 | { 21 | Theme = theme; 22 | } 23 | 24 | public State(State from) 25 | { 26 | Theme = from.Theme; 27 | HeaderParameterList = new ParameterList(from.HeaderParameterList); 28 | MainParameterList = new ParameterList(from.MainParameterList); 29 | Components = new List(from.Components.Select(x => new UIComponent(x))); 30 | } 31 | 32 | public Theme Theme = null; 33 | 34 | [HeaderParameterList] 35 | public ParameterList HeaderParameterList = new ParameterList(); 36 | 37 | [MainParameterList] 38 | public ParameterList MainParameterList = new ParameterList(); 39 | 40 | public List Components = new List(); 41 | 42 | public UIComponent this[int componentIndex] 43 | { 44 | get => Components[componentIndex]; 45 | set => Components[componentIndex] = value; 46 | } 47 | 48 | public UIComponent this[string componentName] 49 | { 50 | get => Components.Find(x => x.Name.Equals(componentName)); 51 | set 52 | { 53 | int existingIndex = Components.FindIndex(x => x.Name.Equals(componentName)); 54 | value.Name = componentName; 55 | if (existingIndex >= 0) 56 | { 57 | Components[existingIndex] = value; 58 | } 59 | else 60 | { 61 | Components.Add(value); 62 | } 63 | } 64 | } 65 | 66 | public Parameter this[int componentIndex, string parameterName] 67 | { 68 | get => this[componentIndex][parameterName]; 69 | set => this[componentIndex].Add(parameterName, value); 70 | } 71 | 72 | public Parameter this[string componentName, string parameterName] 73 | { 74 | get => this[componentName][parameterName]; 75 | set => this[componentName].Add(parameterName, value); 76 | } 77 | 78 | public string HeaderText 79 | { 80 | get => GetHeaderParameterValue("text"); 81 | set => SetHeaderParameter("text", value); 82 | } 83 | 84 | public Color HeaderColor 85 | { 86 | get => GetHeaderParameterValue("color"); 87 | set => SetHeaderParameter("color", value); 88 | } 89 | 90 | public string HeaderBackground 91 | { 92 | get => GetHeaderParameterValue("background"); 93 | set => SetHeaderParameter("background", value); 94 | } 95 | 96 | public string MainAlignment 97 | { 98 | get => GetMainParameterValue("align"); 99 | set => SetMainParameter("align", value); 100 | } 101 | 102 | public string MainBackground 103 | { 104 | get => GetMainParameterValue("background"); 105 | set => SetMainParameter("background", value); 106 | } 107 | 108 | private JObject _obj = new JObject(); 109 | 110 | #region IEnumerable Interface & Collection Initialiser Implementation 111 | public IEnumerator GetEnumerator() 112 | { 113 | return Components.GetEnumerator(); 114 | } 115 | 116 | public void Add(UIComponent component) 117 | { 118 | Components.Add(component); 119 | } 120 | 121 | public void Add(string componentName, UIComponent component) 122 | { 123 | this[componentName] = component; 124 | } 125 | 126 | public bool Remove(UIComponent component) 127 | { 128 | return Components.Remove(component); 129 | } 130 | 131 | public bool Remove(string componentName) 132 | { 133 | return Components.Remove(this[componentName]); 134 | } 135 | 136 | public void RemoveAt(int componentIndex) 137 | { 138 | Components.RemoveAt(componentIndex); 139 | } 140 | #endregion 141 | 142 | #region Public Methods 143 | public static State Create(Theme theme) 144 | { 145 | return new State() { Theme = theme }; 146 | } 147 | 148 | public Parameter GetGenericHeaderParameter(string parameterName) 149 | { 150 | return HeaderParameterList.GetGenericParameter(parameterName); 151 | } 152 | 153 | public ParamT GetHeaderParameter(string parameterName) where ParamT : Parameter, new() 154 | { 155 | return HeaderParameterList.GetParameter(parameterName); 156 | } 157 | 158 | public ValueT GetHeaderParameterValue(string parameterName) 159 | { 160 | return GetGenericHeaderParameter(parameterName).Value; 161 | } 162 | 163 | public void SetHeaderParameter(string parameterName, ValueT value) 164 | { 165 | HeaderParameterList.SetParameterValue(parameterName, value); 166 | } 167 | 168 | public string GetHeaderText() 169 | { 170 | return HeaderText; 171 | } 172 | 173 | public void SetHeaderText(string text) 174 | { 175 | HeaderText = text; 176 | } 177 | 178 | public Parameter GetGenericMainParameter(string parameterName) 179 | { 180 | return MainParameterList.GetGenericParameter(parameterName); 181 | } 182 | 183 | public ParamT GetMainParameter(string parameterName) where ParamT : Parameter, new() 184 | { 185 | return MainParameterList.GetParameter(parameterName); 186 | } 187 | 188 | public ValueT GetMainParameterValue(string parameterName) 189 | { 190 | return GetGenericMainParameter(parameterName).Value; 191 | } 192 | 193 | public void SetMainParameter(string parameterName, ValueT value) 194 | { 195 | MainParameterList.SetParameterValue(parameterName, value); 196 | } 197 | 198 | public UIComponent GetComponent(int componentIndex) 199 | { 200 | return this[componentIndex]; 201 | } 202 | 203 | public UIComponent GetComponent(string componentName) 204 | { 205 | return this[componentName]; 206 | } 207 | 208 | public bool TryGetComponent(string componentName, out UIComponent component) 209 | { 210 | component = Components.Find(x => x.Name.Equals(componentName)); 211 | return component != null; 212 | } 213 | 214 | public Parameter GetComponentGenericParameter(int componentIndex, string parameterName) 215 | { 216 | return this[componentIndex].GetGenericParameter(parameterName); 217 | } 218 | 219 | public Parameter GetComponentGenericParameter(string componentName, string parameterName) 220 | { 221 | return this[componentName].GetGenericParameter(parameterName); 222 | } 223 | 224 | public ParamT GetComponentParameter(int componentIndex, string parameterName) where ParamT: Parameter, new() 225 | { 226 | return this[componentIndex].GetParameter(parameterName); 227 | } 228 | 229 | public ParamT GetComponentParameter(string componentName, string parameterName) where ParamT : Parameter, new() 230 | { 231 | return this[componentName].GetParameter(parameterName); 232 | } 233 | 234 | public ValueT GetComponentParameterValue(int componentIndex, string parameterName) 235 | { 236 | return this[componentIndex].GetParameterValue(parameterName); 237 | } 238 | 239 | public ValueT GetComponentParameterValue(string componentName, string parameterName) 240 | { 241 | return this[componentName].GetParameterValue(parameterName); 242 | } 243 | 244 | public void SetComponentParameterValue(int componentIndex, string parameterName, ValueT value) 245 | { 246 | this[componentIndex].SetParameterValue(parameterName, value); 247 | } 248 | 249 | public void SetComponentParameterValue(string componentName, string parameterName, ValueT value) 250 | { 251 | this[componentName].SetParameterValue(parameterName, value); 252 | } 253 | 254 | public Parameter GetComponentGenericStyleParameter(int componentIndex, string parameterName) 255 | { 256 | return this[componentIndex].GetGenericStyleParameter(parameterName); 257 | } 258 | 259 | public Parameter GetComponentGenericStyleParameter(string componentName, string parameterName) 260 | { 261 | return this[componentName].GetGenericStyleParameter(parameterName); 262 | } 263 | 264 | public ParamT GetComponentStyleParameter(int componentIndex, string parameterName) where ParamT : Parameter, new() 265 | { 266 | return this[componentIndex].GetStyleParameter(parameterName); 267 | } 268 | 269 | public ParamT GetComponentStyleParameter(string componentName, string parameterName) where ParamT : Parameter, new() 270 | { 271 | return this[componentName].GetStyleParameter(parameterName); 272 | } 273 | 274 | public ValueT GetComponentStyleParameterValue(int componentIndex, string parameterName) 275 | { 276 | return this[componentIndex].GetStyleParameterValue(parameterName); 277 | } 278 | 279 | public ValueT GetComponentStyleParameterValue(string componentName, string parameterName) 280 | { 281 | return this[componentName].GetStyleParameterValue(parameterName); 282 | } 283 | 284 | public void SetComponentStyleParameterValue(int componentIndex, string parameterName, ValueT value) 285 | { 286 | this[componentIndex].SetStyleParameterValue(parameterName, value); 287 | } 288 | 289 | public void SetComponentStyleParameterValue(string componentName, string parameterName, ValueT value) 290 | { 291 | this[componentName].SetStyleParameterValue(parameterName, value); 292 | } 293 | 294 | public string GetComponentText(int componentIndex) 295 | { 296 | return GetComponentParameterValue(componentIndex, "text"); 297 | } 298 | 299 | public string GetComponentText(string componentName) 300 | { 301 | return GetComponentParameterValue(componentName, "text"); 302 | } 303 | 304 | public void SetComponentText(int componentIndex, string text) 305 | { 306 | SetComponentParameterValue(componentIndex, "text", text); 307 | } 308 | 309 | public void SetComponentText(string componentName, string text) 310 | { 311 | SetComponentParameterValue(componentName, "text", text); 312 | } 313 | 314 | public string GetComponentLabel(int componentIndex) 315 | { 316 | return GetComponentParameterValue(componentIndex, "label"); 317 | } 318 | 319 | public string GetComponentLabel(string componentName) 320 | { 321 | return GetComponentParameterValue(componentName, "label"); 322 | } 323 | 324 | public void SetComponentLabel(int componentIndex, string label) 325 | { 326 | SetComponentParameterValue(componentIndex, "label", label); 327 | } 328 | 329 | public void SetComponentLabel(string componentName, string label) 330 | { 331 | SetComponentParameterValue(componentName, "label", label); 332 | } 333 | 334 | public string GetComponentValue(int componentIndex) 335 | { 336 | return GetComponentParameterValue(componentIndex, "value"); 337 | } 338 | 339 | public string GetComponentValue(string componentName) 340 | { 341 | return GetComponentParameterValue(componentName, "value"); 342 | } 343 | 344 | public void SetComponentValue(int componentIndex, string value) 345 | { 346 | SetComponentParameterValue(componentIndex, "value", value); 347 | } 348 | 349 | public void SetComponentValue(string componentName, string value) 350 | { 351 | SetComponentParameterValue(componentName, "value", value); 352 | } 353 | 354 | public JObject GenerateJSON(int version) 355 | { 356 | if (Theme == null) 357 | { 358 | return _obj; 359 | } 360 | 361 | _obj = new JObject(); 362 | _obj["version"] = version; 363 | _obj["theme"] = Theme.GenerateJSON(version); 364 | _obj["presets"] = GeneratePresets(version); 365 | 366 | JObject ui = new JObject(); 367 | _obj["ui"] = ui; 368 | 369 | JObject headerObj = new JObject(); 370 | _obj["ui"]["header"] = headerObj; 371 | 372 | JObject mainObj = new JObject(); 373 | mainObj["components"] = new JArray(Components.Select(x => x.GenerateJSON(version))); 374 | _obj["ui"]["main"] = mainObj; 375 | 376 | foreach (Parameter parameter in HeaderParameterList.Parameters) 377 | { 378 | parameter.ApplyValueToJObject(headerObj, version); 379 | } 380 | 381 | foreach (Parameter parameter in MainParameterList.Parameters) 382 | { 383 | parameter.ApplyValueToJObject(mainObj, version); 384 | } 385 | 386 | return _obj; 387 | } 388 | #endregion 389 | 390 | #region Private Methods 391 | private JObject GeneratePresets(int version) 392 | { 393 | JObject presets = new JObject(); 394 | foreach (Preset preset in Components.Select(x => x.Preset).Distinct()) 395 | { 396 | presets[preset.name] = preset.GenerateJSON(version); 397 | } 398 | 399 | return presets; 400 | } 401 | #endregion 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /Runtime/State.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79bf5fa3b0d27b04b92ad11a3ed4c7d3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/StateAsset.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Hackbox.UI; 5 | using Hackbox.Parameters; 6 | 7 | namespace Hackbox 8 | { 9 | [CreateAssetMenu(menuName = "Hackbox/State Asset")] 10 | public class StateAsset : ScriptableObject 11 | { 12 | public State State = null; 13 | 14 | private void OnValidate() 15 | { 16 | HashSet parameters = new HashSet(); 17 | 18 | foreach (UIComponent component in State.Components) 19 | { 20 | foreach (Parameter parameter in component.ParameterList.Parameters) 21 | { 22 | if (parameters.Any(x => Object.ReferenceEquals(x, parameter))) 23 | { 24 | component.ParameterList = new ParameterList(component.ParameterList); 25 | } 26 | parameters.Add(parameter); 27 | } 28 | } 29 | } 30 | 31 | //Can just pass a StateAsset object in as an argument for a State by allowing implicit conversion 32 | public static implicit operator State(StateAsset stateAsset) => stateAsset.State; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Runtime/StateAsset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82984bcd6169ff144b5387bf970b6f80 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce681d36ff6484c4abbef01ca78d57c7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/UI/IUIElement.cs: -------------------------------------------------------------------------------- 1 | using Hackbox.Parameters; 2 | using Newtonsoft.Json.Linq; 3 | 4 | namespace Hackbox.UI 5 | { 6 | public interface IUIElement : IParameterList, IStyleParameterList 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Runtime/UI/IUIElement.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1043209a138f5f4d97a5a6f5918669f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UI/Preset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using UnityEngine; 3 | using Newtonsoft.Json.Linq; 4 | using Hackbox.Parameters; 5 | 6 | namespace Hackbox.UI 7 | { 8 | [CreateAssetMenu(menuName = "Hackbox/Preset")] 9 | public class Preset : ScriptableObject, IUIElement 10 | { 11 | public enum PresetType 12 | { 13 | Text, 14 | TextInput, 15 | Buzzer, 16 | Button, 17 | Choices, 18 | Range, 19 | Sort 20 | } 21 | 22 | public PresetType Type = PresetType.Text; 23 | 24 | [StyleParameterList] 25 | public ParameterList StyleParameterList = new ParameterList(); 26 | [NormalParameterList] 27 | public ParameterList ParameterList = new ParameterList(); 28 | 29 | public Parameter this[string parameterName] 30 | { 31 | get => ParameterList[parameterName] ?? StyleParameterList[parameterName]; 32 | set 33 | { 34 | Add(parameterName, value); 35 | } 36 | } 37 | 38 | private JObject _obj = new JObject(); 39 | 40 | private void OnValidate() 41 | { 42 | //This is somewhat temporary to get style-based parameters into a specific parameter collection 43 | for (int parameterIndex = 0; parameterIndex < ParameterList.Parameters.Count; ++parameterIndex) 44 | { 45 | Parameter parameter = ParameterList[parameterIndex]; 46 | if (!DefaultParameters.GetDefaultParameters(this).ContainsKey(parameter.Name) && 47 | DefaultParameters.GetDefaultStyleParameters(this).ContainsKey(parameter.Name)) 48 | { 49 | StyleParameterList.Parameters.Add(parameter); 50 | ParameterList.Parameters.Remove(parameter); 51 | parameterIndex--; 52 | } 53 | } 54 | } 55 | 56 | #region IEnumerable Interface & Collection Initialiser Implementation 57 | public IEnumerator GetEnumerator() 58 | { 59 | yield return StyleParameterList.GetEnumerator(); 60 | yield return ParameterList.GetEnumerator(); 61 | } 62 | 63 | public void Add(string parameterName, T value) 64 | { 65 | if (DefaultParameters.GetDefaultStyleParameters(this, null).ContainsKey(parameterName)) 66 | { 67 | StyleParameterList.Add(parameterName, value); 68 | } 69 | else 70 | { 71 | ParameterList.Add(parameterName, value); 72 | } 73 | } 74 | #endregion 75 | 76 | #region Equatable Implementation 77 | public override int GetHashCode() 78 | { 79 | return GetInstanceID(); 80 | } 81 | 82 | public override bool Equals(object other) 83 | { 84 | if (other is Preset otherPreset) 85 | { 86 | return GetInstanceID() == otherPreset.GetInstanceID(); 87 | } 88 | 89 | return base.Equals(other); 90 | } 91 | #endregion 92 | 93 | #region Public Methods 94 | public static Preset Create(string name, PresetType type) 95 | { 96 | Preset preset = ScriptableObject.CreateInstance(); 97 | preset.name = name; 98 | preset.Type = type; 99 | return preset; 100 | } 101 | 102 | public Parameter GetGenericParameter(string parameterName) 103 | { 104 | return ParameterList.GetGenericParameter(parameterName); 105 | } 106 | 107 | public ParamT GetParameter(string parameterName) where ParamT : Parameter, new() 108 | { 109 | return ParameterList.GetParameter(parameterName); 110 | } 111 | 112 | public ValueT GetParameterValue(string parameterName) 113 | { 114 | return GetGenericParameter(parameterName).Value; 115 | } 116 | 117 | public void SetParameterValue(string parameterName, ValueT value) 118 | { 119 | ParameterList.SetParameterValue(parameterName, value); 120 | } 121 | 122 | public Parameter GetGenericStyleParameter(string parameterName) 123 | { 124 | return StyleParameterList.GetGenericParameter(parameterName); 125 | } 126 | 127 | public ParamT GetStyleParameter(string parameterName) where ParamT : Parameter, new() 128 | { 129 | return StyleParameterList.GetParameter(parameterName); 130 | } 131 | 132 | public ValueT GetStyleParameterValue(string parameterName) 133 | { 134 | return GetGenericStyleParameter(parameterName).Value; 135 | } 136 | 137 | public void SetStyleParameterValue(string parameterName, ValueT value) 138 | { 139 | StyleParameterList.SetParameterValue(parameterName, value); 140 | } 141 | #endregion 142 | 143 | #region Internal Methods 144 | internal JObject GenerateJSON(int version) 145 | { 146 | _obj["type"] = Type.ToString(); 147 | _obj["props"] = GenerateProps(version); 148 | 149 | return _obj; 150 | } 151 | 152 | internal JObject GenerateProps(int version) 153 | { 154 | JObject props = new JObject(); 155 | 156 | switch (version) 157 | { 158 | case 1: 159 | foreach (Parameter parameter in StyleParameterList.Parameters) 160 | { 161 | parameter.ApplyValueToJObject(props, version); 162 | } 163 | break; 164 | 165 | default: 166 | JObject styleProps = new JObject(); 167 | props["style"] = styleProps; 168 | 169 | foreach (Parameter parameter in StyleParameterList.Parameters) 170 | { 171 | parameter.ApplyValueToJObject(styleProps, version); 172 | } 173 | break; 174 | } 175 | 176 | foreach (Parameter parameter in ParameterList.Parameters) 177 | { 178 | parameter.ApplyValueToJObject(props, version); 179 | } 180 | 181 | return props; 182 | } 183 | #endregion 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Runtime/UI/Preset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a43553a911877b049ab371a3fae2637f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UI/Theme.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Newtonsoft.Json.Linq; 3 | using UnityEngine; 4 | 5 | namespace Hackbox.UI 6 | { 7 | [CreateAssetMenu(menuName = "Hackbox/Theme")] 8 | public class Theme : ScriptableObject 9 | { 10 | [Header("Header")] 11 | [Tooltip("Color of the text of the header section.")] 12 | public Color HeaderColor = Color.black; 13 | [BackgroundString] 14 | [Tooltip("The background of the header section.")] 15 | public string HeaderBackground = "#ffffff"; 16 | [Tooltip("The minimum height of the header section.")] 17 | public string HeaderMinHeight = "50px"; 18 | [Tooltip("The maximum height of the header section.")] 19 | public string HeaderMaxHeight = "50px"; 20 | [Tooltip("The header section font family.")] 21 | public string HeaderFontFamily = ""; 22 | 23 | [Header("Main")] 24 | [Tooltip("Color of the text of the main section.")] 25 | public Color MainColor = Color.white; 26 | [BackgroundString] 27 | [Tooltip("The background of the main section.")] 28 | public string MainBackground = "#0000ff"; 29 | [Tooltip("The minimum width of the main section.")] 30 | public string MainMinWidth = "300px"; 31 | [Tooltip("The maximum width of the main section.")] 32 | public string MainMaxWidth = "350px"; 33 | 34 | [Header("Fonts")] 35 | public List Fonts = new List(); 36 | 37 | public Color? HeaderBackgroundColor 38 | { 39 | get 40 | { 41 | if (ColorUtility.TryParseHtmlString(HeaderBackground, out Color color)) 42 | { 43 | return color; 44 | } 45 | return null; 46 | } 47 | set => HeaderBackground = value?.ToHTMLStringWithAlpha(); 48 | } 49 | 50 | public Color? MainBackgroundColor 51 | { 52 | get 53 | { 54 | if (ColorUtility.TryParseHtmlString(MainBackground, out Color color)) 55 | { 56 | return color; 57 | } 58 | return null; 59 | } 60 | set => MainBackground = value?.ToHTMLStringWithAlpha(); 61 | } 62 | 63 | private JObject _obj = new JObject(); 64 | 65 | #region Public Methods 66 | public static Theme Create(string name) 67 | { 68 | Theme theme = ScriptableObject.CreateInstance(); 69 | theme.name = name; 70 | return theme; 71 | } 72 | #endregion 73 | 74 | #region Internal Methods 75 | internal JObject GenerateJSON(int version) 76 | { 77 | JObject header = new JObject(); 78 | header["color"] = HeaderColor.ToHTMLString(); 79 | header["background"] = HeaderBackground; 80 | header["minHeight"] = HeaderMinHeight; 81 | header["maxHeight"] = HeaderMaxHeight; 82 | if (!string.IsNullOrEmpty(HeaderFontFamily)) 83 | { 84 | header["fontFamily"] = HeaderFontFamily; 85 | } 86 | _obj["header"] = header; 87 | 88 | JObject main = new JObject(); 89 | main["color"] = MainColor.ToHTMLString(); 90 | main["background"] = MainBackground; 91 | main["minWidth"] = MainMinWidth; 92 | main["maxWidth"] = MainMaxWidth; 93 | _obj["main"] = main; 94 | 95 | if (Fonts != null && Fonts.Count > 0) 96 | { 97 | JArray fonts = new JArray(); 98 | foreach (string font in Fonts) 99 | { 100 | JObject fontObject = new JObject(); 101 | fontObject["family"] = font; 102 | fonts.Add(fontObject); 103 | } 104 | _obj["fonts"] = fonts; 105 | } 106 | 107 | return _obj; 108 | } 109 | #endregion 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Runtime/UI/Theme.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 92925c059f7816149b0a3ca61040876a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UI/UIComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using Newtonsoft.Json.Linq; 4 | using Hackbox.Parameters; 5 | using UnityEngine; 6 | 7 | namespace Hackbox.UI 8 | { 9 | [Serializable] 10 | public class UIComponent: IUIElement 11 | { 12 | public UIComponent() 13 | { 14 | } 15 | 16 | public UIComponent(Preset preset) 17 | { 18 | Preset = preset; 19 | } 20 | 21 | public UIComponent(string name, Preset preset) 22 | { 23 | Name = name; 24 | Preset = preset; 25 | } 26 | 27 | public UIComponent(UIComponent from) 28 | { 29 | Name = from.Name; 30 | Key = from.Key; 31 | Preset = from.Preset; 32 | StyleParameterList = new ParameterList(from.StyleParameterList); 33 | ParameterList = new ParameterList(from.ParameterList); 34 | } 35 | 36 | [Tooltip("Name of the component. Only used in Unity.")] 37 | public string Name = ""; 38 | [Tooltip("Key of the component. Use this to persist the state of a component between state changes.")] 39 | public string Key = ""; 40 | [Tooltip("The preset this component is based on.")] 41 | public Preset Preset = null; 42 | 43 | [StyleParameterList] 44 | public ParameterList StyleParameterList = new ParameterList(); 45 | 46 | [NormalParameterList] 47 | public ParameterList ParameterList = new ParameterList(); 48 | 49 | public Parameter this[string parameterName] 50 | { 51 | get => ParameterList[parameterName] ?? StyleParameterList[parameterName]; 52 | set 53 | { 54 | Add(parameterName, value); 55 | } 56 | } 57 | 58 | private JObject _obj = new JObject(); 59 | 60 | private void OnValidate() 61 | { 62 | //This is somewhat temporary to get style-based parameters into a specific parameter collection 63 | for (int parameterIndex = 0; parameterIndex < ParameterList.Parameters.Count; ++parameterIndex) 64 | { 65 | Parameter parameter = ParameterList[parameterIndex]; 66 | 67 | if (!DefaultParameters.GetDefaultParameters(this).ContainsKey(parameter.Name) && 68 | DefaultParameters.GetDefaultStyleParameters(this).ContainsKey(parameter.Name)) 69 | { 70 | StyleParameterList.Parameters.Add(parameter); 71 | ParameterList.Parameters.Remove(parameter); 72 | parameterIndex--; 73 | } 74 | } 75 | } 76 | 77 | #region IEnumerable Interface & Collection Initialiser Implementation 78 | public IEnumerator GetEnumerator() 79 | { 80 | yield return StyleParameterList.GetEnumerator(); 81 | yield return ParameterList.GetEnumerator(); 82 | } 83 | 84 | public void Add(Parameter parameter) 85 | { 86 | Add(parameter.Name, parameter); 87 | } 88 | 89 | public void Add(string parameterName, T value) 90 | { 91 | if (DefaultParameters.GetDefaultStyleParameters(this, null).ContainsKey(parameterName)) 92 | { 93 | StyleParameterList.Add(parameterName, value); 94 | } 95 | else 96 | { 97 | ParameterList.Add(parameterName, value); 98 | } 99 | } 100 | #endregion 101 | 102 | #region Public Methods 103 | public static UIComponent Create(string name, Preset preset, string key) 104 | { 105 | return new UIComponent() 106 | { 107 | Name = name, 108 | Preset = preset, 109 | Key = key 110 | }; 111 | } 112 | 113 | public static UIComponent Create(string name, Preset preset) 114 | { 115 | return new UIComponent() 116 | { 117 | Name = name, 118 | Preset = preset 119 | }; 120 | } 121 | 122 | public static UIComponent Create(Preset preset, string key) 123 | { 124 | return new UIComponent() 125 | { 126 | Preset = preset, 127 | Key = key 128 | }; 129 | } 130 | 131 | public static UIComponent Create(Preset preset) 132 | { 133 | return new UIComponent() 134 | { 135 | Preset = preset 136 | }; 137 | } 138 | 139 | public Parameter GetGenericParameter(string parameterName) 140 | { 141 | return ParameterList.GetGenericParameter(parameterName); 142 | } 143 | 144 | public ParamT GetParameter(string parameterName) where ParamT : Parameter, new() 145 | { 146 | return ParameterList.GetParameter(parameterName); 147 | } 148 | 149 | public ValueT GetParameterValue(string parameterName) 150 | { 151 | return GetGenericParameter(parameterName).Value; 152 | } 153 | 154 | public void SetParameterValue(string parameterName, ValueT value) 155 | { 156 | ParameterList.SetParameterValue(parameterName, value); 157 | } 158 | 159 | public Parameter GetGenericStyleParameter(string parameterName) 160 | { 161 | return StyleParameterList.GetGenericParameter(parameterName); 162 | } 163 | 164 | public ParamT GetStyleParameter(string parameterName) where ParamT : Parameter, new() 165 | { 166 | return StyleParameterList.GetParameter(parameterName); 167 | } 168 | 169 | public ValueT GetStyleParameterValue(string parameterName) 170 | { 171 | return GetGenericStyleParameter(parameterName).Value; 172 | } 173 | 174 | public void SetStyleParameterValue(string parameterName, ValueT value) 175 | { 176 | StyleParameterList.SetParameterValue(parameterName, value); 177 | } 178 | #endregion 179 | 180 | #region Internal Methods 181 | internal JObject GenerateJSON(int version) 182 | { 183 | _obj["type"] = Preset.name; 184 | 185 | if (!string.IsNullOrEmpty(Key)) 186 | { 187 | _obj["key"] = Key; 188 | } 189 | 190 | _obj["props"] = GenerateProps(version); 191 | 192 | return _obj; 193 | } 194 | 195 | internal JObject GenerateProps(int version) 196 | { 197 | //There's some strange lingering issue with the slicing of style properties, so let's do it here to make sure all is styled correctly 198 | JObject props = Preset?.GenerateProps(version) ?? new JObject(); 199 | 200 | foreach (Parameter parameter in ParameterList.Parameters) 201 | { 202 | parameter.ApplyValueToJObject(props, version); 203 | } 204 | 205 | switch (version) 206 | { 207 | case 1: 208 | foreach (Parameter parameter in StyleParameterList.Parameters) 209 | { 210 | parameter.ApplyValueToJObject(props, version); 211 | } 212 | break; 213 | 214 | default: 215 | JObject style = null; 216 | if (props.TryGetValue("style", out JToken styleToken)) 217 | { 218 | style = styleToken as JObject; 219 | } 220 | if (style == null) 221 | { 222 | style = new JObject(); 223 | props["style"] = style; 224 | } 225 | 226 | foreach (Parameter parameter in StyleParameterList.Parameters) 227 | { 228 | parameter.ApplyValueToJObject(style, version); 229 | } 230 | break; 231 | } 232 | 233 | return props; 234 | } 235 | #endregion 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /Runtime/UI/UIComponent.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e7136d04037cde49b6b85e291a70b01 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/com.atb.hackbox.Runtime.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hackbox", 3 | "references": [], 4 | "includePlatforms": [], 5 | "excludePlatforms": [], 6 | "allowUnsafeCode": false, 7 | "overrideReferences": true, 8 | "precompiledReferences": [ 9 | "SocketIOClient.dll", 10 | "SocketIOClient.Newtonsoft.Json.dll", 11 | "Newtonsoft.Json.dll" 12 | ], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /Runtime/com.atb.hackbox.Runtime.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6fe8d6e668b30ef43af6d49072f7c997 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.atb.hackbox", 3 | "version": "0.12.0", 4 | "displayName": "Hackbox.ca", 5 | "description": "This integrates the online signalling system Hackbox.ca into Unity.", 6 | "unity": "2019.3", 7 | "documentationUrl": "https://github.com/ashbash1987/hackbox-unity/blob/master/README.md", 8 | "changelogUrl": "https://github.com/ashbash1987/hackbox-unity/blob/master/CHANGELOG.md", 9 | "licensesUrl": "https://github.com/ashbash1987/hackbox-unity/blob/master/LICENSE", 10 | "dependencies": { 11 | "com.unity.nuget.newtonsoft-json": "1.1.2" 12 | }, 13 | "keywords": [ 14 | 15 | ], 16 | "author": { 17 | "name": "Ash The Bash / DevDev", 18 | "email": "ashley@atbweb.co.uk", 19 | "url": "https://hackbox.ca" 20 | }, 21 | "type": "library" 22 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 33d2fbf20ea9658408bdf55d410fd055 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------