diff --git a/.gitignore b/.gitignore index 0673581..01b8a8b 100644 --- a/.gitignore +++ b/.gitignore @@ -364,3 +364,5 @@ MigrationBackup/ # Vi swap files *.swp + +.DS_Store diff --git a/Editor/Descriptors/ClearDisplayUnitDescriptor.cs b/Editor/Descriptors/ClearDisplayUnitDescriptor.cs new file mode 100644 index 0000000..1272f0d --- /dev/null +++ b/Editor/Descriptors/ClearDisplayUnitDescriptor.cs @@ -0,0 +1,39 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// ReSharper disable UnusedType.Global + +using Unity.VisualScripting; +using VisualPinball.Unity.Editor; +using IconSize = VisualPinball.Unity.Editor.IconSize; + +namespace VisualPinball.Unity.VisualScripting.Editor +{ + [Descriptor(typeof(ClearDisplayUnit))] + public class ClearDisplayUnitDescriptor : UnitDescriptor + { + public ClearDisplayUnitDescriptor(ClearDisplayUnit target) : base(target) + { + } + + protected override string DefinedSummary() + { + return "This node clears a display connected through the given ID."; + } + + protected override EditorTexture DefinedIcon() => EditorTexture.Single(Unity.Editor.Icons.UpdateDisplay); + } +} diff --git a/Editor/Descriptors/ClearDisplayUnitDescriptor.cs.meta b/Editor/Descriptors/ClearDisplayUnitDescriptor.cs.meta new file mode 100644 index 0000000..e788ef7 --- /dev/null +++ b/Editor/Descriptors/ClearDisplayUnitDescriptor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86eda94feb9564ccf8c7a4dbe3079be7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Descriptors/DisplayEventUnitDescriptor.cs b/Editor/Descriptors/DisplayEventUnitDescriptor.cs new file mode 100644 index 0000000..a7206fd --- /dev/null +++ b/Editor/Descriptors/DisplayEventUnitDescriptor.cs @@ -0,0 +1,45 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// ReSharper disable UnusedType.Global + +using Unity.VisualScripting; + +namespace VisualPinball.Unity.VisualScripting.Editor +{ + [Descriptor(typeof(DisplayEventUnit))] + public class DisplayEventUnitDescriptor : UnitDescriptor + { + public DisplayEventUnitDescriptor(DisplayEventUnit target) : base(target) { } + + protected override EditorTexture DefinedIcon() => EditorTexture.Single(Unity.Editor.Icons.DisplayEvent); + + protected override void DefinedPort(IUnitPort port, UnitPortDescription desc) + { + base.DefinedPort(port, desc); + + switch (port.key) + { + case nameof(DisplayEventUnit.NumericOutput): + desc.summary = "The numerical value of the display event."; + break; + case nameof(DisplayEventUnit.TextOutput): + desc.summary = "The text value of the display event."; + break; + } + } + } +} diff --git a/Editor/Descriptors/DisplayEventUnitDescriptor.cs.meta b/Editor/Descriptors/DisplayEventUnitDescriptor.cs.meta new file mode 100644 index 0000000..088f0b3 --- /dev/null +++ b/Editor/Descriptors/DisplayEventUnitDescriptor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 60c0acc9f3d294135be71b5edc285b47 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Descriptors/UpdateDisplayUnitDescriptor.cs b/Editor/Descriptors/UpdateDisplayUnitDescriptor.cs index 34bf0da..d4eedfc 100644 --- a/Editor/Descriptors/UpdateDisplayUnitDescriptor.cs +++ b/Editor/Descriptors/UpdateDisplayUnitDescriptor.cs @@ -17,8 +17,6 @@ // ReSharper disable UnusedType.Global using Unity.VisualScripting; -using VisualPinball.Unity.Editor; -using IconSize = VisualPinball.Unity.Editor.IconSize; namespace VisualPinball.Unity.VisualScripting.Editor { diff --git a/Editor/Inspectors/DisplayDefinitionInspector.cs b/Editor/Inspectors/DisplayDefinitionInspector.cs index a88e57c..6f9cc63 100644 --- a/Editor/Inspectors/DisplayDefinitionInspector.cs +++ b/Editor/Inspectors/DisplayDefinitionInspector.cs @@ -40,6 +40,7 @@ protected override void OnGUI(Rect position, GUIContent label) var varNames = new List { "None" } .Concat(gle.Displays.Select(d => d.Id)) .ToArray(); + var currentDisplayDef = metadata.value as DisplayDefinition; var currentIndex = 0; if (currentDisplayDef != null) { diff --git a/Editor/Widgets/ClearDisplayUnitWidget.cs b/Editor/Widgets/ClearDisplayUnitWidget.cs new file mode 100644 index 0000000..4589824 --- /dev/null +++ b/Editor/Widgets/ClearDisplayUnitWidget.cs @@ -0,0 +1,30 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// ReSharper disable UnusedType.Global + +using Unity.VisualScripting; + +namespace VisualPinball.Unity.VisualScripting.Editor +{ + [Widget(typeof(ClearDisplayUnit))] + public sealed class ClearDisplayUnitWidget : GleUnitWidget + { + public ClearDisplayUnitWidget(FlowCanvas canvas, ClearDisplayUnit unit) : base(canvas, unit) + { + } + } +} diff --git a/Editor/Widgets/ClearDisplayUnitWidget.cs.meta b/Editor/Widgets/ClearDisplayUnitWidget.cs.meta new file mode 100644 index 0000000..fc4d182 --- /dev/null +++ b/Editor/Widgets/ClearDisplayUnitWidget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a040226b549bc402d83800689d1ca891 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Widgets/DisplayEventUnitWidget.cs b/Editor/Widgets/DisplayEventUnitWidget.cs new file mode 100644 index 0000000..f0dd158 --- /dev/null +++ b/Editor/Widgets/DisplayEventUnitWidget.cs @@ -0,0 +1,30 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// ReSharper disable UnusedType.Global + +using Unity.VisualScripting; + +namespace VisualPinball.Unity.VisualScripting.Editor +{ + [Widget(typeof(DisplayEventUnit))] + public sealed class DisplayEventUnitWidget : GleUnitWidget + { + public DisplayEventUnitWidget(FlowCanvas canvas, DisplayEventUnit unit) : base(canvas, unit) + { + } + } +} diff --git a/Editor/Widgets/DisplayEventUnitWidget.cs.meta b/Editor/Widgets/DisplayEventUnitWidget.cs.meta new file mode 100644 index 0000000..62d2850 --- /dev/null +++ b/Editor/Widgets/DisplayEventUnitWidget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 71c5c16c4dcbd449195a1195a75602f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Gamelogic/VisualScriptingEventNames.cs b/Runtime/Gamelogic/VisualScriptingEventNames.cs index 461b07f..7b59c6d 100644 --- a/Runtime/Gamelogic/VisualScriptingEventNames.cs +++ b/Runtime/Gamelogic/VisualScriptingEventNames.cs @@ -22,6 +22,7 @@ public static class VisualScriptingEventNames public const string LampEvent = "LampEvent"; public const string SwitchEvent = "SwitchEvent"; public const string CoilEvent = "CoilEvent"; + public const string DisplayChangedEvent = "DisplayChangedEvent"; public const string CurrentPlayerChanged = "CurrentPlayerChanged"; public const string PlayerVariableChanged = "PlayerVariableChanged"; public const string TableVariableChanged = "TableVariableChanged"; diff --git a/Runtime/Gamelogic/VisualScriptingGamelogicEngine.cs b/Runtime/Gamelogic/VisualScriptingGamelogicEngine.cs index 0bcc49b..6fc794b 100644 --- a/Runtime/Gamelogic/VisualScriptingGamelogicEngine.cs +++ b/Runtime/Gamelogic/VisualScriptingGamelogicEngine.cs @@ -64,7 +64,10 @@ public class VisualScriptingGamelogicEngine : MonoBehaviour, IGamelogicEngine, I public GamelogicEngineWire[] AvailableWires => Wires; public event EventHandler OnDisplaysRequested; - public event EventHandler OnDisplayFrame; + public event EventHandler OnDisplayClear; + public event EventHandler OnDisplayUpdateFrame; + public event EventHandler OnDisplayUpdated; + public event EventHandler OnLampChanged; public event EventHandler OnLampsChanged; public event EventHandler OnCoilChanged; @@ -87,11 +90,6 @@ public PlayerState CurrentPlayerState { } } - public void DisplayFrame(DisplayFrameData data) - { - OnDisplayFrame?.Invoke(this, data); - } - public void SetCurrentPlayer(int value, bool forceNotify = false) { if (!PlayerStates.ContainsKey(value)) { @@ -159,6 +157,16 @@ public void OnInit(Player player, TableApi tableApi, BallManager ballManager) EventBus.Trigger(VisualScriptingEventNames.GleStartedEvent, EventArgs.Empty); } + public void DisplayClear(string id) + { + OnDisplayClear?.Invoke(this, id); + } + + public void DisplayUpdateFrame(DisplayFrameData data) + { + OnDisplayUpdateFrame?.Invoke(this, data); + } + public void Switch(string id, bool isClosed) { var args = new SwitchEventArgs2(id, isClosed); @@ -178,6 +186,11 @@ public void SetLamp(string id, float value, bool isCoil = false, LampSource sour OnLampChanged?.Invoke(this, new LampEventArgs(id, value, isCoil, source)); } + public void DisplayChanged(DisplayFrameData data) + { + EventBus.Trigger(VisualScriptingEventNames.DisplayChangedEvent, new DisplayChangedEventArgs(data)); + } + public LampState GetLamp(string id) { return _player.LampStatuses.ContainsKey(id) ? _player.LampStatuses[id] : LampState.Default; @@ -193,7 +206,6 @@ public bool GetCoil(string id) return _player.CoilStatuses.ContainsKey(id) && _player.CoilStatuses[id]; } - public void OnBeforeSerialize() { #if UNITY_EDITOR diff --git a/Runtime/Nodes/Display/ClearDisplayUnit.cs b/Runtime/Nodes/Display/ClearDisplayUnit.cs new file mode 100644 index 0000000..52e6c39 --- /dev/null +++ b/Runtime/Nodes/Display/ClearDisplayUnit.cs @@ -0,0 +1,60 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using System.Text; +using Unity.VisualScripting; + +namespace VisualPinball.Unity.VisualScripting +{ + [UnitTitle("Clear Display")] + [UnitSurtitle("Gamelogic Engine")] + [UnitCategory("Visual Pinball")] + public class ClearDisplayUnit : GleUnit + { + [Serialize, Inspectable, UnitHeaderInspectable("ID")] + public DisplayDefinition Display { get; private set; } + + [DoNotSerialize] + [PortLabelHidden] + public ControlInput InputTrigger; + + [DoNotSerialize] + [PortLabelHidden] + public ControlOutput OutputTrigger; + + protected override void Definition() + { + InputTrigger = ControlInput(nameof(InputTrigger), Process); + OutputTrigger = ControlOutput(nameof(OutputTrigger)); + + Succession(InputTrigger, OutputTrigger); + } + + private ControlOutput Process(Flow flow) + { + if (!AssertVsGle(flow)) { + throw new InvalidOperationException("Cannot retrieve GLE from unit."); + } + + if (Display != null) { + VsGle.DisplayClear(Display.Id); + } + + return OutputTrigger; + } + } +} diff --git a/Runtime/Nodes/Display/ClearDisplayUnit.cs.meta b/Runtime/Nodes/Display/ClearDisplayUnit.cs.meta new file mode 100644 index 0000000..177c850 --- /dev/null +++ b/Runtime/Nodes/Display/ClearDisplayUnit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15ec3d88570f643b3913dce96027e86a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Nodes/Display/DisplayEventUnit.cs b/Runtime/Nodes/Display/DisplayEventUnit.cs new file mode 100644 index 0000000..00b5945 --- /dev/null +++ b/Runtime/Nodes/Display/DisplayEventUnit.cs @@ -0,0 +1,84 @@ +// Visual Pinball Engine +// Copyright (C) 2022 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using Unity.VisualScripting; +using UnityEngine; + +namespace VisualPinball.Unity.VisualScripting +{ + [UnitTitle("On Display Changed")] + [UnitSurtitle("Gamelogic Engine")] + [UnitCategory("Events\\Visual Pinball")] + public class DisplayEventUnit : GleEventUnit + { + [Serialize] + [Inspectable] + [UnitHeaderInspectable("ID")] + public DisplayDefinition Display { get; private set; } + + [DoNotSerialize] + [PortLabel("Numeric")] + public ValueOutput NumericOutput { get; private set; } + + [DoNotSerialize] + [PortLabel("Text")] + public ValueOutput TextOutput { get; private set; } + + [DoNotSerialize] + protected override bool register => true; + + public override EventHook GetHook(GraphReference reference) => new(VisualScriptingEventNames.DisplayChangedEvent); + + protected override void Definition() + { + base.Definition(); + + if (Display != null) { + if (Display.Supports(DisplayFrameFormat.Numeric)) { + NumericOutput = ValueOutput(nameof(NumericOutput)); + } + + if (Display.Supports(DisplayFrameFormat.AlphaNumeric)) { + TextOutput = ValueOutput(nameof(TextOutput)); + } + } + } + + protected override bool ShouldTrigger(Flow flow, DisplayChangedEventArgs args) + { + return Display != null && Display.Id.Equals(args.DisplayFrameData.Id); + } + + protected override void AssignArguments(Flow flow, DisplayChangedEventArgs args) + { + if (Display.Supports(DisplayFrameFormat.Numeric)) { + if (args.DisplayFrameData.Format == DisplayFrameFormat.Numeric) { + flow.SetValue(NumericOutput, BitConverter.ToSingle(args.DisplayFrameData.Data)); + } + } + + if (Display.Supports(DisplayFrameFormat.AlphaNumeric)) { + if (args.DisplayFrameData.Format == DisplayFrameFormat.AlphaNumeric) { + flow.SetValue(TextOutput, Encoding.UTF8.GetString(args.DisplayFrameData.Data)); + } + } + } + } +} diff --git a/Runtime/Nodes/Display/DisplayEventUnit.cs.meta b/Runtime/Nodes/Display/DisplayEventUnit.cs.meta new file mode 100644 index 0000000..c7579a2 --- /dev/null +++ b/Runtime/Nodes/Display/DisplayEventUnit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b573073ca33b4faa8898ea67c052243 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Nodes/Display/UpdateDisplayUnit.cs b/Runtime/Nodes/Display/UpdateDisplayUnit.cs index 3bc4cc2..344c364 100644 --- a/Runtime/Nodes/Display/UpdateDisplayUnit.cs +++ b/Runtime/Nodes/Display/UpdateDisplayUnit.cs @@ -105,42 +105,42 @@ private ControlOutput Process(Flow flow) if (Display != null) { if (Display.Supports(DisplayFrameFormat.Numeric) && NumericInput.hasValidConnection) { var numValue = flow.GetValue(NumericInput); - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Numeric, BitConverter.GetBytes(numValue))); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Numeric, BitConverter.GetBytes(numValue))); } if (Display.Supports(DisplayFrameFormat.AlphaNumeric) && flow.IsLocal(TextInput)) { var strValue = flow.GetValue(TextInput); if (!string.IsNullOrEmpty(strValue)) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.AlphaNumeric, Encoding.UTF8.GetBytes(strValue))); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.AlphaNumeric, Encoding.UTF8.GetBytes(strValue))); } } if (Display.Supports(DisplayFrameFormat.Segment) && SegmentInput.hasValidConnection) { var byteValue = flow.GetValue(SegmentInput); if (byteValue is { Length: > 0 }) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Segment, byteValue)); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Segment, byteValue)); } } if (Display.Supports(DisplayFrameFormat.Dmd2) && Dmd2Input.hasValidConnection) { var byteValue = flow.GetValue(Dmd2Input); if (byteValue is { Length: > 0 }) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd2, byteValue)); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd2, byteValue)); } } if (Display.Supports(DisplayFrameFormat.Dmd4) && Dmd4Input.hasValidConnection) { var byteValue = flow.GetValue(Dmd4Input); if (byteValue is { Length: > 0 }) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd4, byteValue)); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd4, byteValue)); } } if (Display.Supports(DisplayFrameFormat.Dmd8) && Dmd8Input.hasValidConnection) { var byteValue = flow.GetValue(Dmd8Input); if (byteValue is { Length: > 0 }) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd8, byteValue)); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd8, byteValue)); } } if (Display.Supports(DisplayFrameFormat.Dmd24) && Dmd24Input.hasValidConnection) { var byteValue = flow.GetValue(Dmd24Input); if (byteValue is { Length: > 0 }) { - VsGle.DisplayFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd24, byteValue)); + VsGle.DisplayUpdateFrame(new DisplayFrameData(Display.Id, DisplayFrameFormat.Dmd24, byteValue)); } } } diff --git a/Runtime/Nodes/Event/PinballEventUnit.cs b/Runtime/Nodes/Event/PinballEventUnit.cs index ac299c4..4952faa 100644 --- a/Runtime/Nodes/Event/PinballEventUnit.cs +++ b/Runtime/Nodes/Event/PinballEventUnit.cs @@ -61,7 +61,7 @@ protected override void Definition() protected override bool ShouldTrigger(Flow flow, PinballEventArgs args) { - return Event.Id.Equals(args.Id); + return Event != null && Event.Id.Equals(args.Id); } protected override void AssignArguments(Flow flow, PinballEventArgs args)