Skip to content

Commit a31d2af

Browse files
authored
Merge pull request #46 from futureboxsystems/feature/media-controller
Media controller
2 parents 6659002 + 6178eec commit a31d2af

File tree

228 files changed

+6276
-221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

228 files changed

+6276
-221
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Visual Pinball Engine
2+
// Copyright (C) 2025 freezy and VPE Team
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10+
// SOFTWARE.
11+
12+
using UnityEditor;
13+
using UnityEngine;
14+
using UnityEngine.UIElements;
15+
using VisualPinball.Engine.Mpf.Unity.MediaController.Sound;
16+
using VisualPinball.Unity.Editor;
17+
18+
namespace VisualPinball.Engine.Mpf.Unity.Editor
19+
{
20+
[CustomEditor(typeof(MpfEventSound)), CanEditMultipleObjects]
21+
public class MpfEventSoundInspector : SoundComponentInspector
22+
{
23+
[SerializeField]
24+
private VisualTreeAsset mpfEventSoundInspectorXml;
25+
26+
public override VisualElement CreateInspectorGUI()
27+
{
28+
var root = base.CreateInspectorGUI();
29+
var inspectorUi = mpfEventSoundInspectorXml.Instantiate();
30+
root.Add(inspectorUi);
31+
return root;
32+
}
33+
}
34+
}

Editor/Inspector/MpfEventSoundInspector.cs.meta

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
2+
<uie:PropertyField binding-path="_eventName" label="Event" tooltip="The name of the MPF event that should trigger the sound" />
3+
</ui:UXML>

Editor/Inspector/MpfEventSoundInspector.uxml.meta

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Editor/Inspector/MpfGamelogicEngineInspector.cs

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
using System.Linq;
1818
using System.Threading;
1919
using Grpc.Core;
20-
using Mono.Cecil;
2120
using UnityEditor;
2221
using UnityEditor.UIElements;
2322
using UnityEngine;
2423
using UnityEngine.UIElements;
24+
using VisualPinball.Engine.Mpf.Unity.MediaController;
2525
using VisualPinball.Unity;
2626

2727
namespace VisualPinball.Engine.Mpf.Unity.Editor
@@ -38,6 +38,9 @@ public class MpfGamelogicEngineInspector : UnityEditor.Editor
3838
private PropertyField _connectDelayField;
3939
private VisualElement _commandLineOptionsContainer;
4040
private VisualElement _startupBehaviorOptionsContainer;
41+
private TextField _mpfStateField;
42+
private TextField _mediaControllerStateField;
43+
private VisualElement _bcpOptionsContainer;
4144

