diff --git a/Editor/Inspector/DisabledParentObjectHelpBox.cs b/Editor/Inspector/DisabledParentObjectHelpBox.cs new file mode 100644 index 0000000..ae7a146 --- /dev/null +++ b/Editor/Inspector/DisabledParentObjectHelpBox.cs @@ -0,0 +1,58 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace VisualPinball.Engine.Mpf.Unity.Editor +{ + public class DisabledParentObjectHelpBox : VisualElement + { + private readonly HelpBox _box; + private readonly UnityEditor.Editor _editor; + + public DisabledParentObjectHelpBox(UnityEditor.Editor editor) + { + _editor = editor; + _box = new HelpBox( + "The game object this component is attached to or one of its parents is disabled. This component" + + " cannot initialize until its parent object becomes active in the hierarchy. It is possible that" + + " events from MPF will be missed.", + HelpBoxMessageType.Warning); + Add(_box); + + RegisterCallback(evt => + { + UpdateHelpBoxVisibility(); + EditorApplication.hierarchyChanged += OnHierarchyChanged; + }); + + RegisterCallback(evt => + { + EditorApplication.hierarchyChanged -= OnHierarchyChanged; + }); + } + + private void OnHierarchyChanged() => UpdateHelpBoxVisibility(); + + private void UpdateHelpBoxVisibility() + { + _box.style.display = _editor.targets.ToList().Any(IsParentObjectDisabled) + ? DisplayStyle.Flex + : DisplayStyle.None; + } + + private static bool IsParentObjectDisabled(UnityEngine.Object target) => + !((Component)target).gameObject.activeInHierarchy; + } +} \ No newline at end of file diff --git a/Editor/Inspector/DisabledParentObjectHelpBox.cs.meta b/Editor/Inspector/DisabledParentObjectHelpBox.cs.meta new file mode 100644 index 0000000..42fbf45 --- /dev/null +++ b/Editor/Inspector/DisabledParentObjectHelpBox.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 74388a516b6a42e084e29df58803e140 +timeCreated: 1743342338 \ No newline at end of file diff --git a/Editor/Inspector/EnableDuringModeInspector.cs b/Editor/Inspector/EnableDuringModeInspector.cs new file mode 100644 index 0000000..92759a9 --- /dev/null +++ b/Editor/Inspector/EnableDuringModeInspector.cs @@ -0,0 +1,31 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; +using VisualPinball.Engine.Mpf.Unity.MediaController.ObjectToggle; + +namespace VisualPinball.Engine.Mpf.Unity.Editor +{ + [CustomEditor(typeof(EnableDuringMode)), CanEditMultipleObjects] + public class EnableDuringModeInspector : UnityEditor.Editor + { + public override VisualElement CreateInspectorGUI() + { + var root = new VisualElement(); + root.Add(new MissingGleHelpBoxes(this)); + root.Add(new DisabledParentObjectHelpBox(this)); + InspectorElement.FillDefaultInspector(root, serializedObject, this); + return root; + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/EnableDuringModeInspector.cs.meta b/Editor/Inspector/EnableDuringModeInspector.cs.meta new file mode 100644 index 0000000..3357b14 --- /dev/null +++ b/Editor/Inspector/EnableDuringModeInspector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a743eb1ed47b425e8ad847e7b7de1bac +timeCreated: 1743339156 \ No newline at end of file diff --git a/Editor/Inspector/MpfEventSoundInspector.cs b/Editor/Inspector/EventSoundInspector.cs similarity index 89% rename from Editor/Inspector/MpfEventSoundInspector.cs rename to Editor/Inspector/EventSoundInspector.cs index 977a8c8..a8bdc2d 100644 --- a/Editor/Inspector/MpfEventSoundInspector.cs +++ b/Editor/Inspector/EventSoundInspector.cs @@ -17,8 +17,8 @@ namespace VisualPinball.Engine.Mpf.Unity.Editor { - [CustomEditor(typeof(MpfEventSound)), CanEditMultipleObjects] - public class MpfEventSoundInspector : SoundComponentInspector + [CustomEditor(typeof(EventSound)), CanEditMultipleObjects] + public class EventSoundInspector : SoundComponentInspector { [SerializeField] private VisualTreeAsset mpfEventSoundInspectorXml; diff --git a/Editor/Inspector/MpfEventSoundInspector.cs.meta b/Editor/Inspector/EventSoundInspector.cs.meta similarity index 100% rename from Editor/Inspector/MpfEventSoundInspector.cs.meta rename to Editor/Inspector/EventSoundInspector.cs.meta diff --git a/Editor/Inspector/MpfEventSoundInspector.uxml b/Editor/Inspector/EventSoundInspector.uxml similarity index 100% rename from Editor/Inspector/MpfEventSoundInspector.uxml rename to Editor/Inspector/EventSoundInspector.uxml diff --git a/Editor/Inspector/MpfEventSoundInspector.uxml.meta b/Editor/Inspector/EventSoundInspector.uxml.meta similarity index 100% rename from Editor/Inspector/MpfEventSoundInspector.uxml.meta rename to Editor/Inspector/EventSoundInspector.uxml.meta diff --git a/Editor/Inspector/MissingGleHelpBoxes.cs b/Editor/Inspector/MissingGleHelpBoxes.cs new file mode 100644 index 0000000..54aeae6 --- /dev/null +++ b/Editor/Inspector/MissingGleHelpBoxes.cs @@ -0,0 +1,71 @@ +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace VisualPinball.Engine.Mpf.Unity.Editor +{ + public class MissingGleHelpBoxes : VisualElement + { + private readonly HelpBox _missingGleHelpBox; + private readonly HelpBox _misconfiguredGleHelpBox; + private readonly UnityEditor.Editor _editor; + + public MissingGleHelpBoxes(UnityEditor.Editor editor) + { + _editor = editor; + _missingGleHelpBox = new HelpBox( + "This component must be on a game object that is underneath an " + + "'MPF Game Logic' component in the scene hierarchy.", + HelpBoxMessageType.Error + ); + Add(_missingGleHelpBox); + + _misconfiguredGleHelpBox = new HelpBox( + "The MPF game logic engine is not configured to use the included media " + + $"controller. Set 'Media Controller' to '{MpfMediaController.Included}' " + + "in the game logic engine inspector.", + HelpBoxMessageType.Error + ); + Add(_misconfiguredGleHelpBox); + + RegisterCallback(evt => + { + UpdateHelpBoxVisibility(); + EditorApplication.hierarchyChanged += OnHierarchyChanged; + }); + + RegisterCallback(evt => + { + EditorApplication.hierarchyChanged -= OnHierarchyChanged; + }); + } + + private void OnHierarchyChanged() => UpdateHelpBoxVisibility(); + + private void UpdateHelpBoxVisibility() + { + if (_editor.targets.ToList().Any(IsGleMissing)) + _missingGleHelpBox.style.display = DisplayStyle.Flex; + else + _missingGleHelpBox.style.display = DisplayStyle.None; + if (_editor.targets.ToList().Any(IsGleMisconfigured)) + _misconfiguredGleHelpBox.style.display = DisplayStyle.Flex; + else + _misconfiguredGleHelpBox.style.display = DisplayStyle.None; + } + + private MpfGamelogicEngine GetParentGle(UnityEngine.Object target) + { + return ((Component)target).GetComponentInParent(); + } + + private bool IsGleMissing(UnityEngine.Object target) => GetParentGle(target) == null; + + private bool IsGleMisconfigured(UnityEngine.Object target) + { + return !IsGleMissing(target) + && GetParentGle(target).MediaControllerSetting != MpfMediaController.Included; + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/MissingGleHelpBoxes.cs.meta b/Editor/Inspector/MissingGleHelpBoxes.cs.meta new file mode 100644 index 0000000..6d861ca --- /dev/null +++ b/Editor/Inspector/MissingGleHelpBoxes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 349332769875426bb04c4bd9c214dab5 +timeCreated: 1743339477 \ No newline at end of file diff --git a/Editor/Inspector/MpfModeSoundInspector.cs b/Editor/Inspector/ModeSoundInspector.cs similarity index 89% rename from Editor/Inspector/MpfModeSoundInspector.cs rename to Editor/Inspector/ModeSoundInspector.cs index ce03b3c..f2b7339 100644 --- a/Editor/Inspector/MpfModeSoundInspector.cs +++ b/Editor/Inspector/ModeSoundInspector.cs @@ -17,8 +17,8 @@ namespace VisualPinball.Engine.Mpf.Unity.Editor { - [CustomEditor(typeof(MpfModeSound)), CanEditMultipleObjects] - public class MpfModeSoundInspector : BinaryEventSoundInspector + [CustomEditor(typeof(ModeSound)), CanEditMultipleObjects] + public class ModeSoundInspector : BinaryEventSoundInspector { [SerializeField] private VisualTreeAsset mpfModeSoundInspectorXml; diff --git a/Editor/Inspector/MpfModeSoundInspector.cs.meta b/Editor/Inspector/ModeSoundInspector.cs.meta similarity index 100% rename from Editor/Inspector/MpfModeSoundInspector.cs.meta rename to Editor/Inspector/ModeSoundInspector.cs.meta diff --git a/Editor/Inspector/MpfModeSoundInspector.uxml b/Editor/Inspector/ModeSoundInspector.uxml similarity index 100% rename from Editor/Inspector/MpfModeSoundInspector.uxml rename to Editor/Inspector/ModeSoundInspector.uxml diff --git a/Editor/Inspector/MpfModeSoundInspector.uxml.meta b/Editor/Inspector/ModeSoundInspector.uxml.meta similarity index 100% rename from Editor/Inspector/MpfModeSoundInspector.uxml.meta rename to Editor/Inspector/ModeSoundInspector.uxml.meta diff --git a/Editor/Inspector/MonitoredVariableTextInspector.cs b/Editor/Inspector/MonitoredVariableTextInspector.cs new file mode 100644 index 0000000..95f58b6 --- /dev/null +++ b/Editor/Inspector/MonitoredVariableTextInspector.cs @@ -0,0 +1,33 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; +using VisualPinball.Engine.Mpf.Unity.MediaController.Text; + +namespace VisualPinball.Engine.Mpf.Unity.Editor +{ + [ + CustomEditor(typeof(MonitoredVariableTextBase), editorForChildClasses: true), + CanEditMultipleObjects + ] + public class MonitoredVariableTextInspector : UnityEditor.Editor + { + public override VisualElement CreateInspectorGUI() + { + var root = new VisualElement(); + root.Add(new MissingGleHelpBoxes(this)); + InspectorElement.FillDefaultInspector(root, serializedObject, this); + return root; + } + } +} diff --git a/Editor/Inspector/MpfMonitorInspector.cs.meta b/Editor/Inspector/MonitoredVariableTextInspector.cs.meta similarity index 100% rename from Editor/Inspector/MpfMonitorInspector.cs.meta rename to Editor/Inspector/MonitoredVariableTextInspector.cs.meta diff --git a/Editor/Inspector/MpfMonitorInspector.cs b/Editor/Inspector/MpfMonitorInspector.cs deleted file mode 100644 index d6012e9..0000000 --- a/Editor/Inspector/MpfMonitorInspector.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Visual Pinball Engine -// Copyright (C) 2025 freezy and VPE Team -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -using System.Linq; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.UIElements; -using VisualPinball.Engine.Mpf.Unity.MediaController.Text; - -namespace VisualPinball.Engine.Mpf.Unity.Editor -{ - [ - CustomEditor(typeof(MonitoredVariableTextBase), editorForChildClasses: true), - CanEditMultipleObjects - ] - public class MpfMonitorInspector : UnityEditor.Editor - { - private HelpBox _missingGleHelpBox; - private HelpBox _misconfiguredGleHelpBox; - - public override VisualElement CreateInspectorGUI() - { - var root = new VisualElement(); - - _missingGleHelpBox = new HelpBox( - "This component must be on a game object that is underneath an " - + $"'{nameof(MpfGamelogicEngine)}' component in the scene hierarchy.", - HelpBoxMessageType.Error - ); - root.Add(_missingGleHelpBox); - - _misconfiguredGleHelpBox = new HelpBox( - "The MPF game logic engine is not configured to use the included media " - + $"controller. Set 'Media Controller' to '{MpfMediaController.Included}' " - + "in the game logic engine inspector.", - HelpBoxMessageType.Error - ); - root.Add(_misconfiguredGleHelpBox); - - UpdateErrorBoxVisibility(); - - EditorApplication.hierarchyChanged += OnHierarchyChanged; - - InspectorElement.FillDefaultInspector(root, serializedObject, this); - return root; - } - - private void OnHierarchyChanged() => UpdateErrorBoxVisibility(); - - private void UpdateErrorBoxVisibility() - { - if (targets.ToList().Any(IsGleMissing)) - _missingGleHelpBox.style.display = DisplayStyle.Flex; - else - _missingGleHelpBox.style.display = DisplayStyle.None; - if (targets.ToList().Any(IsGleMisconfigured)) - _misconfiguredGleHelpBox.style.display = DisplayStyle.Flex; - else - _misconfiguredGleHelpBox.style.display = DisplayStyle.None; - } - - private void OnDisable() - { - EditorApplication.hierarchyChanged -= OnHierarchyChanged; - } - - private MpfGamelogicEngine GetParentGle(UnityEngine.Object target) - { - return ((Component)target).GetComponentInParent(); - } - - private bool IsGleMissing(UnityEngine.Object target) => GetParentGle(target) == null; - - private bool IsGleMisconfigured(UnityEngine.Object target) - { - return !IsGleMissing(target) - && GetParentGle(target).MediaControllerSetting != MpfMediaController.Included; - } - } -} diff --git a/Editor/Inspector/ToggleOnEventInspector.cs b/Editor/Inspector/ToggleOnEventInspector.cs new file mode 100644 index 0000000..497f8cf --- /dev/null +++ b/Editor/Inspector/ToggleOnEventInspector.cs @@ -0,0 +1,31 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; +using VisualPinball.Engine.Mpf.Unity.MediaController.ObjectToggle; + +namespace VisualPinball.Engine.Mpf.Unity.Editor +{ + [CustomEditor(typeof(ToggleOnEvent)), CanEditMultipleObjects] + public class ToggleOnEventIInspector : UnityEditor.Editor + { + public override VisualElement CreateInspectorGUI() + { + var root = new VisualElement(); + root.Add(new MissingGleHelpBoxes(this)); + root.Add(new DisabledParentObjectHelpBox(this)); + InspectorElement.FillDefaultInspector(root, serializedObject, this); + return root; + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/ToggleOnEventInspector.cs.meta b/Editor/Inspector/ToggleOnEventInspector.cs.meta new file mode 100644 index 0000000..941239a --- /dev/null +++ b/Editor/Inspector/ToggleOnEventInspector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cc65e452dfd54b3abd607de7dc2162b4 +timeCreated: 1743343240 \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Device/DeviceMonitor.cs b/Runtime/MediaController/Messages/Device/DeviceMonitor.cs index 0e5f5b3..5f77020 100644 --- a/Runtime/MediaController/Messages/Device/DeviceMonitor.cs +++ b/Runtime/MediaController/Messages/Device/DeviceMonitor.cs @@ -11,7 +11,6 @@ using System; using Newtonsoft.Json; -using UnityEngine; namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Device { @@ -19,7 +18,7 @@ public abstract class DeviceMonitor : MonitorBase where TMessage : SpecificDeviceMessageBase, IEquatable { - private string _deviceName; + private readonly string _deviceName; protected DeviceMonitor(BcpInterface bcpInterface, string deviceName) : base(bcpInterface) @@ -29,17 +28,19 @@ protected DeviceMonitor(BcpInterface bcpInterface, string deviceName) protected override string BcpCommand => DeviceMessage.Command; protected abstract string Type { get; } + protected delegate TMessage ParseStateDelegate( TDeviceState deserializedState, string deviceName ); + protected abstract ParseStateDelegate ParseState { get; } protected override bool MatchesMonitoringCriteria(DeviceMessage msg) { return base.MatchesMonitoringCriteria(msg) - && msg.Type == Type - && msg.Name == _deviceName; + && msg.Type == Type + && msg.Name == _deviceName; } protected override void MessageHandler_Received(object sender, DeviceMessage msg) @@ -64,7 +65,7 @@ protected override TMessage GetValueFromMessage(DeviceMessage msg) TMessage specificDeviceMessage = ParseState(deserializedState, msg.Name); return specificDeviceMessage; } - + protected abstract void HandleAttributeChange(DeviceAttributeChange change); } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/MachineVariable/MachineVariableMonitor.cs b/Runtime/MediaController/Messages/MachineVariable/MachineVariableMonitor.cs index c67b728..e802db5 100644 --- a/Runtime/MediaController/Messages/MachineVariable/MachineVariableMonitor.cs +++ b/Runtime/MediaController/Messages/MachineVariable/MachineVariableMonitor.cs @@ -13,8 +13,8 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.MachineVariable { - public class MachineVariableMonitor : MpfVariableMonitorBase - where TVar : IEquatable + public class MachineVariableMonitor : MpfVariableMonitorBase + where T : IEquatable { public MachineVariableMonitor(BcpInterface bcpInterface, string varName) : base(bcpInterface, varName) { } diff --git a/Runtime/MediaController/Messages/Mode/Mode.cs b/Runtime/MediaController/Messages/Mode/Mode.cs index baa9103..b13c2ee 100644 --- a/Runtime/MediaController/Messages/Mode/Mode.cs +++ b/Runtime/MediaController/Messages/Mode/Mode.cs @@ -9,9 +9,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Mode { - public readonly struct Mode + public readonly struct Mode : IEquatable { public readonly string Name; public readonly int Priority; @@ -21,5 +23,20 @@ public Mode(string name, int priority) Name = name; Priority = priority; } + + public bool Equals(Mode other) + { + return Name == other.Name && Priority == other.Priority; + } + + public override bool Equals(object obj) + { + return obj is Mode other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, Priority); + } } } diff --git a/Runtime/MediaController/Messages/Mode/ModeList.cs b/Runtime/MediaController/Messages/Mode/ModeList.cs new file mode 100644 index 0000000..a2ad692 --- /dev/null +++ b/Runtime/MediaController/Messages/Mode/ModeList.cs @@ -0,0 +1,49 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.ObjectModel; +using System.Linq; + +namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Mode +{ + public class ModeList : IEquatable + { + private readonly ReadOnlyCollection _list; + + public ModeList(ReadOnlyCollection list) + { + _list = list; + } + + public bool Equals(ModeList other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + if (Equals(_list, other._list)) return true; + if (_list == null || other._list == null) return false; + return _list.Count == other._list.Count && _list.All(other._list.Contains); + } + + public override bool Equals(object obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((ModeList)obj); + } + + public override int GetHashCode() + { + return _list != null ? _list.GetHashCode() : 0; + } + } +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Mode/ModeList.cs.meta b/Runtime/MediaController/Messages/Mode/ModeList.cs.meta new file mode 100644 index 0000000..cb58858 --- /dev/null +++ b/Runtime/MediaController/Messages/Mode/ModeList.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f8a974be979d49dc91298cf5b15d0aa9 +timeCreated: 1743327460 \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Mode/ModeListMessage.cs b/Runtime/MediaController/Messages/Mode/ModeListMessage.cs index 08c039d..3e26514 100644 --- a/Runtime/MediaController/Messages/Mode/ModeListMessage.cs +++ b/Runtime/MediaController/Messages/Mode/ModeListMessage.cs @@ -10,7 +10,6 @@ // SOFTWARE. using System; -using System.Collections.ObjectModel; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -20,12 +19,11 @@ public class ModeListMessage : EventArgs { public const string Command = "mode_list"; public const string RunningModesParamName = "running_modes"; - public ReadOnlyCollection RunningModes => Array.AsReadOnly(_runningModes); - private readonly Mode[] _runningModes; + public readonly ModeList RunningModes; - public ModeListMessage(Mode[] runningModes) + public ModeListMessage(ModeList runningModes) { - _runningModes = runningModes; + RunningModes = runningModes; } public static ModeListMessage FromGenericMessage(BcpMessage bcpMessage) @@ -33,9 +31,9 @@ public static ModeListMessage FromGenericMessage(BcpMessage bcpMessage) try { var jArr = bcpMessage.GetParamValue(RunningModesParamName); - Mode[] runningModes = new Mode[jArr.Count]; + var runningModes = new Mode[jArr.Count]; - for (int i = 0; i < jArr.Count; i++) + for (var i = 0; i < jArr.Count; i++) { var modeJArr = (JArray)jArr[i]; var modeName = (string)modeJArr[0]; @@ -43,16 +41,13 @@ public static ModeListMessage FromGenericMessage(BcpMessage bcpMessage) runningModes[i] = new Mode(modeName, modePrio); } - return new ModeListMessage(runningModes); + return new ModeListMessage(new ModeList(Array.AsReadOnly(runningModes))); } catch (Exception e) - when (e is JsonException - || e is InvalidCastException - || e is IndexOutOfRangeException - ) + when (e is JsonException or InvalidCastException or IndexOutOfRangeException) { - throw new ParameterException(RunningModesParamName, null, e); + throw new ParameterException(RunningModesParamName, bcpMessage, e); } } } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs b/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs new file mode 100644 index 0000000..d8553dd --- /dev/null +++ b/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs @@ -0,0 +1,24 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Mode +{ + public class ModeListMonitor : MonitorBase + { + public ModeListMonitor(BcpInterface bcpInterface) : base(bcpInterface) + { + } + + protected override string BcpCommand => ModeListMessage.Command; + + protected override ModeList GetValueFromMessage(ModeListMessage msg) => msg.RunningModes; + } +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs.meta b/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs.meta new file mode 100644 index 0000000..c371e4f --- /dev/null +++ b/Runtime/MediaController/Messages/Mode/ModeListMonitor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5e62c3d18df2400fa7b213b2dec2a315 +timeCreated: 1743321497 \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Mode/ModeMonitor.cs b/Runtime/MediaController/Messages/Mode/ModeMonitor.cs index 6c679be..4d41611 100644 --- a/Runtime/MediaController/Messages/Mode/ModeMonitor.cs +++ b/Runtime/MediaController/Messages/Mode/ModeMonitor.cs @@ -10,13 +10,13 @@ // SOFTWARE. using System; -using UnityEngine; namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Mode { + // Does not derive from MonitorBase because it needs to listen receive two different message types public class ModeMonitor : IDisposable { - private string _modeName; + private readonly string _modeName; private BcpMessageHandler _modeStartMessageHandler; private BcpMessageHandler _modeStopMessageHandler; diff --git a/Runtime/MediaController/Messages/MonitorBase.cs b/Runtime/MediaController/Messages/MonitorBase.cs index 5b25759..2cb72da 100644 --- a/Runtime/MediaController/Messages/MonitorBase.cs +++ b/Runtime/MediaController/Messages/MonitorBase.cs @@ -18,25 +18,26 @@ public abstract class MonitorBase : IDisposable where TMessage : EventArgs { protected abstract string BcpCommand { get; } - private BcpInterface _bcpInterface; - private BcpMessageHandler _messageHandler; + private readonly BcpInterface _bcpInterface; + private readonly BcpMessageHandler _messageHandler; public event EventHandler ValueChanged; private TVar _varValue; + public TVar VarValue { get => _varValue; protected set { WasEverUpdated = true; - if ((value == null && VarValue == null) || value != null && value.Equals(_varValue)) + if ((value == null && VarValue == null) || value != null && Equals(value, VarValue)) return; _varValue = value; ValueChanged?.Invoke(this, _varValue); } } - public bool WasEverUpdated { get; private set; } = false; + public bool WasEverUpdated { get; private set; } protected MonitorBase(BcpInterface bcpInterface) { @@ -72,4 +73,4 @@ protected virtual void MessageHandler_Received(object sender, TMessage msg) protected abstract TVar GetValueFromMessage(TMessage msg); } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/MpfVariableMonitorBase.cs b/Runtime/MediaController/Messages/MpfVariableMonitorBase.cs index ac834e2..43247d9 100644 --- a/Runtime/MediaController/Messages/MpfVariableMonitorBase.cs +++ b/Runtime/MediaController/Messages/MpfVariableMonitorBase.cs @@ -10,15 +10,15 @@ // SOFTWARE. using System; -using UnityEngine; namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages { - public abstract class MpfVariableMonitorBase : MonitorBase + public abstract class + MpfVariableMonitorBase : MonitorBase where TVar : IEquatable where TMessage : MpfVariableMessageBase { - protected string _varName; + private readonly string _varName; protected MpfVariableMonitorBase(BcpInterface bcpInterface, string varName) : base(bcpInterface) @@ -38,14 +38,10 @@ protected override TVar GetValueFromMessage(TMessage msg) return (TVar)Convert.ChangeType(msg.Value, typeof(TVar)); } catch (Exception e) - when (e is InvalidCastException - || e is FormatException - || e is OverflowException - || e is ArgumentNullException - ) + when (e is InvalidCastException or FormatException or OverflowException or ArgumentNullException) { throw new ParameterException(MpfVariableMessageBase.ValueParamName, null, e); } } } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/PlayerAdded/PlayerCountMonitor.cs b/Runtime/MediaController/Messages/PlayerAdded/PlayerCountMonitor.cs index 31aee36..7fc4b25 100644 --- a/Runtime/MediaController/Messages/PlayerAdded/PlayerCountMonitor.cs +++ b/Runtime/MediaController/Messages/PlayerAdded/PlayerCountMonitor.cs @@ -14,11 +14,13 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.PlayerAdded public class PlayerCountMonitor : MonitorBase { public PlayerCountMonitor(BcpInterface bcpInterface) - : base(bcpInterface) { } + : base(bcpInterface) + { + } // Assumes that player numbers are assigned consecutively starting at 1 protected override int GetValueFromMessage(PlayerAddedMessage msg) => msg.PlayerNum; protected override string BcpCommand => PlayerAddedMessage.Command; } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/PlayerVariable/PlayerVariableMonitor.cs b/Runtime/MediaController/Messages/PlayerVariable/PlayerVariableMonitor.cs index 0b8519e..5c1c828 100644 --- a/Runtime/MediaController/Messages/PlayerVariable/PlayerVariableMonitor.cs +++ b/Runtime/MediaController/Messages/PlayerVariable/PlayerVariableMonitor.cs @@ -15,14 +15,14 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.PlayerVariable { - public class PlayerVariableMonitor - : MpfVariableMonitorBase - where VarType : IEquatable + public class PlayerVariableMonitor + : MpfVariableMonitorBase + where T : IEquatable { - private CurrentPlayerMonitor _currentPlayerMonitor; + private readonly CurrentPlayerMonitor _currentPlayerMonitor; protected override string BcpCommand => PlayerVariableMessage.Command; - protected Dictionary _varPerPlayer = new(); + private readonly Dictionary _varPerPlayer = new(); public PlayerVariableMonitor(BcpInterface bcpInterface, string varName) : base(bcpInterface, varName) @@ -47,16 +47,17 @@ protected override void MessageHandler_Received(object sender, PlayerVariableMes { if (base.MatchesMonitoringCriteria(msg)) { - VarType var = GetValueFromMessage(msg); + T var = GetValueFromMessage(msg); _varPerPlayer[msg.PlayerNum] = var; } + base.MessageHandler_Received(sender, msg); } protected override bool MatchesMonitoringCriteria(PlayerVariableMessage msg) { return base.MatchesMonitoringCriteria(msg) - && msg.PlayerNum == _currentPlayerMonitor.VarValue; + && msg.PlayerNum == _currentPlayerMonitor.VarValue; } } -} +} \ No newline at end of file diff --git a/Runtime/MediaController/Messages/Switch/SwitchMonitor.cs b/Runtime/MediaController/Messages/Switch/SwitchMonitor.cs index 29d26c8..6187397 100644 --- a/Runtime/MediaController/Messages/Switch/SwitchMonitor.cs +++ b/Runtime/MediaController/Messages/Switch/SwitchMonitor.cs @@ -15,7 +15,7 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Switch { public class SwitchMonitor : MonitorBase { - protected string _switchName; + private readonly string _switchName; public SwitchMonitor(BcpInterface bcpInterface, string switchName) : base(bcpInterface) diff --git a/Runtime/MediaController/Messages/Trigger/MpfEventListener.cs b/Runtime/MediaController/Messages/Trigger/MpfEventListener.cs index 54e7c70..231c226 100644 --- a/Runtime/MediaController/Messages/Trigger/MpfEventListener.cs +++ b/Runtime/MediaController/Messages/Trigger/MpfEventListener.cs @@ -14,9 +14,11 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Trigger { + /// + /// Provides an event handler for arbitrary MPF events + /// public class MpfEventListener : IDisposable { - [SerializeField] private string _eventName; private BcpInterface _bcpInterface; diff --git a/Runtime/MediaController/ObjectToggle.meta b/Runtime/MediaController/ObjectToggle.meta new file mode 100644 index 0000000..368221a --- /dev/null +++ b/Runtime/MediaController/ObjectToggle.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 53c0880af48c4bffa131486958a6c8ac +timeCreated: 1743329846 \ No newline at end of file diff --git a/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs b/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs new file mode 100644 index 0000000..9c04a8b --- /dev/null +++ b/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs @@ -0,0 +1,57 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using UnityEngine; +using VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Mode; + +namespace VisualPinball.Engine.Mpf.Unity.MediaController.ObjectToggle +{ + /// + /// Enable the parent game object while the specified mode is active in MPF. + /// + [AddComponentMenu("Pinball/MPF Media Controller/Enable During MPF Mode")] + [DisallowMultipleComponent] + public class EnableDuringMode : MonoBehaviour + { + [SerializeField] private string _mode; + + private ModeMonitor _modeMonitor; + + private void Awake() + { + if (!MpfGamelogicEngine.TryGetBcpInterface(this, out var bcpInterface)) return; + + _modeMonitor = new ModeMonitor(bcpInterface, _mode); + _modeMonitor.IsModeActiveChanged += OnModeActiveChanged; + } + + private void Start() + { + // This is done in Start to give other components like this one attached to children of this game object a + // chance to run their Awake functions. + gameObject.SetActive(false); + } + + private void OnDestroy() + { + if (_modeMonitor != null) + { + _modeMonitor.IsModeActiveChanged -= OnModeActiveChanged; + _modeMonitor.Dispose(); + } + } + + private void OnModeActiveChanged(object sender, bool isActive) + { + gameObject.SetActive(isActive); + } + } +} \ No newline at end of file diff --git a/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs.meta b/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs.meta new file mode 100644 index 0000000..3041644 --- /dev/null +++ b/Runtime/MediaController/ObjectToggle/EnableDuringMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 79f9cfb88e574490a16919b31f49c35b +timeCreated: 1743332854 \ No newline at end of file diff --git a/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs b/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs new file mode 100644 index 0000000..d872194 --- /dev/null +++ b/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs @@ -0,0 +1,94 @@ +// Visual Pinball Engine +// Copyright (C) 2025 freezy and VPE Team +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using UnityEngine; +using VisualPinball.Engine.Mpf.Unity.MediaController.Messages.Trigger; + +namespace VisualPinball.Engine.Mpf.Unity.MediaController.ObjectToggle +{ + /// + /// Toggle the parent game object when the specified enable and disable events occur in MPF. + /// + [AddComponentMenu("Pinball/MPF Media Controller/Toggle On MPF Event")] + public class ToggleOnEvent : MonoBehaviour + { + [SerializeField] private bool _enabledOnStart; + [SerializeField] private string _enableEvent; + [SerializeField] private string _disableEvent; + + private MpfEventListener _enableEventListener; + private MpfEventListener _disableEventListener; + private MpfEventListener _toggleEventListener; + + + private void Awake() + { + if (!MpfGamelogicEngine.TryGetBcpInterface(this, out var bcpInterface)) return; + + if (_enableEvent == _disableEvent) + { + _toggleEventListener = new MpfEventListener(bcpInterface, _enableEvent); + _toggleEventListener.Triggered += OnToggleEvent; + } + else + { + _enableEventListener = new MpfEventListener(bcpInterface, _enableEvent); + _enableEventListener.Triggered += OnEnableEvent; + _disableEventListener = new MpfEventListener(bcpInterface, _disableEvent); + _disableEventListener.Triggered += OnDisableEvent; + } + } + + private void Start() + { + // This is done in Start to give other components like this one attached to children of this game object a + // chance to run their Awake functions. + gameObject.SetActive(_enabledOnStart); + } + + private void OnDestroy() + { + if (_toggleEventListener != null) + { + _toggleEventListener.Triggered -= OnToggleEvent; + _toggleEventListener.Dispose(); + } + + if (_enableEventListener != null) + { + _enableEventListener.Triggered -= OnEnableEvent; + _enableEventListener.Dispose(); + } + + if (_disableEventListener != null) + { + _disableEventListener.Triggered -= OnDisableEvent; + _disableEventListener.Dispose(); + } + } + + private void OnEnableEvent(object sender, EventArgs eventArgs) + { + gameObject.SetActive(true); + } + + private void OnDisableEvent(object sender, EventArgs eventArgs) + { + gameObject.SetActive(false); + } + + private void OnToggleEvent(object sender, EventArgs eventArgs) + { + gameObject.SetActive(!gameObject.activeSelf); + } + } +} \ No newline at end of file diff --git a/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs.meta b/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs.meta new file mode 100644 index 0000000..f361d4d --- /dev/null +++ b/Runtime/MediaController/ObjectToggle/ToggleOnEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e216c9d0474b4ef8bd4de642beddee45 +timeCreated: 1743329921 \ No newline at end of file diff --git a/Runtime/MediaController/Sound/MpfEventSound.cs b/Runtime/MediaController/Sound/EventSound.cs similarity index 91% rename from Runtime/MediaController/Sound/MpfEventSound.cs rename to Runtime/MediaController/Sound/EventSound.cs index 7d81b09..eedef49 100644 --- a/Runtime/MediaController/Sound/MpfEventSound.cs +++ b/Runtime/MediaController/Sound/EventSound.cs @@ -16,8 +16,8 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Sound { - [AddComponentMenu("Visual Pinball/Sound/Mpf Event Sound")] - public class MpfEventSound : EventSoundComponent + [AddComponentMenu("Pinball/Sound/MPF Event Sound")] + public class EventSound : EventSoundComponent { [SerializeField] private string _eventName; diff --git a/Runtime/MediaController/Sound/MpfEventSound.cs.meta b/Runtime/MediaController/Sound/EventSound.cs.meta similarity index 100% rename from Runtime/MediaController/Sound/MpfEventSound.cs.meta rename to Runtime/MediaController/Sound/EventSound.cs.meta diff --git a/Runtime/MediaController/Sound/MpfModeSound.cs b/Runtime/MediaController/Sound/ModeSound.cs similarity index 91% rename from Runtime/MediaController/Sound/MpfModeSound.cs rename to Runtime/MediaController/Sound/ModeSound.cs index 3d2cd89..df41027 100644 --- a/Runtime/MediaController/Sound/MpfModeSound.cs +++ b/Runtime/MediaController/Sound/ModeSound.cs @@ -15,8 +15,8 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Sound { - [AddComponentMenu("Visual Pinball/Sound/Mpf Mode Sound")] - public class MpfModeSound : BinaryEventSoundComponent + [AddComponentMenu("Pinball/Sound/MPF Mode Sound")] + public class ModeSound : BinaryEventSoundComponent { [SerializeField] private string _modeName; diff --git a/Runtime/MediaController/Sound/MpfModeSound.cs.meta b/Runtime/MediaController/Sound/ModeSound.cs.meta similarity index 100% rename from Runtime/MediaController/Sound/MpfModeSound.cs.meta rename to Runtime/MediaController/Sound/ModeSound.cs.meta diff --git a/Runtime/MediaController/Text/CurrentPlayerText.cs b/Runtime/MediaController/Text/CurrentPlayerText.cs index 281e1c7..4d062d9 100644 --- a/Runtime/MediaController/Text/CurrentPlayerText.cs +++ b/Runtime/MediaController/Text/CurrentPlayerText.cs @@ -9,11 +9,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; using VisualPinball.Engine.Mpf.Unity.MediaController.Messages; using VisualPinball.Engine.Mpf.Unity.MediaController.Messages.PlayerTurnStart; namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Current Player Text")] public class CurrentPlayerText : MonitoredVariableText { protected override MonitorBase CreateMonitor( diff --git a/Runtime/MediaController/Text/MachineVariable/FloatMachineVariableText.cs b/Runtime/MediaController/Text/MachineVariable/FloatMachineVariableText.cs index 7c29317..7ef39cc 100644 --- a/Runtime/MediaController/Text/MachineVariable/FloatMachineVariableText.cs +++ b/Runtime/MediaController/Text/MachineVariable/FloatMachineVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Machine Variable Text (Float)")] public class FloatMachineVariableText : MachineVariableText { } } diff --git a/Runtime/MediaController/Text/MachineVariable/IntMachineVariableText.cs b/Runtime/MediaController/Text/MachineVariable/IntMachineVariableText.cs index 72bae42..1cae07b 100644 --- a/Runtime/MediaController/Text/MachineVariable/IntMachineVariableText.cs +++ b/Runtime/MediaController/Text/MachineVariable/IntMachineVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Machine Variable Text (Int)")] public class IntMachineVariableText : MachineVariableText { } } diff --git a/Runtime/MediaController/Text/MachineVariable/StringMachineVariableText.cs b/Runtime/MediaController/Text/MachineVariable/StringMachineVariableText.cs index 19287da..1f17cdc 100644 --- a/Runtime/MediaController/Text/MachineVariable/StringMachineVariableText.cs +++ b/Runtime/MediaController/Text/MachineVariable/StringMachineVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Machine Variable Text (String)")] public class StringMachineVariableText : MachineVariableText { } } diff --git a/Runtime/MediaController/Text/MonitoredVariableText.cs b/Runtime/MediaController/Text/MonitoredVariableText.cs index 68333e8..cf7fef7 100644 --- a/Runtime/MediaController/Text/MonitoredVariableText.cs +++ b/Runtime/MediaController/Text/MonitoredVariableText.cs @@ -16,6 +16,7 @@ namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + // This non-generic base class exists so there can be one inspector for all generic variations. public abstract class MonitoredVariableTextBase : MonoBehaviour { [SerializeField] diff --git a/Runtime/MediaController/Text/PlayerCountText.cs b/Runtime/MediaController/Text/PlayerCountText.cs index 51ebde0..39fcba6 100644 --- a/Runtime/MediaController/Text/PlayerCountText.cs +++ b/Runtime/MediaController/Text/PlayerCountText.cs @@ -9,11 +9,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; using VisualPinball.Engine.Mpf.Unity.MediaController.Messages; using VisualPinball.Engine.Mpf.Unity.MediaController.Messages.PlayerAdded; namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Player Count Text")] public class PlayerCountText : MonitoredVariableText { protected override MonitorBase CreateMonitor( diff --git a/Runtime/MediaController/Text/PlayerVariable/FloatPlayerVariableText.cs b/Runtime/MediaController/Text/PlayerVariable/FloatPlayerVariableText.cs index 04161d3..4f3ac42 100644 --- a/Runtime/MediaController/Text/PlayerVariable/FloatPlayerVariableText.cs +++ b/Runtime/MediaController/Text/PlayerVariable/FloatPlayerVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Player Variable Text (Float)")] public class FloatPlayerVariableText : PlayerVariableText { } } diff --git a/Runtime/MediaController/Text/PlayerVariable/IntPlayerVariableText.cs b/Runtime/MediaController/Text/PlayerVariable/IntPlayerVariableText.cs index 6f2b037..e1b3329 100644 --- a/Runtime/MediaController/Text/PlayerVariable/IntPlayerVariableText.cs +++ b/Runtime/MediaController/Text/PlayerVariable/IntPlayerVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Player Variable Text (Int)")] public class IntPlayerVariableText : PlayerVariableText { } } diff --git a/Runtime/MediaController/Text/PlayerVariable/StringPlayerVariableText.cs b/Runtime/MediaController/Text/PlayerVariable/StringPlayerVariableText.cs index 8575714..f34b2c7 100644 --- a/Runtime/MediaController/Text/PlayerVariable/StringPlayerVariableText.cs +++ b/Runtime/MediaController/Text/PlayerVariable/StringPlayerVariableText.cs @@ -9,7 +9,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using UnityEngine; + namespace VisualPinball.Engine.Mpf.Unity.MediaController.Text { + [AddComponentMenu("Pinball/MPF Media Controller/MPF Player Variable Text (String)")] public class StringPlayerVariableText : PlayerVariableText { } } diff --git a/Runtime/MpfGamelogicEngine.cs b/Runtime/MpfGamelogicEngine.cs index 38321e5..bef5469 100644 --- a/Runtime/MpfGamelogicEngine.cs +++ b/Runtime/MpfGamelogicEngine.cs @@ -29,6 +29,7 @@ namespace VisualPinball.Engine.Mpf.Unity /// Allows the Mission Pinball Framework to drive VPE by sending switch changes to MPF /// and applying changes to coils, lights and hardware rules requested by MPF. /// + [AddComponentMenu("Pinball/Gamelogic Engine/MPF Game Logic")] public class MpfGamelogicEngine : MonoBehaviour, IGamelogicEngine { [SerializeField]