Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mechanical sound support part 3 #495

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
73accf8
initial commit
Mr-Jay-Gatsby Feb 13, 2023
00c4fa9
Individual component implements ISoundEmitter, starting with flipper …
Mr-Jay-Gatsby Feb 15, 2023
53e0bb5
Get the component that implements ISoundEmitter for pulling data to t…
Mr-Jay-Gatsby Feb 16, 2023
fc27912
SoundInspector updates including refactor playroundrobin and playrand…
Mr-Jay-Gatsby Feb 16, 2023
e0ba6a0
Further attempt to set pitch shifter value when testing sounds in the…
Mr-Jay-Gatsby Feb 18, 2023
78c0239
sound: Simplify sound asset and move play routine from inspector to a…
freezy Feb 18, 2023
3d4848e
sound: Refactor editor classes.
freezy Mar 1, 2023
f6291d1
sound: Get the runtime working.
freezy Mar 1, 2023
43a8233
sounds: Clean up obsolete stuff.
freezy Mar 1, 2023
54351aa
style: Some comments and re-ordering.
freezy Mar 1, 2023
2d5049b
Minor fix to sound asset, in order to handle when audio clips length …
Mr-Jay-Gatsby Mar 3, 2023
489705d
Initial audio fade implementation.
Mr-Jay-Gatsby Mar 21, 2023
207416d
Updated fade handling. Added sound handling to the following componen…
Mr-Jay-Gatsby Mar 30, 2023
09f4158
fix: UnityEditor reference.
freezy Jan 3, 2024
7b02f2a
implement Stop action
linojon Jan 4, 2024
a5fecdf
Dynamic audiosource for mechanical sound clips
linojon Jan 4, 2024
7612027
populate AudioMixer prop by searching parents
linojon Jan 5, 2024
3a746d9
added target sounds
linojon Jan 5, 2024
0ed3e81
Q to exit play mode
linojon Jan 5, 2024
86bc749
wip drop targets reset and score motor sounds
linojon Jan 8, 2024
c436b1a
trigger switch sounds
linojon Jan 5, 2024
d5cb350
attempt to do target bank reset sound
linojon Jan 5, 2024
3b895c2
Update DropTargetBankApi.cs
linojon Jan 5, 2024
d25ec19
wip drop targets reset and score motor sounds
linojon Jan 8, 2024
491b5c3
button to add MechSound with default volume=1
linojon Jan 30, 2024
25b528a
Apply default values to MechSound instances
arthurkehrwald Nov 25, 2024
b38ae1d
Fix UNT0026 warning
arthurkehrwald Nov 25, 2024
5416805
Remove unused variable
arthurkehrwald Nov 25, 2024
0187995
Do not change open scene when previewing sounds
arthurkehrwald Nov 25, 2024
0ffc529
DropTargetBankComponent doesn't inherit MainRenderableComponent
arthurkehrwald Nov 25, 2024
3bdfed2
Complete score motor sound support
arthurkehrwald Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions VisualPinball.Engine/VPT/MechSounds.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion VisualPinball.Unity/Assets/Presets.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions VisualPinball.Unity/VisualPinball.Unity.Editor/Sound.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Visual Pinball Engine
// Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.

using System.Linq;
using UnityEditor;
using UnityEngine;

namespace VisualPinball.Unity.Editor
{
[CustomPropertyDrawer(typeof(MechSound))]
public class MechSoundDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing) * 5 + 4f;
}

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// retrieve reference to GO and component
var mechSoundsComponent = (MechSoundsComponent)property.serializedObject.targetObject;
var soundEmitter = mechSoundsComponent.GetComponent<ISoundEmitter>();

EditorGUI.BeginProperty(position, label, property);

// init height
position.height = EditorGUIUtility.singleLineHeight;

// trigger drop-down
var triggerIdProperty = property.FindPropertyRelative(nameof(MechSound.TriggerId));
var triggers = soundEmitter.AvailableTriggers;
if (triggers.Length > 0) {
var triggerIndex = triggers.ToList().FindIndex(t => t.Id == triggerIdProperty.stringValue);
if (triggerIndex == -1) { // pre-select first trigger in list, if none set.
triggerIndex = 0;
}
triggerIndex = EditorGUI.Popup(position, "Trigger on", triggerIndex, triggers.Select(t => t.Name).ToArray());
triggerIdProperty.stringValue = triggers[triggerIndex].Id;
} else {
EditorGUI.LabelField(position, "No Triggers found.");
}
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

// sound object picker
var soundProperty = property.FindPropertyRelative(nameof(MechSound.Sound));
EditorGUI.BeginChangeCheck();
var soundValue = EditorGUI.ObjectField(position, "Sound", soundProperty.objectReferenceValue, typeof(SoundAsset), true);
if (EditorGUI.EndChangeCheck()) {
soundProperty.objectReferenceValue = soundValue;
}
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

// volume
var volumeProperty = property.FindPropertyRelative(nameof(MechSound.Volume));
EditorGUI.PropertyField(position, volumeProperty);
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

// action
var actionProperty = property.FindPropertyRelative(nameof(MechSound.Action));
EditorGUI.PropertyField(position, actionProperty);
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

// fade
var fadeProperty = property.FindPropertyRelative(nameof(MechSound.Fade));
EditorGUI.PropertyField(position, fadeProperty);
position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

EditorGUI.EndProperty();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Visual Pinball Engine
// Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.

using UnityEditor;
using UnityEngine;