4245
public override VisualElement CreateInspectorGUI()
4346
{
@@ -63,12 +66,9 @@ public override VisualElement CreateInspectorGUI()
6366

6467
if (!string.IsNullOrWhiteSpace(path))
6568
{
66-
path = path.Replace("\\", "/");
67-
if (path.Contains("StreamingAssets/"))
68-
path = "./StreamingAssets/" + path.Split("StreamingAssets/")[1];
69-
69+
path = MpfWranglerOptions.RealPathToSerializedPath(path);
7070
var machineFolderProp = serializedObject.FindProperty(
71-
$"_mpfWrangler._machineFolder"
71+
$"_wranglerOptions._machineFolder"
7272
);
7373
machineFolderProp.stringValue = path;
7474
serializedObject.ApplyModifiedProperties();
@@ -77,21 +77,21 @@ public override VisualElement CreateInspectorGUI()
7777
);
7878

7979
var getDescBtn = root.Q<Button>("get-machine-description");
80-
var optionsBox = root.Q<GroupBox>("options");
80+
var optionsBox = root.Q<VisualElement>("options");
8181
if (Application.isPlaying)
8282
getDescBtn.SetEnabled(false);
8383

8484
var getDescBtnDefaultText = getDescBtn.text;
8585

8686
getDescBtn.clicked += async () =>
8787
{
88-
Undo.RecordObject(_mpfEngine, "Get machine description");
89-
PrefabUtility.RecordPrefabInstancePropertyModifications(_mpfEngine);
9088
if (_getMachineDescCts == null)
9189
{
92-
_getMachineDescCts = new CancellationTokenSource();
90+
Undo.RecordObject(_mpfEngine, "Get machine description");
91+
PrefabUtility.RecordPrefabInstancePropertyModifications(_mpfEngine);
9392
getDescBtn.text = "Cancel";
9493
optionsBox.SetEnabled(false);
94+
_getMachineDescCts = new CancellationTokenSource();
9595

9696
try
9797
{
@@ -110,17 +110,15 @@ ex is RpcException exception
110110
{
111111
optionsBox.SetEnabled(true);
112112
getDescBtn.text = getDescBtnDefaultText;
113+
getDescBtn.SetEnabled(true);
113114
_getMachineDescCts?.Dispose();
114115
_getMachineDescCts = null;
115116
}
116117
}
117118
else
118119
{
120+
getDescBtn.SetEnabled(false);
119121
_getMachineDescCts?.Cancel();
120-
_getMachineDescCts?.Dispose();
121-
_getMachineDescCts = null;
122-
optionsBox.SetEnabled(true);
123-
getDescBtn.text = getDescBtnDefaultText;
124122
}
125123
};
126124

@@ -133,7 +131,8 @@ ex is RpcException exception
133131
if (
134132
EditorUtility.DisplayDialog(
135133
"Mission Pinball Framework",
136-
"This will clear all linked switches, coils and lamps and re-populate them. Are you sure you want to do that?",
134+
"This will clear all linked switches, coils and lamps and re-populate "
135+
+ "them. Are you sure you want to do that?",
137136
"Yes",
138137
"No"
139138
)
@@ -177,7 +176,7 @@ ex is RpcException exception
177176

178177
var startupBehaviorField = root.Q<PropertyField>("startup-behavior");
179178
var startupBehaviorProp = serializedObject.FindProperty(
180-
"_mpfWrangler._startupBehavior"
179+
"_wranglerOptions._startupBehavior"
181180
);
182181
_connectTimeoutField = root.Q<PropertyField>("connect-timeout");
183182
_connectDelayField = root.Q<PropertyField>("connect-delay");
@@ -188,7 +187,7 @@ ex is RpcException exception
188187
_commandLineOptionsContainer = root.Q<VisualElement>("command-line-options");
189188
_startupBehaviorOptionsContainer = root.Q<VisualElement>("startup-behavior-options");
190189
var executableSourceProp = serializedObject.FindProperty(
191-
"_mpfWrangler._executableSource"
190+
"_wranglerOptions._executableSource"
192191
);
193192
OnExecutableSourceChanged(executableSourceProp);
194193
_commandLineOptionsContainer.TrackPropertyValue(
@@ -198,11 +197,31 @@ ex is RpcException exception
198197

199198
MachineFolderValidationBoxes(machineFolderField);
200199

200+
_mpfStateField = root.Q<TextField>("mpf-state");
201+
UpdateMpfStateField(_mpfEngine.MpfState);
202+
_mpfEngine.MpfStateChanged += OnMpfStateChanged;
203+
204+
_mediaControllerStateField = root.Q<TextField>("media-controller-state");
205+
UpdateBcpStateField(_mpfEngine.BcpState);
206+
_mpfEngine.BcpStateChanged += OnBcpStateChanged;
207+
208+
_bcpOptionsContainer = root.Q<VisualElement>("bcp-options");
209+
var mediaControllerProp = serializedObject.FindProperty(
210+
"_wranglerOptions._mediaController"
211+
);
212+
UpdateMediaControllerUiVisibility(mediaControllerProp);
213+
_bcpOptionsContainer.TrackPropertyValue(
214+
mediaControllerProp,
215+
UpdateMediaControllerUiVisibility
216+
);
217+
201218
return root;
202219
}
203220

204221
private void OnDisable()
205222
{
223+
_mpfEngine.MpfStateChanged -= OnMpfStateChanged;
224+
_mpfEngine.BcpStateChanged -= OnBcpStateChanged;
206225
_getMachineDescCts?.Cancel();
207226
_getMachineDescCts?.Dispose();
208227
_getMachineDescCts = null;
@@ -259,9 +278,42 @@ private void UpdateGameItemList(VisualElement parent, IEnumerable<string> itemId
259278
}
260279
}
261280

281+
private void OnMpfStateChanged(object sender, StateChangedEventArgs<MpfState> args)
282+
{
283+
UpdateMpfStateField(args.CurrentState);
284+
}
285+
286+
private void UpdateMpfStateField(MpfState state)
287+
{
288+
_mpfStateField.value = state.ToString();
289+
}
290+
291+
private void OnBcpStateChanged(
292+
object sender,
293+
StateChangedEventArgs<BcpConnectionState> args
294+
)
295+
{
296+
UpdateBcpStateField(args.CurrentState);
297+
}
298+
299+
private void UpdateBcpStateField(BcpConnectionState state)
300+
{
301+
_mediaControllerStateField.value = state.ToString();
302+
}
303+
304+
private void UpdateMediaControllerUiVisibility(SerializedProperty mediaControllerProp)
305+
{
306+
var mediaController = (MpfMediaController)mediaControllerProp.enumValueIndex;
307+
var usingIncludedMediaController = mediaController == MpfMediaController.Included;
308+
_mediaControllerStateField.SetEnabled(usingIncludedMediaController);
309+
_bcpOptionsContainer.SetEnabled(usingIncludedMediaController);
310+
}
311+
262312
private void MachineFolderValidationBoxes(VisualElement machineFolderField)
263313
{
264-
var machineFolderProp = serializedObject.FindProperty($"_mpfWrangler._machineFolder");
314+
var machineFolderProp = serializedObject.FindProperty(
315+
"_wranglerOptions._machineFolder"
316+
);
265317
var notAMachineFolderErrorBox = new HelpBox(
266318
"The machine folder is not valid. It must contain a folder called 'config' "
267319
+ "with at least one .yaml file inside.",
@@ -281,7 +333,9 @@ private void MachineFolderValidationBoxes(VisualElement machineFolderField)
281333

282334
void UpdateVisibility(SerializedProperty _)
283335
{
284-
var machineFolder = _mpfEngine.MachineFolder;
336+
var options = (MpfWranglerOptions)
337+
serializedObject.FindProperty("_wranglerOptions").boxedValue;
338+
var machineFolder = options.MachineFolder;
285339
var isMachineFolderInStreamingAssets = machineFolder.StartsWith(
286340
Application.streamingAssetsPath
287341
);

0 commit comments

Comments
 (0)