Skip to content

Commit a984b59

Browse files
committed
mech: Handle solenoids by coil manager.
1 parent edac690 commit a984b59

File tree

3 files changed

+69
-28
lines changed

3 files changed

+69
-28
lines changed

VisualPinball.Engine.PinMAME.Unity/Editor/PinMameMechInspector.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ namespace VisualPinball.Unity.Editor
2727
public class PinMameMechInspector : ItemInspector
2828
{
2929
private SerializedProperty _typeProperty;
30-
private SerializedProperty _solenoid1Property;
31-
private SerializedProperty _solenoid2Property;
3230
private SerializedProperty _repeatProperty;
3331
private SerializedProperty _linearMovementProperty;
3432
private SerializedProperty _fastUpdatesProperty;
@@ -46,8 +44,6 @@ protected override void OnEnable()
4644
base.OnEnable();
4745

4846
_typeProperty = serializedObject.FindProperty(nameof(PinMameMechComponent.Type));
49-
_solenoid1Property = serializedObject.FindProperty(nameof(PinMameMechComponent.Solenoid1));
50-
_solenoid2Property = serializedObject.FindProperty(nameof(PinMameMechComponent.Solenoid2));
5147
_repeatProperty = serializedObject.FindProperty(nameof(PinMameMechComponent.Repeat));
5248
_linearMovementProperty = serializedObject.FindProperty(nameof(PinMameMechComponent.LinearMovement));
5349
_fastUpdatesProperty = serializedObject.FindProperty(nameof(PinMameMechComponent.FastUpdates));
@@ -66,15 +62,6 @@ public override void OnInspectorGUI()
6662
OnPreInspectorGUI();
6763

6864
PropertyField(_typeProperty);
69-
if (_typeProperty.enumValueIndex == (int)PinMameMechType.OneDirectionalSolenoid) {
70-
PropertyField(_solenoid1Property, "Solenoid");
71-
72-
} else {
73-
PropertyField(_solenoid1Property);
74-
}
75-
if (_typeProperty.enumValueIndex > (int)PinMameMechType.OneDirectionalSolenoid && _typeProperty.enumValueIndex != (int)PinMameMechType.FourStepperSolenoids) {
76-
PropertyField(_solenoid2Property);
77-
}
7865
PropertyField(_repeatProperty);
7966
PropertyField(_lengthProperty);
8067
PropertyField(_stepsProperty);

VisualPinball.Engine.PinMAME.Unity/Runtime/PinMameGamelogicEngine.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ public void OnInit(Player player, TableApi tableApi, BallManager ballManager)
174174
public void RegisterMech(PinMameMechComponent mechComponent)
175175
{
176176
var id = _numMechs++;
177+
if (id > _pinMame.GetMaxMechs()) {
178+
Logger.Error($"PinMAME only supports up to {_pinMame.GetMaxMechs()} custom mechs, ignoring {mechComponent.name}.");
179+
return;
180+
}
177181
_registeredMechs[id] = mechComponent;
178182
}
179183

@@ -486,7 +490,7 @@ public void SendInitialSwitches()
486490
private void SendMechs()
487491
{
488492
foreach (var (id, mech) in _registeredMechs) {
489-
var mechConfig = mech.Config(_player.SwitchMapping);
493+
var mechConfig = mech.Config(_player.SwitchMapping, _player.CoilMapping);
490494
_pinMame.SetMech(id, mechConfig);
491495
foreach (var c in mechConfig.SwitchList) {
492496
_mechSwitches.Add(c.SwNo);

VisualPinball.Engine.PinMAME.Unity/Runtime/PinMameMechComponent.cs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,13 @@
2929
namespace VisualPinball.Engine.PinMAME
3030
{
3131
[AddComponentMenu("Visual Pinball/PinMAME/PinMAME Mech Handler")]
32-
public class PinMameMechComponent : MonoBehaviour, IMechHandler, ISwitchDeviceComponent, ISerializationCallbackReceiver
32+
public class PinMameMechComponent : MonoBehaviour, IMechHandler, ISwitchDeviceComponent, ICoilDeviceComponent, ISerializationCallbackReceiver
3333
{
3434
#region Data
3535

3636
[Tooltip("This defines how the mech is controlled.")]
3737
public PinMameMechType Type = PinMameMechType.OneDirectionalSolenoid;
3838

39-
[Tooltip("The first solenoid handled by the mech.")]
40-
public int Solenoid1;
41-
42-
[Tooltip("The second solenoid handled by the mech.")]
43-
public int Solenoid2;
44-
4539
[Tooltip("How the mech behaves when the end of the range of motion is reached.")]
4640
public PinMameRepeat Repeat;
4741

@@ -71,6 +65,7 @@ public class PinMameMechComponent : MonoBehaviour, IMechHandler, ISwitchDeviceCo
7165
[Tooltip("The amount of time in milliseconds required to reach full speed.")]
7266
public int Acceleration;
7367

68+
[Unit("times acceleration")]
7469
[Min(0)]
7570
[Tooltip("Retardation factor. One means same as acceleration, 0.5 half as fast, etc.")]
7671
public int Retardation;
@@ -79,9 +74,12 @@ public class PinMameMechComponent : MonoBehaviour, IMechHandler, ISwitchDeviceCo
7974

8075
#region Access
8176

77+
[SerializeField] private string _solenoid1;
78+
[SerializeField] private string _solenoid2;
79+
8280
public event EventHandler<MechEventArgs> OnMechUpdate;
8381

84-
public PinMameMechConfig Config(List<SwitchMapping> switchMappings)
82+
public PinMameMechConfig Config(List<SwitchMapping> switchMappings, List<CoilMapping> coilMappings)
8583
{
8684
var type = 0u;
8785
type |= Type switch {
@@ -104,10 +102,13 @@ public PinMameMechConfig Config(List<SwitchMapping> switchMappings)
104102
type |= FastUpdates ? (uint)PinMameMechFlag.Fast : (uint)PinMameMechFlag.Slow;
105103
type |= ResultByLength ? (uint)PinMameMechFlag.LengthSw : (uint)PinMameMechFlag.StepSw;
106104

105+
var coilMapping1 = coilMappings.FirstOrDefault(cm => ReferenceEquals(cm.Device, this) && cm.DeviceItem == _solenoid1);
106+
var coilMapping2 = coilMappings.FirstOrDefault(cm => ReferenceEquals(cm.Device, this) && cm.DeviceItem == _solenoid2);
107+
107108
var mechConfig = new PinMameMechConfig(
108109
type,
109-
Solenoid1,
110-
Solenoid2,
110+
coilMapping1?.InternalId ?? 0,
111+
coilMapping2?.InternalId ?? 0,
111112
Length,
112113
Steps,
113114
0,
@@ -118,14 +119,27 @@ public PinMameMechConfig Config(List<SwitchMapping> switchMappings)
118119
foreach (var mark in Marks) {
119120
var switchMapping = switchMappings.FirstOrDefault(sm => ReferenceEquals(sm.Device, this) && sm.DeviceItem == mark.SwitchId);
120121
if (switchMapping == null) {
121-
Logger.Error($"Switch \"{mark.Description}\" for mech {name} is not mapped in the switch manager, ignoring.");
122+
Logger.Error($"Switch \"{mark.Name}\" for mech {name} is not mapped in the switch manager, ignoring.");
122123
continue;
123124
}
124-
mechConfig.AddSwitch(new PinMameMechSwitchConfig(switchMapping.InternalId, mark.StepBeginning, mark.StepEnd, mark.Pulse));
125-
}
126125

127-
return mechConfig;
126+
switch (mark.Type) {
127+
case MechMarkSwitchType.EnableBetween:
128+
mechConfig.AddSwitch(new PinMameMechSwitchConfig(switchMapping.InternalId, mark.StepBeginning, mark.StepEnd));
129+
break;
130+
131+
case MechMarkSwitchType.AlwaysPulse:
132+
mechConfig.AddSwitch(new PinMameMechSwitchConfig(switchMapping.InternalId, -mark.PulseFreq, mark.PulseDuration));
133+
break;
128134

135+
case MechMarkSwitchType.PulseBetween:
136+
mechConfig.AddSwitch(new PinMameMechSwitchConfig(switchMapping.InternalId, mark.StepBeginning, mark.StepEnd, mark.PulseFreq));
137+
break;
138+
default:
139+
throw new ArgumentOutOfRangeException();
140+
}
141+
}
142+
return mechConfig;
129143
}
130144

131145
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@@ -140,6 +154,32 @@ public PinMameMechConfig Config(List<SwitchMapping> switchMappings)
140154

141155
IEnumerable<GamelogicEngineSwitch> IDeviceComponent<GamelogicEngineSwitch>.AvailableDeviceItems => AvailableSwitches;
142156

157+
IEnumerable<IGamelogicEngineDeviceItem> IDeviceComponent<IGamelogicEngineDeviceItem>.AvailableDeviceItems => AvailableCoils;
158+
159+
public IEnumerable<IGamelogicEngineDeviceItem> AvailableWireDestinations => AvailableCoils;
160+
161+
IEnumerable<GamelogicEngineCoil> IDeviceComponent<GamelogicEngineCoil>.AvailableDeviceItems => AvailableCoils;
162+
163+
public IEnumerable<GamelogicEngineCoil> AvailableCoils {
164+
get {
165+
switch (Type)
166+
{
167+
case PinMameMechType.OneSolenoid:
168+
case PinMameMechType.OneDirectionalSolenoid:
169+
return new[] { new GamelogicEngineCoil(_solenoid1) { Description = "Mech Solenoid" } };
170+
case PinMameMechType.TwoDirectionalSolenoids:
171+
case PinMameMechType.TwoStepperSolenoids:
172+
case PinMameMechType.FourStepperSolenoids:
173+
return new[] {
174+
new GamelogicEngineCoil(_solenoid1) { Description = "Mech Solenoid 1" },
175+
new GamelogicEngineCoil(_solenoid2) { Description = "Mech Solenoid 2" },
176+
};
177+
default:
178+
throw new ArgumentOutOfRangeException();
179+
}
180+
}
181+
}
182+
143183
#endregion
144184

145185
#region Runtime
@@ -167,6 +207,14 @@ public void OnBeforeSerialize()
167207
{
168208
#if UNITY_EDITOR
169209

210+
if (string.IsNullOrEmpty(_solenoid1)) {
211+
_solenoid1 = GenerateCoilId();
212+
}
213+
if (string.IsNullOrEmpty(_solenoid2) || _solenoid1 == _solenoid2) {
214+
_solenoid2 = GenerateCoilId();
215+
}
216+
217+
170218
var switchIds = new HashSet<string>();
171219
foreach (var mark in Marks) {
172220
if (!mark.HasId || switchIds.Contains(mark.SwitchId)) {
@@ -181,6 +229,8 @@ public void OnAfterDeserialize()
181229
{
182230
}
183231

232+
private string GenerateCoilId() => $"coil_{Guid.NewGuid().ToString()[..8]}";
233+
184234
#endregion
185235
}
186236
}

0 commit comments

Comments
 (0)