namespace VisualPinball.Unity.Editor
{
[CustomEditor(typeof(MechSoundsComponent)), CanEditMultipleObjects]
public class MechanicalSoundInspector : UnityEditor.Editor
{
private SerializedProperty _audioMixerProperty;
private SerializedProperty _soundsProperty;

private void OnEnable()
{
_audioMixerProperty = serializedObject.FindProperty(nameof(MechSoundsComponent.AudioMixer));
_soundsProperty = serializedObject.FindProperty(nameof(MechSoundsComponent.Sounds));
}

public override void OnInspectorGUI()
{
var comp = target as MechSoundsComponent;
if (!comp!.TryGetComponent<ISoundEmitter>(out _)) {
EditorGUILayout.HelpBox("Cannot find sound emitter. This component only works with a sound emitter on the same GameObject.", MessageType.Error);
return;
}

serializedObject.Update();

EditorGUILayout.PropertyField(_soundsProperty);
EditorGUILayout.PropertyField(_audioMixerProperty);

serializedObject.ApplyModifiedProperties();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Visual Pinball Engine
// Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.

using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace VisualPinball.Unity.Editor
{
[CustomEditor(typeof(SoundAsset)), CanEditMultipleObjects]
public class SoundAssetInspector : UnityEditor.Editor
{
private SerializedProperty _nameProperty;
private SerializedProperty _descriptionProperty;
private SerializedProperty _volumeCorrectionProperty;
private SerializedProperty _clipsProperty;
private SerializedProperty _clipSelectionProperty;
private SerializedProperty _randomizePitchProperty;
private SerializedProperty _randomizeVolumeProperty;
private SerializedProperty _loopProperty;

private SoundAsset _soundAsset;

private AudioSource _editorAudioSource;
//private AudioMixer _editorAudioMixer;

private const float ButtonHeight = 30;
private const float ButtonWidth = 50;

private void OnEnable()
{
_nameProperty = serializedObject.FindProperty(nameof(SoundAsset.Name));
_descriptionProperty = serializedObject.FindProperty(nameof(SoundAsset.Description));
_volumeCorrectionProperty = serializedObject.FindProperty(nameof(SoundAsset.VolumeCorrection));
_clipsProperty = serializedObject.FindProperty(nameof(SoundAsset.Clips));
_clipSelectionProperty = serializedObject.FindProperty(nameof(SoundAsset.ClipSelection));
_randomizePitchProperty = serializedObject.FindProperty(nameof(SoundAsset.RandomizePitch));
_randomizeVolumeProperty = serializedObject.FindProperty(nameof(SoundAsset.RandomizeVolume));
_loopProperty = serializedObject.FindProperty(nameof(SoundAsset.Loop));

_editorAudioSource = GetOrCreateAudioSource();
//_editorAudioMixer = AssetDatabase.LoadAssetAtPath<AudioMixer>("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/Assets/Resources/EditorMixer.mixer");
//_editorAudioSource.outputAudioMixerGroup = _editorAudioMixer.outputAudioMixerGroup;

_soundAsset = target as SoundAsset;
}

public override void OnInspectorGUI()
{
serializedObject.Update();

EditorGUILayout.PropertyField(_nameProperty, true);

using (var horizontalScope = new GUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(_descriptionProperty, GUILayout.Height(100));
}

EditorGUILayout.PropertyField(_volumeCorrectionProperty, true);
EditorGUILayout.PropertyField(_clipsProperty);
EditorGUILayout.PropertyField(_clipSelectionProperty, true);
EditorGUILayout.PropertyField(_randomizePitchProperty, true);
EditorGUILayout.PropertyField(_randomizeVolumeProperty, true);
EditorGUILayout.PropertyField(_loopProperty);

serializedObject.ApplyModifiedProperties();

// center button
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (PlayStopButton()) {
PlayStop();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}

private void PlayStop()
{
if (_editorAudioSource.isPlaying) {
_soundAsset.Stop(_editorAudioSource);
} else {
_soundAsset.Play(_editorAudioSource);
}
}

private bool PlayStopButton()
{
return _editorAudioSource.isPlaying
? GUILayout.Button(new GUIContent("Stop", Icons.StopButton(IconSize.Small, IconColor.Orange)),
GUILayout.Height(ButtonHeight), GUILayout.Width(ButtonWidth))
: GUILayout.Button(new GUIContent("Play", Icons.PlayButton(IconSize.Small, IconColor.Orange)),
GUILayout.Height(ButtonHeight), GUILayout.Width(ButtonWidth));
}

/// <summary>
/// Gets or creates the AudioSource for playing sounds in the editor.
/// The object containing the AudioSource is created in a new, additively loaded scene
/// to avoid making changes to the user's currently open scene.
/// </summary>
/// <returns>AudioSource for previewing audio assets in the editor</returns>
private static AudioSource GetOrCreateAudioSource()
{
Scene editorScene = GetOrCreatePreviewScene();
GameObject editorAudio = GetOrCreatePreviewAudioObject(editorScene);
if (!editorAudio.TryGetComponent<AudioSource>(out var audioSource)) {
audioSource = editorAudio.AddComponent<AudioSource>();
}
return audioSource;
}

private static Scene GetOrCreatePreviewScene()
{
const string sceneName = "VpeEditorScene";

for (int i = 0; i < SceneManager.loadedSceneCount; i++) {
Scene scene = SceneManager.GetSceneAt(i);
if (scene.name == sceneName)
return scene;
}

Scene previewScene = EditorSceneManager.NewPreviewScene();
previewScene.name = sceneName;
return previewScene;
}

private static GameObject GetOrCreatePreviewAudioObject(Scene previewScene)
{
const string audioObjName = "AudioPreview";

var audioObj = previewScene.GetRootGameObjects()
.FirstOrDefault(go => go.name == audioObjName);

if (audioObj == null) {
audioObj = new GameObject(audioObjName);
SceneManager.MoveGameObjectToScene(audioObj, previewScene);
}

return audioObj;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading