diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a76a2721..eaf06b255 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,10 @@ ## Unreleased -Built with Unity 2021.2. +Built with Unity 2021.3.0 ### Added +- Scale support for rubbers. - Gate Lifter Component ([#418](https://github.com/freezy/VisualPinball.Engine/pull/418), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/lifting-gates.html)). - Asset Browser ([#412](https://github.com/freezy/VisualPinball.Engine/pull/412)) - Trigger meshes can now be easily scaled ([#374](https://github.com/freezy/VisualPinball.Engine/pull/374)) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs similarity index 95% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs index 5c016e9e2..639b762ac 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs @@ -26,7 +26,7 @@ namespace VisualPinball.Unity.Editor { - public partial class AssetBrowserX : EditorWindow, IDragHandler + public partial class AssetBrowser : EditorWindow, IDragHandler { [SerializeField] private int _thumbnailSize = 150; @@ -62,7 +62,7 @@ private AssetResult LastSelectedAsset { [MenuItem("Visual Pinball/Asset Browser")] public static void ShowWindow() { - var wnd = GetWindow(); + var wnd = GetWindow(); wnd.titleContent = new GUIContent("Asset Browser", Icons.AssetLibrary(IconSize.Small)); // Limit size of the window diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs.meta index a923a77c0..f66df1373 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8d98d4620f8776048a59fe0d28811083 +guid: 811805683b267144eb09cda5daf830e2 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss.meta similarity index 87% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss.meta index ed016fa45..cb69910eb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 98b5afa4f7306e04fb160371138d6662 +guid: c9d303c69a9d8af41a396f4a087e950b ScriptedImporter: internalIDToNameTable: [] externalObjects: {} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml.meta similarity index 86% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml.meta index f50e51df0..24e44dfbd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 466b5f13746a85b4ba3ed622cfc5198c +guid: 79510a21163b54e4c989c5d3eb346329 ScriptedImporter: internalIDToNameTable: [] externalObjects: {} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs similarity index 94% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs index 8d185d408..5b10e4faa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX_Init.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs @@ -21,7 +21,7 @@ namespace VisualPinball.Unity.Editor { - public partial class AssetBrowserX + public partial class AssetBrowser { private ToolbarButton _refreshButton; private ToolbarSearchField _queryInput; @@ -77,14 +77,14 @@ private string DragError { public void CreateGUI() { // import UXML - var visualTree = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uxml"); + var visualTree = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml"); visualTree.CloneTree(rootVisualElement); _assetTree = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryAssetElement.uxml"); var ui = rootVisualElement; // import style sheet - var styleSheet = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.uss"); + var styleSheet = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss"); ui.styleSheets.Add(styleSheet); // libraries diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs.meta index 5771d2a01..bc8726ab4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowserX.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 681ba8a5561dfea4497a01e5b5e1b801 +guid: 7c975a63030513841ba0c40d204d0f03 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetDetailsElement.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetDetailsElement.cs index 941b12647..aea81dd4f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetDetailsElement.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetDetailsElement.cs @@ -188,7 +188,7 @@ public void UpdateDetails() return; } - var browser = panel.visualTree.userData as AssetBrowserX; + var browser = panel.visualTree.userData as AssetBrowser; _object = _asset.Asset.Object; _titleElement.text = _asset.Asset.Name; _libraryElement.text = _asset.Library.Name; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetQuery.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetQuery.cs index 2c4c06d25..552177492 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetQuery.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetQuery.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Unity.Mathematics; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; @@ -49,7 +50,15 @@ public void Search(string q) { // parse attributes _attributes.Clear(); - foreach (var regex in new []{ new Regex(@"(\w+):(\w+)"), new Regex("\"([\\w\\s]+)\":(\\w+)"), new Regex("(\\w+):\"([\\w\\s]+)\""), new Regex("\"([\\w\\s]+)\":\"([\\w\\s]+)\"") }) { + const string quoted = "\"([\\w\\d\\s_-]+)\""; + const string nonQuoted = "([\\w\\d_-]+)"; + var regexes = new[] { + new Regex($"{nonQuoted}:{nonQuoted}"), + new Regex($"{quoted}:{nonQuoted}"), + new Regex($"{nonQuoted}:{quoted}"), + new Regex($"{quoted}:{quoted}") + }; + foreach (var regex in regexes) { foreach (Match match in regex.Matches(q)) { var key = match.Groups[1].Value; if (!_attributes.ContainsKey(key)) { @@ -151,6 +160,13 @@ public AssetResult(AssetLibrary library, LibraryAsset asset, long score) Score = score; } + public void AddScore(long score) + { + Score = Score < 0 + ? math.max(Score, score) + : math.max(Score, Score + score); + } + public void Save() { Library.SaveAsset(Asset); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/KeyValueElement.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/KeyValueElement.cs index 69655e1e6..38af2a224 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/KeyValueElement.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/KeyValueElement.cs @@ -38,7 +38,7 @@ public class KeyValueElement : VisualElement private readonly bool _isLink; private bool _isEditing; - private AssetBrowserX _browser; + private AssetBrowser _browser; private VisualElement DisplayContainer => _isLink ? _displayLinkElement : _displayElement; private Label DisplayElement => _isLink ? _linkElement : _nameElement; @@ -86,7 +86,7 @@ public KeyValueElement(AssetResult result, LibraryKeyValue keyValue, bool isLink private void OnAttached(AttachToPanelEvent evt) { - _browser = panel.visualTree.userData as AssetBrowserX; + _browser = panel.visualTree.userData as AssetBrowser; _valuesEditElement.RegisterCallback(OnAttributeValueFocus); Update(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryElement.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryElement.cs index f8a473b9f..1589ddf5a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryElement.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryElement.cs @@ -163,7 +163,7 @@ private void OnPointerUp(PointerUpEvent evt) private void OnDragEnterEvent(DragEnterEvent evt) { - if (AssetBrowserX.IsDraggingExistingAssets || AssetBrowserX.IsDraggingNewAssets) { + if (AssetBrowser.IsDraggingExistingAssets || AssetBrowser.IsDraggingNewAssets) { AddToClassList(ClassDrag); } else { return; @@ -198,7 +198,7 @@ private void OnDragEnterEvent(DragEnterEvent evt) private static void OnDragUpdatedEvent(DragUpdatedEvent evt) { - DragAndDrop.visualMode = AssetBrowserX.IsDraggingExistingAssets || AssetBrowserX.IsDraggingNewAssets + DragAndDrop.visualMode = AssetBrowser.IsDraggingExistingAssets || AssetBrowser.IsDraggingNewAssets ? DragAndDropVisualMode.Move : DragAndDropVisualMode.Rejected; } @@ -208,7 +208,7 @@ private void OnDragPerformEvent(DragPerformEvent evt) RemoveFromClassList(ClassDrag); if (_libraryCategoryView.DragError != null) { _libraryCategoryView.DragError = null; - AssetBrowserX.StopDraggingAssets(); + AssetBrowser.StopDraggingAssets(); return; } @@ -221,12 +221,12 @@ private void OnDragPerformEvent(DragPerformEvent evt) d.Library.SetCategory(d.Asset, category); } _libraryCategoryView.Refresh(); - AssetBrowserX.StopDraggingAssets(); + AssetBrowser.StopDraggingAssets(); return; } // drop from outside - if (AssetBrowserX.IsDraggingNewAssets) { + if (AssetBrowser.IsDraggingNewAssets) { _libraryCategoryView.AddAssets(DragAndDrop.paths, assetLibrary => Categories.FirstOrDefault(i => i.Item1 == assetLibrary).Item2 ??assetLibrary.AddCategory(Name)); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryView.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryView.cs index 5d635ad96..762a47e4b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryView.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryCategoryView.cs @@ -38,7 +38,7 @@ public string DragError { public void AddAssets(IEnumerable paths, Func getCategory) => _browser.AddAssets(paths, getCategory); - private AssetBrowserX _browser; + private AssetBrowser _browser; private AssetLibrary _activeLibrary; private readonly VisualElement _container; @@ -87,7 +87,7 @@ private string OnActiveLibraryChanged(string libraryName) return libraryName; } - public void Refresh(AssetBrowserX browser = null) + public void Refresh(AssetBrowser browser = null) { if (browser != null) { _browser = browser; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryDatabase.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryDatabase.cs index f7b64cd67..d65f60495 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryDatabase.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryDatabase.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Unity.Mathematics; using UnityEditor; using UnityEditor.Search; using UnityEngine; @@ -41,13 +42,16 @@ public IEnumerable GetAssets(AssetLibrary lib, LibraryQuery query) results = results .Select(result => { FuzzySearch.FuzzyMatch(query.Keywords, result.Asset.Object.name, ref result.Score); - /* todo fix search in tags and attributes. foreach (var tag in result.Asset.Tags) { - FuzzySearch.FuzzyMatch(query.Keywords, tag, ref result.Score); + var score = 0L; + FuzzySearch.FuzzyMatch(query.Keywords, tag, ref score); + result.AddScore(score); } foreach (var value in result.Asset.Attributes.SelectMany(values => values.Value.Split(","))) { - FuzzySearch.FuzzyMatch(query.Keywords, value, ref result.Score); - }*/ + var score = 0L; + FuzzySearch.FuzzyMatch(query.Keywords, value, ref score); + result.AddScore(score); + } return result; }) .Where(result => result.Score > 0); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/TagElement.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/TagElement.cs index 5527c0f31..7c197232c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/TagElement.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/TagElement.cs @@ -46,7 +46,7 @@ public bool IsActive { private readonly SearchSuggest _nameEditElement; private bool _isEditing; - private AssetBrowserX _browser; + private AssetBrowser _browser; public TagElement(AssetResult result, string value, SerializableHashSet values) { @@ -83,7 +83,7 @@ public TagElement(AssetResult result, string value, SerializableHashSet private void OnAttached(AttachToPanelEvent evt) { - _browser = panel.visualTree.userData as AssetBrowserX; + _browser = panel.visualTree.userData as AssetBrowser; } private void OnNameClicked(MouseDownEvent evt) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs index 154464504..669101cf1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs @@ -148,10 +148,11 @@ public GameObject Convert(bool applyPatch = true, string tableName = null) ExtractTextures(); ExtractSounds(); SaveData(); - SaveLegacyData(); var prefabLookup = InstantiateGameItems(); var componentLookup = UpdateGameItems(prefabLookup); + + SaveLegacyData(); // now we freed the binary data, write the remaining game items. FinalizeGameItems(componentLookup); FreeTextures(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SlingshotInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SlingshotInspector.cs index 28b327941..75874f5de 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SlingshotInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SlingshotInspector.cs @@ -30,7 +30,9 @@ public class SlingshotInspector : ItemInspector private SerializedProperty _animationDurationProperty; private SerializedProperty _animationCurveProperty; private SerializedProperty _coilArmProperty; - private SerializedProperty _coilArmAngleProperty; + private SerializedProperty _coilArmEndAngleProperty; + private SerializedProperty _coilArmStartAngleProperty; + private SerializedProperty _coilArmRotationAxis; protected override MonoBehaviour UndoTarget => target as MonoBehaviour; @@ -44,7 +46,9 @@ protected override void OnEnable() _rubberOffProperty = serializedObject.FindProperty(nameof(SlingshotComponent.RubberOff)); _rubberOnProperty = serializedObject.FindProperty(nameof(SlingshotComponent.RubberOn)); _coilArmProperty = serializedObject.FindProperty(nameof(SlingshotComponent.CoilArm)); - _coilArmAngleProperty = serializedObject.FindProperty(nameof(SlingshotComponent.CoilArmAngle)); + _coilArmStartAngleProperty = serializedObject.FindProperty(nameof(SlingshotComponent.CoilArmStartAngle)); + _coilArmEndAngleProperty = serializedObject.FindProperty(nameof(SlingshotComponent.CoilArmEndAngle)); + _coilArmRotationAxis = serializedObject.FindProperty(nameof(SlingshotComponent.CoilArmRotationAxis)); _animationDurationProperty = serializedObject.FindProperty(nameof(SlingshotComponent.AnimationDuration)); _animationCurveProperty = serializedObject.FindProperty(nameof(SlingshotComponent.AnimationCurve)); } @@ -66,7 +70,9 @@ public override void OnInspectorGUI() EditorGUILayout.Space(10f); PropertyField(_coilArmProperty, "Coil Arm"); - PropertyField(_coilArmAngleProperty, "Arm Angle"); + PropertyField(_coilArmStartAngleProperty, "Start Angle"); + PropertyField(_coilArmEndAngleProperty, "End Angle"); + PropertyField(_coilArmRotationAxis, "Rotation Axis"); EditorGUILayout.Space(10f); PropertyField(_animationDurationProperty, "Animation Duration"); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index dfc3d530a..73a32b030 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -277,7 +277,9 @@ private void HandleMoveTool() private void HandleScaleTool() { var e = Event.current; - if (e.type == EventType.MouseDown || e.type == EventType.MouseUp) { + var startScaling = e.type == EventType.MouseDown; + var endScaling = e.type == EventType.MouseUp; + if (startScaling || endScaling) { _scaleFactor = _primaryItem.GetEditorScale().x; } @@ -290,6 +292,14 @@ private void HandleScaleTool() } var handleRot = _transform.rotation; var handleScale = HandleUtility.GetHandleSize(handlePos); + + if (startScaling) { + _primaryItem.EditorStartScaling(); + } + if (endScaling) { + _primaryItem.EditorEndScaling(); + } + switch (_primaryItem.EditorScaleType) { case ItemDataTransformType.OneD: { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Rock.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Rock.cs index 1aa1bee06..676e6868f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Rock.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Rock.cs @@ -152,8 +152,8 @@ private static void SetupLeftSlingshot(GameObject go) ss.SlingshotSurface = go.GetComponent(); ss.RubberOff = playfieldGo.transform.Find("Rubbers/LeftSling1").GetComponent(); ss.RubberOn = playfieldGo.transform.Find("Rubbers/LeftSling4").GetComponent(); - ss.CoilArm = playfieldGo.transform.Find("Primitives/Lemk").GetComponent(); - ss.CoilArmAngle = 22f; + ss.CoilArm = playfieldGo.transform.Find("Primitives/Lemk").gameObject; + ss.CoilArmEndAngle = 22f; EditorUtility.SetDirty(ssGo); PrefabUtility.RecordPrefabInstancePropertyModifications(ss); @@ -173,8 +173,8 @@ private static void SetupRightSlingshot(GameObject go) ss.SlingshotSurface = go.GetComponent(); ss.RubberOff = playfieldGo.transform.Find("Rubbers/RightSling1").GetComponent(); ss.RubberOn = playfieldGo.transform.Find("Rubbers/RightSling3").GetComponent(); - ss.CoilArm = playfieldGo.transform.Find("Primitives/Remk").GetComponent(); - ss.CoilArmAngle = 22f; + ss.CoilArm = playfieldGo.transform.Find("Primitives/Remk").gameObject; + ss.CoilArmEndAngle = 22f; EditorUtility.SetDirty(ssGo); PrefabUtility.RecordPrefabInstancePropertyModifications(ss); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs index 9e5b5545f..6a76e97ae 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs @@ -52,6 +52,9 @@ public class Player : MonoBehaviour public event EventHandler OnUpdate; + public event EventHandler OnBallCreated; + public event EventHandler OnBallDestroyed; + [HideInInspector] [SerializeField] public string debugUiId; [HideInInspector] [SerializeField] public string physicsEngineId; @@ -485,6 +488,15 @@ public void OnEvent(in EventData eventData) } } + internal void BallCreated(Entity ballEntity, GameObject ball) + { + OnBallCreated?.Invoke(this, new BallEvent(ballEntity, ball)); + } + internal void BallDestroyed(Entity ballEntity, GameObject ball) + { + OnBallDestroyed?.Invoke(this, new BallEvent(ballEntity, ball)); + } + #endregion #region API @@ -579,4 +591,16 @@ private static void HandleInput(object obj, InputActionChange change) } } } + + public readonly struct BallEvent + { + public readonly Entity BallEntity; + public readonly GameObject Ball; + + public BallEvent(Entity ballEntity, GameObject ball) + { + BallEntity = ballEntity; + Ball = ball; + } + } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallManager.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallManager.cs index 467f528f0..218727484 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ball/BallManager.cs @@ -148,12 +148,17 @@ public void CreateEntity(GameObject ballGo, int id, in float3 worldPos, in float } NumBalls++; + + _player.BallCreated(entity, ballGo); } public void DestroyEntity(Entity ballEntity) { + var ballGo = _player.Balls[ballEntity]; + _player.BallDestroyed(ballEntity, ballGo); + // destroy game object - Object.DestroyImmediate(_player.Balls[ballEntity]); + Object.DestroyImmediate(ballGo); _player.Balls.Remove(ballEntity); // destroy entity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/CollidableApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/CollidableApi.cs index ffbc168b3..698bb6fed 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/CollidableApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/CollidableApi.cs @@ -28,10 +28,14 @@ public abstract class CollidableApi : I where TData : ItemData { public bool IsCollidable { - get => _simulateCycleSystemGroup.ItemsColliding[Entity]; - set => _simulateCycleSystemGroup.ItemsColliding[Entity] = value; + get => _simulateCycleSystemGroup != null && _simulateCycleSystemGroup.ItemsColliding[Entity]; + set { + if (_simulateCycleSystemGroup != null) { + _simulateCycleSystemGroup.ItemsColliding[Entity] = value; + } + } } - + protected readonly Entity Entity; protected readonly TCollidableComponent ColliderComponent; @@ -40,7 +44,9 @@ public bool IsCollidable { protected CollidableApi(GameObject go, Entity entity, Player player) : base(go, player) { - _simulateCycleSystemGroup = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem(); + if (World.DefaultGameObjectInjectionWorld != null) { + _simulateCycleSystemGroup = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem(); + } EntityManager = World.DefaultGameObjectInjectionWorld != null ? World.DefaultGameObjectInjectionWorld.EntityManager : default; Entity = entity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMainRenderableComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMainRenderableComponent.cs index 25cb22371..48526533b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMainRenderableComponent.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMainRenderableComponent.cs @@ -58,6 +58,8 @@ public interface IMainRenderableComponent : IMainComponent Entity Entity { get; set; } Vector3 GetEditorScale(); void SetEditorScale(Vector3 pos); + void EditorStartScaling(); + void EditorEndScaling(); } public enum ItemDataTransformType diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MainRenderableComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MainRenderableComponent.cs index 459a8ad07..44c9fb3ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/MainRenderableComponent.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MainRenderableComponent.cs @@ -164,6 +164,8 @@ public virtual void SetEditorRotation(Vector3 rot) { } public virtual ItemDataTransformType EditorScaleType => ItemDataTransformType.None; public virtual Vector3 GetEditorScale() => Vector3.zero; public virtual void SetEditorScale(Vector3 rot) { } + public virtual void EditorStartScaling() {} + public virtual void EditorEndScaling() {} #endregion } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberComponent.cs index bb91d96e3..1d50f8dcc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberComponent.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberComponent.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Math; @@ -51,6 +52,12 @@ public class RubberComponent : MainRenderableComponent, [SerializeField] private DragPointData[] _dragPoints; + [NonSerialized] + private float _scale = 1f; + + [NonSerialized] + private Vertex3D[] _scalingDragPoints; + #endregion #region IRubberData @@ -219,6 +226,31 @@ public override void SetEditorRotation(Vector3 rot) { RebuildMeshes(); } + public override void EditorStartScaling() + { + _scalingDragPoints = _dragPoints.Select(dp => dp.Center).ToArray(); + _scale = 1f; + } + + public override void EditorEndScaling() + { + _scalingDragPoints = null; + } + + public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; + public override Vector3 GetEditorScale() => new(_scale, 1f, 1f); + public override void SetEditorScale(Vector3 vScale) + { + var scale = 1 + (vScale.x - 1) / 5f; + _scale = scale; + var center = DragPointCenter.ToVertex3D(); + for (var i = 0; i < _dragPoints.Length; i++) { + _dragPoints[i].Center = center + scale * (_scalingDragPoints[i] - center); + } + + RebuildMeshes(); + } + #endregion } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SlingshotComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SlingshotComponent.cs index fda1a9888..b377ac0fe 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SlingshotComponent.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SlingshotComponent.cs @@ -22,12 +22,18 @@ using Unity.Entities; using Unity.Mathematics; using UnityEngine; +using UnityEngine.Serialization; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Rubber; using VisualPinball.Engine.Game.Engines; namespace VisualPinball.Unity { + public enum Axis + { + X, Y, Z + } + [AddComponentMenu("Visual Pinball/Game Item/Slingshot")] public class SlingshotComponent : MonoBehaviour, IMeshComponent, IMainRenderableComponent, IRubberData, ISwitchDeviceComponent { @@ -41,11 +47,19 @@ public class SlingshotComponent : MonoBehaviour, IMeshComponent, IMainRenderable public RubberComponent RubberOff; [Tooltip("Reference to the arm attached to the coil. Rotates around X.")] - public PrimitiveComponent CoilArm; + public GameObject CoilArm; + [Range(-180f, 180f)] + [Tooltip("Angle of the coil arm when off.")] + public float CoilArmStartAngle; + + [FormerlySerializedAs("CoilArmAngle")] [Range(-180f, 180f)] [Tooltip("Angle of the coil arm when on.")] - public float CoilArmAngle; + public float CoilArmEndAngle; + + [Tooltip("Which axis to rotate.")] + public Axis CoilArmRotationAxis; [Min(0f)] [Tooltip("Total duration of the animation in milliseconds.")] @@ -174,8 +188,18 @@ public void RebuildMeshes() } if (CoilArm) { - CoilArm.Rotation.x = CoilArmAngle * Position; - CoilArm.UpdateTransforms(); + var currentRot = CoilArm.transform.rotation.eulerAngles; + switch (CoilArmRotationAxis) { + case Axis.X: + CoilArm.transform.rotation = Quaternion.Euler(CoilArmStartAngle + CoilArmEndAngle * Position, currentRot.y, currentRot.z); + break; + case Axis.Y: + CoilArm.transform.rotation = Quaternion.Euler(currentRot.x, CoilArmStartAngle + CoilArmEndAngle * Position, currentRot.z); + break; + case Axis.Z: + CoilArm.transform.rotation = Quaternion.Euler(currentRot.x, currentRot.y, CoilArmStartAngle + CoilArmEndAngle * Position); + break; + } } } @@ -232,6 +256,8 @@ public void SetEditorRotation(Vector3 pos) { } public ItemDataTransformType EditorScaleType => ItemDataTransformType.None; public Vector3 GetEditorScale() => Vector3.one; public void SetEditorScale(Vector3 pos) { } + public void EditorStartScaling() { } + public void EditorEndScaling() { } #endregion