diff --git a/CHANGELOG.md b/CHANGELOG.md index 91eb9c8f3..d6fa99ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased ### Changes + +- [UUM-131032] Added a reset of static variables when entering playmode to allow fast enter playmode compatibility. - [UUM-138960] Removed a large utility dictionary to reduce binary size and runtime memory overhead. ### Fixed diff --git a/Debug/Scripts/ShowHoveredInfo.cs b/Debug/Scripts/ShowHoveredInfo.cs index 5e467714d..1e58e9fad 100644 --- a/Debug/Scripts/ShowHoveredInfo.cs +++ b/Debug/Scripts/ShowHoveredInfo.cs @@ -10,6 +10,14 @@ public class ShowHoveredInfo : MonoBehaviour static Material m_Material; bool m_IsHovering; +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod] + static void ResetStaticsOnLoad() + { + m_Material = null; + } +#endif + void Start() { if (m_Material == null) diff --git a/Editor/EditorCore/CutTool.cs b/Editor/EditorCore/CutTool.cs index 7f44d05fe..76f3f2ae1 100644 --- a/Editor/EditorCore/CutTool.cs +++ b/Editor/EditorCore/CutTool.cs @@ -201,6 +201,7 @@ public override void OnActivated() Undo.undoRedoPerformed += UndoRedoPerformed; MeshSelection.objectSelectionChanged += UpdateTarget; ProBuilderEditor.selectModeChanged += OnSelectModeChanged; + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } public override void OnWillBeDeactivated() @@ -210,6 +211,7 @@ public override void OnWillBeDeactivated() Undo.undoRedoPerformed -= UndoRedoPerformed; MeshSelection.objectSelectionChanged -= UpdateTarget; ProBuilderEditor.selectModeChanged -= OnSelectModeChanged; + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; } /// @@ -242,6 +244,16 @@ void ExitTool() ToolManager.RestorePreviousTool(); } + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingEditMode || state == PlayModeStateChange.ExitingPlayMode) + { + // Reset tool state when entering/exiting playmode + if (ToolManager.IsActiveTool(this)) + ExitTool(); + } + } + /// /// Undo/Redo callback: Reset and recompute lines, and update the targeted face if needed /// diff --git a/Editor/EditorCore/DrawShapeTool.cs b/Editor/EditorCore/DrawShapeTool.cs index 8ad2c37e2..d59e4424d 100644 --- a/Editor/EditorCore/DrawShapeTool.cs +++ b/Editor/EditorCore/DrawShapeTool.cs @@ -723,6 +723,7 @@ public override void OnActivated() ToolManager.activeToolChanged += OnActiveToolChanged; ToolManager.activeContextChanged += OnActiveContextChanged; ProBuilderEditor.selectModeChanged += OnSelectModeChanged; + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; if (m_CurrentState == null) m_CurrentState = InitStateMachine(); @@ -741,6 +742,7 @@ public override void OnWillBeDeactivated() ToolManager.activeToolChanged -= OnActiveToolChanged; ToolManager.activeContextChanged -= OnActiveContextChanged; ProBuilderEditor.selectModeChanged -= OnSelectModeChanged; + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; if (m_ProBuilderShape != null && !( m_CurrentState is ShapeState_InitShape )) m_CurrentState = ShapeState.ResetState(); @@ -766,6 +768,19 @@ void OnActiveContextChanged() ToolManager.RestorePreviousPersistentTool(); } + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingEditMode || state == PlayModeStateChange.ExitingPlayMode) + { + // Reset tool state when entering/exiting playmode + if (ToolManager.IsActiveTool(this)) + { + m_CurrentState = ShapeState.ResetState(); + ToolManager.RestorePreviousPersistentTool(); + } + } + } + void HandleUndoRedoPerformed() { if(ToolManager.IsActiveTool(this)) diff --git a/Editor/EditorCore/EditShapeTool.cs b/Editor/EditorCore/EditShapeTool.cs index 885ba843f..b81886400 100644 --- a/Editor/EditorCore/EditShapeTool.cs +++ b/Editor/EditorCore/EditShapeTool.cs @@ -94,6 +94,30 @@ static Vector3[][] arrowsLines } } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Faces = null; + s_CurrentId = -1; + s_SizeManipulationInit = false; + s_SizeDelta = 0f; + s_StartMousePosition = Vector2.zero; + s_StartSize = Vector3.zero; + s_StartPositionLocal = Vector3.zero; + s_StartPositionGlobal = Vector3.zero; + s_StartScale = Vector3.zero; + s_StartScaleInverse = Vector3.zero; + s_StartCenter = Vector3.zero; + s_Direction = Vector3.zero; + s_DefaultMidpointHandleSize = 0.03f; + s_DefaultMidpointSquareSize = 0.15f; + s_CurrentAngle = 0f; + s_CurrentArrowHovered = -1; + s_ShapeRotation = Quaternion.identity; + s_ArrowsLines = null; + s_IconContent = null; + } + public override bool gridSnapEnabled => true; static GUIContent s_IconContent; diff --git a/Editor/EditorCore/EditorGUILayout.cs b/Editor/EditorCore/EditorGUILayout.cs index 31ec42060..17ebf11dc 100644 --- a/Editor/EditorCore/EditorGUILayout.cs +++ b/Editor/EditorCore/EditorGUILayout.cs @@ -195,6 +195,14 @@ static Rect ResizeTopRight(Rect currentRect, ResizeHandleState handleState, Even static int s_ResizeHandleAreaDimension = 6; static int s_MoveWindowAreaHeight = 30; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_RowToggle = true; + s_ResizeHandleAreaDimension = 6; + s_MoveWindowAreaHeight = 30; + } + public static Rect DoResizeHandle(Rect rect, int minimumWidth, int minimumHeight) { var evt = Event.current; diff --git a/Editor/EditorCore/EditorGUIUtility.cs b/Editor/EditorCore/EditorGUIUtility.cs index df15a4a45..f4a2d611a 100644 --- a/Editor/EditorCore/EditorGUIUtility.cs +++ b/Editor/EditorCore/EditorGUIUtility.cs @@ -45,6 +45,15 @@ public static void Init() : new GUIContent("FCE", "Face Selection"), }; } + + internal static void ResetForPlayMode() + { + selectModeIcons = null; + s_ObjectIcon = null; + s_VertexIcon = null; + s_EdgeIcon = null; + s_FaceIcon = null; + } } static readonly Color TOOL_SETTINGS_COLOR = UnityEditor.EditorGUIUtility.isProSkin @@ -469,6 +478,18 @@ static GUIStyle sceneBoldLabel static GUIStyle _sceneBoldLabel = null; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + Styles.ResetForPlayMode(); + _splitStyle = null; + _centeredGreyMiniLabel = null; + _solidBackgroundStyle = null; + _buttonNoBackgroundSmallMarginStyle = null; + _sceneBoldLabel = null; + sceneLabelRect = new Rect(0f, 0f, 0f, 0f); + } + /** * Draw a label in the scene view with a solid color background. */ diff --git a/Editor/EditorCore/EditorHandleDrawing.cs b/Editor/EditorCore/EditorHandleDrawing.cs index e30fb8c23..77380408f 100644 --- a/Editor/EditorCore/EditorHandleDrawing.cs +++ b/Editor/EditorCore/EditorHandleDrawing.cs @@ -200,17 +200,36 @@ static void Init() ResetPreferences(); } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + ReleaseResources(); + s_Initialized = false; + s_WireHandles = null; + s_VertexHandles = null; + s_SelectedFaceHandles = null; + s_SelectedVertexHandles = null; + s_SelectedEdgeHandles = null; + s_TemporaryHandles = null; + } + internal static void ReleaseResources() { ClearHandles(); - if(s_MeshPool2 != null) - s_MeshPool2.Dispose(); - if(s_EdgeMaterial != null) UnityObject.DestroyImmediate(s_EdgeMaterial); - if(s_WireMaterial != null) UnityObject.DestroyImmediate(s_WireMaterial); - if(s_LineMaterial != null) UnityObject.DestroyImmediate(s_LineMaterial); - if(s_VertMaterial != null) UnityObject.DestroyImmediate(s_VertMaterial); - if(s_GlWireMaterial != null) UnityObject.DestroyImmediate(s_GlWireMaterial); - if(s_FaceMaterial != null) UnityObject.DestroyImmediate(s_FaceMaterial); + if (s_MeshPool2 != null) s_MeshPool2.Dispose(); + if (s_FaceMaterial != null) UnityObject.DestroyImmediate(s_FaceMaterial); + if (s_EdgeMaterial != null) UnityObject.DestroyImmediate(s_EdgeMaterial); + if (s_VertMaterial != null) UnityObject.DestroyImmediate(s_VertMaterial); + if (s_WireMaterial != null) UnityObject.DestroyImmediate(s_WireMaterial); + if (s_LineMaterial != null) UnityObject.DestroyImmediate(s_LineMaterial); + if (s_GlWireMaterial != null) UnityObject.DestroyImmediate(s_GlWireMaterial); + s_MeshPool2 = null; + s_FaceMaterial = null; + s_EdgeMaterial = null; + s_VertMaterial = null; + s_WireMaterial = null; + s_LineMaterial = null; + s_GlWireMaterial = null; } internal static void ResetPreferences() diff --git a/Editor/EditorCore/EditorHandleUtility.cs b/Editor/EditorCore/EditorHandleUtility.cs index e90b43597..c22ea25fd 100644 --- a/Editor/EditorCore/EditorHandleUtility.cs +++ b/Editor/EditorCore/EditorHandleUtility.cs @@ -67,6 +67,19 @@ public static Material handleMaterial public static int CurrentID { get { return currentId; } } static int currentId = -1; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + if (s_HandleMaterial != null) + Object.DestroyImmediate(s_HandleMaterial); + s_HandleMaterial = null; + currentId = -1; + s_HandleMatrix.Clear(); + handleOffset = Vector2.zero; + initialMousePosition = Vector2.zero; + axisConstraint = new HandleConstraint2D(0, 0); + } + static Vector2 handleOffset = Vector2.zero; static Vector2 initialMousePosition = Vector2.zero; diff --git a/Editor/EditorCore/EditorSceneViewPicker.cs b/Editor/EditorCore/EditorSceneViewPicker.cs index dfc1c5f46..1085e1dad 100644 --- a/Editor/EditorCore/EditorSceneViewPicker.cs +++ b/Editor/EditorCore/EditorSceneViewPicker.cs @@ -33,6 +33,18 @@ static class EditorSceneViewPicker // When enabled, a mouse click on an unselected mesh will select both the GameObject and the mesh element picked. const bool k_AllowUnselected = true; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_DeepSelectionPrevious = 0x0; + s_AppendModifierPreviousState = false; + s_Selection.Clear(); + s_NearestVertices.Clear(); + s_OverlappingGameObjects.Clear(); + s_IndexBuffer.Clear(); + s_EdgeBuffer.Clear(); + } + public static void DoMouseHover(SceneSelection selection) { if (selection.faces.Count == 0) diff --git a/Editor/EditorCore/EditorShapeUtility.cs b/Editor/EditorCore/EditorShapeUtility.cs index 457b4e940..1f0562e09 100644 --- a/Editor/EditorCore/EditorShapeUtility.cs +++ b/Editor/EditorCore/EditorShapeUtility.cs @@ -103,6 +103,14 @@ public static List shapeTypesGUI } } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_AvailableShapeTypes = null; + s_ShapeTypes = null; + s_ShapeTypesGUILists = null; + } + static EditorShapeUtility() { ResetPrefs(); diff --git a/Editor/EditorCore/EditorStyles.cs b/Editor/EditorCore/EditorStyles.cs index 765821229..2321e41eb 100644 --- a/Editor/EditorCore/EditorStyles.cs +++ b/Editor/EditorCore/EditorStyles.cs @@ -28,6 +28,12 @@ static class EditorStyles static GUIStyle s_HeaderLabel; static GUIStyle s_SceneTextBox; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Initialized = false; + } + public static GUIStyle buttonStyle { get { Init(); return s_ButtonStyle; } } public static GUIStyle toolbarHelpIcon { get { Init(); return s_ToolbarHelpIcon; } } public static GUIStyle settingsGroup { get { Init(); return s_SettingsGroup; } } diff --git a/Editor/EditorCore/EditorUtility.cs b/Editor/EditorCore/EditorUtility.cs index ea192dd73..d32dc0704 100644 --- a/Editor/EditorCore/EditorUtility.cs +++ b/Editor/EditorCore/EditorUtility.cs @@ -28,6 +28,22 @@ public static class EditorUtility static EditorWindow s_NotificationWindow; static bool s_IsNotificationDisplayed; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_IsNotificationDisplayed = false; + EditorApplication.update -= NotifUpdate; + if (s_NotificationWindow != null) + { + // Window may be destroyed when entering Play Mode without domain reload. + try { s_NotificationWindow.RemoveNotification(); } + catch {} + } + + s_NotificationWindow = null; + s_NotificationTimer = 0f; + } + [UserSetting("General", "Show Action Notifications", "Enable or disable notification popups when performing actions.")] static Pref s_ShowNotifications = new Pref("editor.showEditorNotifications", false); diff --git a/Editor/EditorCore/IconUtility.cs b/Editor/EditorCore/IconUtility.cs index ca8149266..1d0058f18 100644 --- a/Editor/EditorCore/IconUtility.cs +++ b/Editor/EditorCore/IconUtility.cs @@ -20,6 +20,12 @@ static class IconUtility static string s_IconFolderPath = "Packages/com.unity.probuilder/Editor Default Resources/Icons/"; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Icons.Clear(); + } + /// /// Load an icon from icons folder located in the package's 'Editor Default Resources'. /// Naming convention is: "path/to/iconName" (without extension). Use the 'd_' prefix for dark skin icons. diff --git a/Editor/EditorCore/Lightmapping.cs b/Editor/EditorCore/Lightmapping.cs index d360a9edb..fb06e092f 100644 --- a/Editor/EditorCore/Lightmapping.cs +++ b/Editor/EditorCore/Lightmapping.cs @@ -37,7 +37,8 @@ static class Styles public static readonly GUIContent areaError = new GUIContent("Area Error", ""); static bool s_Initialized; - public static GUIStyle miniButton; + public static GUIStyle s_MiniButton; + public static GUIStyle miniButton { get { Init(); return s_MiniButton; } } public static bool unwrapSettingsFoldout; public static void Init() @@ -47,12 +48,20 @@ public static void Init() s_Initialized = true; - miniButton = new GUIStyle(GUI.skin.button); - miniButton.stretchHeight = false; - miniButton.stretchWidth = false; - miniButton.padding = new RectOffset(6, 6, 3, 3); - miniButton.margin = new RectOffset(4, 4, 4, 0); + s_MiniButton = new GUIStyle(GUI.skin.button); + s_MiniButton.stretchHeight = false; + s_MiniButton.stretchWidth = false; + s_MiniButton.padding = new RectOffset(6, 6, 3, 3); + s_MiniButton.margin = new RectOffset(4, 4, 4, 0); } + +#if UNITY_EDITOR + internal static void Reset() + { + s_Initialized = false; + unwrapSettingsFoldout = false; + } +#endif } [UserSettingBlock("Mesh Settings")] @@ -106,6 +115,12 @@ static Lightmapping() Undo.postprocessModifications += PostprocessModifications; } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + Styles.Reset(); + } + /// /// Toggles the LightmapStatic bit of an objects Static flags. /// diff --git a/Editor/EditorCore/MaterialEditor.cs b/Editor/EditorCore/MaterialEditor.cs index 4729d4b2c..75432b5bb 100644 --- a/Editor/EditorCore/MaterialEditor.cs +++ b/Editor/EditorCore/MaterialEditor.cs @@ -131,6 +131,13 @@ public static void ApplyMaterial9() // The currently loaded material palette asset. static MaterialPalette s_CurrentPalette = null; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_CurrentPalette = null; + instance?.RefreshAvailablePalettes(); + } + // The user set "quick material" Pref m_QueuedMaterial = new Pref("materialEditor.quickMaterial", null, SettingsScope.User); diff --git a/Editor/EditorCore/MeshSelection.cs b/Editor/EditorCore/MeshSelection.cs index 39c1c977b..60220dba4 100644 --- a/Editor/EditorCore/MeshSelection.cs +++ b/Editor/EditorCore/MeshSelection.cs @@ -140,9 +140,36 @@ static MeshSelection() OnObjectSelectionChanged(); } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_SelectedFacesInEditArea.Clear(); + s_SelectedObjectCount = 0; + s_SelectedVertexCount = 0; + s_SelectedSharedVertexCount = 0; + s_SelectedFaceCount = 0; + s_SelectedEdgeCount = 0; + + s_SelectedFaceCountObjectMax = 0; + s_SelectedEdgeCountObjectMax = 0; + s_SelectedVertexCountObjectMax = 0; + s_SelectedSharedVertexCountObjectMax = 0; + s_SelectedCoincidentVertexCountMax = 0; + + s_TotalVertexCount = 0; + s_TotalFaceCount = 0; + s_TotalEdgeCount = 0; + s_TotalCommonVertexCount = 0; + s_TotalVertexCountCompiled = 0; + s_TotalTriangleCountCompiled = 0; + s_SelectionBounds = new Bounds(); + + OnObjectSelectionChanged(); + } + static void PrefabInstanceReverted(GameObject obj) { - if(obj.TryGetComponent(out _)) + if (obj.TryGetComponent(out _)) OnObjectSelectionChanged(); } diff --git a/Editor/EditorCore/PolyShapeTool.cs b/Editor/EditorCore/PolyShapeTool.cs index ba4ef44c7..7dc2de244 100644 --- a/Editor/EditorCore/PolyShapeTool.cs +++ b/Editor/EditorCore/PolyShapeTool.cs @@ -48,6 +48,12 @@ public override GUIContent toolbarIcon } } + [InitializeOnEnterPlayMode] + static void ResetDrawPolyShapeToolStatics() + { + s_IconContent = null; + } + /// public override void OnActivated() { @@ -373,6 +379,13 @@ public override GUIContent toolbarIcon } } + [InitializeOnEnterPlayMode] + static void ResetPolyShapeToolStatics() + { + s_HeightMouseOffset = 0f; + s_IconContent = null; + } + void OnEnable() { m_OverlayTitle = new GUIContent("PolyShape Settings"); @@ -392,6 +405,7 @@ public override void OnActivated() MeshSelection.objectSelectionChanged += OnObjectSelectionChanged; ToolManager.activeContextChanged += OnActiveContextChanged; Undo.undoRedoPerformed += UndoRedoPerformed; + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; m_Target = null; UpdateTarget(); @@ -404,6 +418,7 @@ public override void OnWillBeDeactivated() MeshSelection.objectSelectionChanged -= OnObjectSelectionChanged; ToolManager.activeContextChanged -= OnActiveContextChanged; Undo.undoRedoPerformed -= UndoRedoPerformed; + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; if(polygon != null && polygon.polyEditMode != PolyShape.PolyEditMode.None) SetPolyEditMode(PolyShape.PolyEditMode.None); @@ -443,6 +458,16 @@ protected void LeaveTool() ToolManager.RestorePreviousPersistentTool(); } + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingEditMode || state == PlayModeStateChange.ExitingPlayMode) + { + // Reset tool state when entering/exiting playmode + if (ToolManager.IsActiveTool(this)) + LeaveTool(); + } + } + /// /// Implements the PolyShapeTool in the Unity Editor. This method is called when the PolyShapeTool is activated. /// diff --git a/Editor/EditorCore/PreferencesInternal.cs b/Editor/EditorCore/PreferencesInternal.cs index d2d428c73..a3f8c0c35 100644 --- a/Editor/EditorCore/PreferencesInternal.cs +++ b/Editor/EditorCore/PreferencesInternal.cs @@ -53,6 +53,13 @@ static class PreferencesInternal static PreferenceDictionary s_Preferences = null; static bool s_Initialized; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Initialized = false; + s_Preferences = null; + } + static void LoadPreferencesObject() { string preferencesPath = FileUtility.GetLocalDataDirectory() + k_PrefsAssetName; diff --git a/Editor/EditorCore/ProBuilderEditor.cs b/Editor/EditorCore/ProBuilderEditor.cs index abc840a9a..6d342c187 100644 --- a/Editor/EditorCore/ProBuilderEditor.cs +++ b/Editor/EditorCore/ProBuilderEditor.cs @@ -179,6 +179,19 @@ public static void Init() padding = new RectOffset(0, 0, 0, 0) }; } + + internal static void ResetForPlayMode() + { + s_Init = false; + s_SelectionRect = null; + Init(); + } + } + + [InitializeOnEnterPlayMode] + static void ResetSceneStylesOnLoad() + { + SceneStyles.ResetForPlayMode(); } /// diff --git a/Editor/EditorCore/ProBuilderMeshEditor.cs b/Editor/EditorCore/ProBuilderMeshEditor.cs index e0784e024..2dcbb5d19 100644 --- a/Editor/EditorCore/ProBuilderMeshEditor.cs +++ b/Editor/EditorCore/ProBuilderMeshEditor.cs @@ -42,6 +42,21 @@ public static void Init() helpBox = new GUIStyle(EditorStyles.helpBox); helpBox.padding = new RectOffset(2, 2, 2, 2); } + +#if UNITY_EDITOR + internal static void ResetForPlayMode() + { + s_Initialized = false; + miniButton = null; + helpBox = null; + } +#endif + } + + [InitializeOnEnterPlayMode] + static void ResetMeshEditorStylesOnLoad() + { + Styles.ResetForPlayMode(); } internal static event System.Action onGetFrameBoundsEvent; diff --git a/Editor/EditorCore/ProBuilderShapeEditor.cs b/Editor/EditorCore/ProBuilderShapeEditor.cs index 5cef00bcf..16c2c2419 100644 --- a/Editor/EditorCore/ProBuilderShapeEditor.cs +++ b/Editor/EditorCore/ProBuilderShapeEditor.cs @@ -37,6 +37,12 @@ SerializedProperty shapeSizeProperty static bool s_foldoutEnabled = true; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_foldoutEnabled = true; + } + public GUIContent m_ShapePropertyLabel = new GUIContent("Shape Properties"); readonly GUIContent k_ShapePivotLabel = new GUIContent("Pivot"); diff --git a/Editor/EditorCore/ProBuilderToolsContexts.cs b/Editor/EditorCore/ProBuilderToolsContexts.cs index 49ab65d23..bde66f48a 100644 --- a/Editor/EditorCore/ProBuilderToolsContexts.cs +++ b/Editor/EditorCore/ProBuilderToolsContexts.cs @@ -184,6 +184,12 @@ public override void OnToolGUI(EditorWindow window) // are called on the entire selection and not per element. static bool s_ActionAlreadyTriggered = false; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_ActionAlreadyTriggered = false; + } + [MenuItem("CONTEXT/ProBuilderMesh/Conform Normals", true)] static bool ValidateConformObjectNormalsAction() { diff --git a/Editor/EditorCore/SceneDragAndDropListener.cs b/Editor/EditorCore/SceneDragAndDropListener.cs index cb98ea79e..672579ec5 100644 --- a/Editor/EditorCore/SceneDragAndDropListener.cs +++ b/Editor/EditorCore/SceneDragAndDropListener.cs @@ -31,6 +31,26 @@ static SceneDragAndDropListener() }; } + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_IsSceneViewDragAndDrop = false; + s_IsFaceDragAndDropOverrideEnabled = false; + s_CurrentPreview = null; + s_PreviewMaterial = null; + s_GetDefaultMaterialDelegate = null; + if (s_PreviewMesh == null) + { + s_PreviewMesh = new Mesh() + { + name = "pb_DragAndDropListener::PreviewMesh", + hideFlags = HideFlags.HideAndDontSave + }; + } + else + s_PreviewMesh.Clear(); + } + static void OnBeforeAssemblyReload() { UObject.DestroyImmediate(s_PreviewMesh); diff --git a/Editor/EditorCore/SmoothGroupEditor.cs b/Editor/EditorCore/SmoothGroupEditor.cs index b70080fc0..3ae72cd97 100644 --- a/Editor/EditorCore/SmoothGroupEditor.cs +++ b/Editor/EditorCore/SmoothGroupEditor.cs @@ -304,6 +304,24 @@ static GUIStyle wordWrappedRichText static bool s_IsMovingVertices = false; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + if (s_FaceMaterial != null) + UnityEngine.Object.DestroyImmediate(s_FaceMaterial); + s_FaceMaterial = null; + if (s_NormalPreviewMaterial != null) + UnityEngine.Object.DestroyImmediate(s_NormalPreviewMaterial); + s_NormalPreviewMaterial = null; + s_GroupButtonStyle = null; + s_GroupButtonSelectedStyle = null; + s_GroupButtonInUseStyle = null; + s_GroupButtonMixedSelectionStyle = null; + s_ColorKeyStyle = null; + s_WordWrappedRichText = null; + s_IsMovingVertices = false; + } + static Pref s_ShowPreview = new Pref("smoothing.showPreview", false); static Pref s_ShowNormals = new Pref("smoothing.showNormals", false); static Pref s_ShowHelp = new Pref("smoothing.showHelp", false); diff --git a/Editor/EditorCore/UVEditor.cs b/Editor/EditorCore/UVEditor.cs index d9976e8a0..69ea72e06 100644 --- a/Editor/EditorCore/UVEditor.cs +++ b/Editor/EditorCore/UVEditor.cs @@ -2529,6 +2529,12 @@ void DrawUVTools(Rect rect) static Rect ActionWindowDragRect = new Rect(0, 6, 10000, 30); static Editor uv2Editor = null; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + uv2Editor = null; + } + void DrawActionWindow(int windowIndex) { if (channel == 0) diff --git a/Editor/EditorCore/UndoUtility.cs b/Editor/EditorCore/UndoUtility.cs index e058b4a43..0354786a0 100644 --- a/Editor/EditorCore/UndoUtility.cs +++ b/Editor/EditorCore/UndoUtility.cs @@ -33,6 +33,12 @@ static void UndoRedoEventCallback(in UndoRedoInfo info) static int s_PreviewGroupIndex = -1; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_PreviewGroupIndex = -1; + } + internal static void StartPreview() { // Using this Undo method to remove the preview actions from the redo stack diff --git a/Editor/EditorCore/VertexColorPalette.cs b/Editor/EditorCore/VertexColorPalette.cs index e88d93f65..af09455d6 100644 --- a/Editor/EditorCore/VertexColorPalette.cs +++ b/Editor/EditorCore/VertexColorPalette.cs @@ -18,6 +18,12 @@ sealed class VertexColorPalette : ConfigurableWindow static VertexColorPalette s_Instance = null; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Instance = null; + } + [SerializeField] ColorPalette m_ColorPalette = null; diff --git a/Editor/MenuActions/Geometry/OffsetElements.cs b/Editor/MenuActions/Geometry/OffsetElements.cs index 21098f4f5..fbcb3e6d7 100644 --- a/Editor/MenuActions/Geometry/OffsetElements.cs +++ b/Editor/MenuActions/Geometry/OffsetElements.cs @@ -197,6 +197,12 @@ void OnGUI() static List s_Points = new List(); + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_Points.Clear(); + } + internal static void OnSceneGUI(SceneView view) { s_Points.Clear(); diff --git a/Editor/MenuActions/Object/ProBuilderize.cs b/Editor/MenuActions/Object/ProBuilderize.cs index dc9223d8a..04c660cb6 100644 --- a/Editor/MenuActions/Object/ProBuilderize.cs +++ b/Editor/MenuActions/Object/ProBuilderize.cs @@ -70,6 +70,12 @@ protected override MenuActionState optionsMenuState // are called on the entire selection and not per element. static bool s_ActionAlreadyTriggered = false; + [InitializeOnEnterPlayMode] + static void ResetStaticsOnLoad() + { + s_ActionAlreadyTriggered = false; + } + [MenuItem("CONTEXT/MeshFilter/ProBuilderize", true, 11)] static bool ProBuilderizeMeshAction_Validate(MenuCommand command) { diff --git a/Editor/Overlays/ActionSettings.cs b/Editor/Overlays/ActionSettings.cs index 2e5828c20..14e3153cc 100644 --- a/Editor/Overlays/ActionSettings.cs +++ b/Editor/Overlays/ActionSettings.cs @@ -60,6 +60,7 @@ void Init(MenuAction action, bool preview) SceneView.AddOverlayToActiveView(m_Overlay = new MenuActionSettingsOverlay()); m_Overlay.displayed = true; + SceneView.RepaintAll(); } public void Dispose() @@ -116,6 +117,12 @@ internal static void EndPreview() s_Instance?.Dispose(); } + [InitializeOnEnterPlayMode] + internal static void ResetPreviewActionManagerStatics() + { + Cancel(); + } + internal static void Validate() { s_Instance?.ValidateInternal(); @@ -224,7 +231,13 @@ public override VisualElement CreatePanelContent() public class MenuActionSettings : EditorAction { static bool s_CanTriggerNewAction = true; - + + [InitializeOnEnterPlayMode] + static void ResetMenuActionSettingsStatics() + { + s_CanTriggerNewAction = true; + } + /// /// MenuActionSettings constructor. /// diff --git a/External/CSG/CSG.cs b/External/CSG/CSG.cs index f2b37b11d..5f13acecb 100644 --- a/External/CSG/CSG.cs +++ b/External/CSG/CSG.cs @@ -46,6 +46,15 @@ public static float epsilon set => s_Epsilon = value; } + +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_Epsilon = k_DefaultEpsilon; + } +#endif + /// /// Performs a boolean operation on two GameObjects. /// diff --git a/External/Poly2Tri/P2T.cs b/External/Poly2Tri/P2T.cs index ab8ac355d..d61ace9d4 100644 --- a/External/Poly2Tri/P2T.cs +++ b/External/Poly2Tri/P2T.cs @@ -33,9 +33,19 @@ namespace UnityEngine.ProBuilder.Poly2Tri { static class P2T { private static TriangulationAlgorithm _defaultAlgorithm = TriangulationAlgorithm.DTSweep; - public static void Triangulate(PolygonSet ps) { +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + _defaultAlgorithm = TriangulationAlgorithm.DTSweep; + } +#endif + + public static void Triangulate(PolygonSet ps) + { TriangulationContext tcx = CreateContext(_defaultAlgorithm); - foreach (Polygon p in ps.Polygons) { + foreach (Polygon p in ps.Polygons) + { tcx.PrepareTriangulation(p); Triangulate(tcx); tcx.Clear(); diff --git a/External/Poly2Tri/Triangulation/TriangulationUtil.cs b/External/Poly2Tri/Triangulation/TriangulationUtil.cs index 7d0bb7750..86c835bff 100644 --- a/External/Poly2Tri/Triangulation/TriangulationUtil.cs +++ b/External/Poly2Tri/Triangulation/TriangulationUtil.cs @@ -35,6 +35,15 @@ namespace UnityEngine.ProBuilder.Poly2Tri { */ class TriangulationUtil { public static double EPSILON = 1e-12; + +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + EPSILON = 1e-12; + } +#endif + /// /// Requirements: /// 1. a,b and c form a triangle. @@ -59,7 +68,8 @@ class TriangulationUtil { /// triangle point /// point opposite a /// true if d is inside circle, false if on circle edge - public static bool SmartIncircle( TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd ) { + public static bool SmartIncircle(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd) + { double pdx = pd.X; double pdy = pd.Y; double adx = pa.X - pdx; diff --git a/External/Poly2Tri/Triangulation/Util/PolygonGenerator.cs b/External/Poly2Tri/Triangulation/Util/PolygonGenerator.cs index b46ec021a..273bb93d5 100644 --- a/External/Poly2Tri/Triangulation/Util/PolygonGenerator.cs +++ b/External/Poly2Tri/Triangulation/Util/PolygonGenerator.cs @@ -34,22 +34,37 @@ namespace UnityEngine.ProBuilder.Poly2Tri { class PolygonGenerator { static readonly System.Random RNG = new System.Random(); - private static double PI_2 = 2.0 * Math.PI; - public static Polygon RandomCircleSweep(double scale, int vertexCount) { +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + PI_2 = 2.0 * Math.PI; + } +#endif + + public static Polygon RandomCircleSweep(double scale, int vertexCount) + { PolygonPoint point; PolygonPoint[] points; double radius = scale / 4; points = new PolygonPoint[vertexCount]; - for (int i = 0; i < vertexCount; i++) { - do { - if (i % 250 == 0) { + for (int i = 0; i < vertexCount; i++) + { + do + { + if (i % 250 == 0) + { radius += scale / 2 * (0.5 - RNG.NextDouble()); - } else if (i % 50 == 0) { + } + else if (i % 50 == 0) + { radius += scale / 5 * (0.5 - RNG.NextDouble()); - } else { + } + else + { radius += 25 * scale / vertexCount * (0.5 - RNG.NextDouble()); } radius = radius > scale / 2 ? scale / 2 : radius; diff --git a/Runtime/Core/BuiltinMaterials.cs b/Runtime/Core/BuiltinMaterials.cs index 2772c75fb..031c9d8d0 100644 --- a/Runtime/Core/BuiltinMaterials.cs +++ b/Runtime/Core/BuiltinMaterials.cs @@ -69,13 +69,28 @@ public static class BuiltinMaterials static Material s_UnityDefaultDiffuse; static Material s_ShapePreviewMaterial; - static string k_EdgePickerMaterial = "Materials/EdgePicker"; - static string k_FacePickerMaterial = "Materials/FacePicker"; - static string k_VertexPickerMaterial = "Materials/VertexPicker"; + const string k_EdgePickerMaterial = "Materials/EdgePicker"; + const string k_FacePickerMaterial = "Materials/FacePicker"; + const string k_VertexPickerMaterial = "Materials/VertexPicker"; - static string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker"; - static string k_FacePickerShader = "Hidden/ProBuilder/FacePicker"; - static string k_VertexPickerShader = "Hidden/ProBuilder/VertexPicker"; + const string k_EdgePickerShader = "Hidden/ProBuilder/EdgePicker"; + const string k_FacePickerShader = "Hidden/ProBuilder/FacePicker"; + const string k_VertexPickerShader = "Hidden/ProBuilder/VertexPicker"; + +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + // Reset the static variables to their initial values, these 3 static variables will be re-initialized when accessed + s_DefaultMaterial = null; + s_UnityDefaultDiffuse = null; + s_ShapePreviewMaterial = null; + + // Re-initialize the rest of the static variables + s_IsInitialized = false; + Init(); + } +#endif static void Init() { @@ -109,6 +124,7 @@ static void Init() } } + /// /// Tests whether the current graphics device supports geometry shaders. /// diff --git a/Runtime/Core/Log.cs b/Runtime/Core/Log.cs index 7b3074a14..2da9297e4 100644 --- a/Runtime/Core/Log.cs +++ b/Runtime/Core/Log.cs @@ -57,6 +57,17 @@ static class Log // Path to the log file. static string s_LogFilePath = k_ProBuilderLogFileName; +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_logStack.Clear(); + s_LogLevel = LogLevel.All; + s_Output = LogOutput.Console; + s_LogFilePath = k_ProBuilderLogFileName; + } +#endif + /// /// Push the current log level in the stack. See also PopLogLevel. /// diff --git a/Runtime/Core/MaterialUtility.cs b/Runtime/Core/MaterialUtility.cs index 6676f4f77..2bd1c41b5 100644 --- a/Runtime/Core/MaterialUtility.cs +++ b/Runtime/Core/MaterialUtility.cs @@ -8,6 +8,14 @@ static class MaterialUtility { internal static List s_MaterialArray = new List(); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_MaterialArray.Clear(); + } +#endif + internal static int GetMaterialCount(Renderer renderer) { s_MaterialArray.Clear(); diff --git a/Runtime/Core/Math.cs b/Runtime/Core/Math.cs index 9c1763856..290101d69 100644 --- a/Runtime/Core/Math.cs +++ b/Runtime/Core/Math.cs @@ -570,6 +570,17 @@ public static bool RayIntersectsTriangle(Ray InRay, Vector3 InTriangleA, Vector3 // Temporary vector3 values static Vector3 tv1, tv2, tv3, tv4; +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + tv1 = default; + tv2 = default; + tv3 = default; + tv4 = default; + } +#endif + /// /// Non-allocating version of Ray / Triangle intersection. /// @@ -1290,7 +1301,7 @@ internal static Vector2 EnsureUnitVector(Vector2 value) { return Mathf.Abs(value.sqrMagnitude) < float.Epsilon ? Vector2.right : value.normalized; } - + internal static Vector3 EnsureUnitVector(Vector3 value) { return Mathf.Abs(value.sqrMagnitude) < float.Epsilon ? Vector3.up : value.normalized; diff --git a/Runtime/Core/MeshHandles.cs b/Runtime/Core/MeshHandles.cs index 07839a996..f8013d30a 100644 --- a/Runtime/Core/MeshHandles.cs +++ b/Runtime/Core/MeshHandles.cs @@ -17,6 +17,18 @@ static class MeshHandles static readonly Vector2 k_Billboard2 = new Vector2( 1f, -1f); static readonly Vector2 k_Billboard3 = new Vector2( 1f, 1f); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_Vector2List.Clear(); + s_Vector3List.Clear(); + s_Vector4List.Clear(); + s_IndexList.Clear(); + s_SharedVertexIndexList.Clear(); + } +#endif + internal static void CreateFaceMesh(ProBuilderMesh mesh, Mesh target) { target.Clear(); diff --git a/Runtime/Core/Normals.cs b/Runtime/Core/Normals.cs index 09d7cfffb..68414cb82 100644 --- a/Runtime/Core/Normals.cs +++ b/Runtime/Core/Normals.cs @@ -20,6 +20,16 @@ static void ClearIntArray(int count) s_CachedIntArray[i] = 0; } +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_SmoothAvg = new Vector3[Smoothing.smoothRangeMax]; + s_SmoothAvgCount = new float[Smoothing.smoothRangeMax]; + s_CachedIntArray = new int[ushort.MaxValue]; + } +#endif + /// /// Calculates the tangents for a mesh. /// diff --git a/Runtime/Core/ProBuilderMeshFunction.cs b/Runtime/Core/ProBuilderMeshFunction.cs index 5175a5656..c5ad58a1d 100644 --- a/Runtime/Core/ProBuilderMeshFunction.cs +++ b/Runtime/Core/ProBuilderMeshFunction.cs @@ -24,6 +24,12 @@ public void OnAfterDeserialize() InvalidateCaches(); } + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_CachedHashSet.Clear(); + } + #if ENABLE_DRIVEN_PROPERTIES // Using the internal callbacks here to avoid registering this component as "enable-able" void OnEnableINTERNAL() diff --git a/Runtime/Core/SelectPathFaces.cs b/Runtime/Core/SelectPathFaces.cs index e5acfce35..7b73269a9 100644 --- a/Runtime/Core/SelectPathFaces.cs +++ b/Runtime/Core/SelectPathFaces.cs @@ -12,6 +12,19 @@ static class SelectPathFaces static List s_cachedWings; static Dictionary s_cachedFacesIndex = new Dictionary(); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_cachedPredecessors = null; + s_cachedStart = -1; + s_cachedMesh = null; + s_cachedFacesCount = -1; + s_cachedWings = null; + s_cachedFacesIndex.Clear(); + } +#endif + /// /// Calculates the indexes of all faces in the shortest path between start and end /// @@ -30,7 +43,7 @@ public static List GetPath(ProBuilderMesh mesh, int start, int end) List path; - if (start == s_cachedStart && mesh == s_cachedMesh && mesh.faceCount == s_cachedFacesCount) + if (start == s_cachedStart && mesh == s_cachedMesh && mesh.faceCount == s_cachedFacesCount) return GetMinimalPath(s_cachedPredecessors, start, end); var predecessors = Dijkstra(mesh, start); diff --git a/Runtime/Core/SelectionPickerRenderer.cs b/Runtime/Core/SelectionPickerRenderer.cs index a0c1da16a..e46027b78 100644 --- a/Runtime/Core/SelectionPickerRenderer.cs +++ b/Runtime/Core/SelectionPickerRenderer.cs @@ -148,12 +148,22 @@ static RenderTextureFormat renderTextureFormat static RenderTextureFormat s_RenderTextureFormat = RenderTextureFormat.Default; - static RenderTextureFormat[] s_PreferredFormats = new RenderTextureFormat[] + static readonly RenderTextureFormat[] s_PreferredFormats = new RenderTextureFormat[] { RenderTextureFormat.ARGB32, RenderTextureFormat.ARGBFloat, }; +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_Initialized = false; + s_PickerRenderer = null; + s_RenderTextureFormat = RenderTextureFormat.Default; + } +#endif + /// /// Returns an appropriate implementation based on the graphic pipeline /// to generate the lookup texture. diff --git a/Runtime/Core/TransformUtility.cs b/Runtime/Core/TransformUtility.cs index 7c4499d74..430cff362 100644 --- a/Runtime/Core/TransformUtility.cs +++ b/Runtime/Core/TransformUtility.cs @@ -10,6 +10,14 @@ public static class TransformUtility { static Dictionary s_ChildStack = new Dictionary(); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_ChildStack.Clear(); + } +#endif + /// /// Unparent all children from a transform, saving them for later re-parenting (see ReparentChildren). /// diff --git a/Runtime/Core/UvAutoManualConversion.cs b/Runtime/Core/UvAutoManualConversion.cs index c69d02429..98bd0e5c8 100644 --- a/Runtime/Core/UvAutoManualConversion.cs +++ b/Runtime/Core/UvAutoManualConversion.cs @@ -81,13 +81,21 @@ public override string ToString() static List s_UVTransformProjectionBuffer = new List(8); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad_UvAutoManualConversion() + { + s_UVTransformProjectionBuffer.Clear(); + } +#endif + /// - /// Returns the auto unwrap settings for a face. In cases where the face is auto unwrapped (manualUV = false), - /// this returns an unmodified copy of the AutoUnwrapSettings. If the face is manually unwrapped, it returns - /// the auto unwrap settings computed from GetUVTransform. - /// - /// - internal static AutoUnwrapSettings GetAutoUnwrapSettings(ProBuilderMesh mesh, Face face) + /// Returns the auto unwrap settings for a face. In cases where the face is auto unwrapped (manualUV = false), + /// this returns an unmodified copy of the AutoUnwrapSettings. If the face is manually unwrapped, it returns + /// the auto unwrap settings computed from GetUVTransform. + /// + /// + internal static AutoUnwrapSettings GetAutoUnwrapSettings(ProBuilderMesh mesh, Face face) { if (!face.manualUV) return new AutoUnwrapSettings(face.uv); diff --git a/Runtime/Core/UvUnwrapping.cs b/Runtime/Core/UvUnwrapping.cs index 4748df144..81d0f101c 100644 --- a/Runtime/Core/UvUnwrapping.cs +++ b/Runtime/Core/UvUnwrapping.cs @@ -8,6 +8,15 @@ static partial class UvUnwrapping static Vector2 s_TempVector2 = Vector2.zero; static readonly List s_IndexBuffer = new List(64); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad_UvUnwrapping() + { + s_TempVector2 = Vector2.zero; + s_IndexBuffer.Clear(); + } +#endif + internal static void Unwrap(ProBuilderMesh mesh, Face face, Vector3 projection = default) { Projection.PlanarProject(mesh, face, projection != Vector3.zero ? projection : Vector3.zero); diff --git a/Runtime/Core/VertexPositioning.cs b/Runtime/Core/VertexPositioning.cs index 70df07391..2d07c6d36 100644 --- a/Runtime/Core/VertexPositioning.cs +++ b/Runtime/Core/VertexPositioning.cs @@ -13,6 +13,14 @@ public static class VertexPositioning { static List s_CoincidentVertices = new List(); +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_CoincidentVertices.Clear(); + } +#endif + /// /// Returns a copy of a mesh positions array transformed into world coordinates. /// diff --git a/Runtime/MeshOperations/Triangulation.cs b/Runtime/MeshOperations/Triangulation.cs index 2cb62bb8d..a073c940c 100644 --- a/Runtime/MeshOperations/Triangulation.cs +++ b/Runtime/MeshOperations/Triangulation.cs @@ -24,6 +24,14 @@ static TriangulationContext triangulationContext } } +#if UNITY_EDITOR + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void ResetStaticsOnLoad() + { + s_TriangulationContext = null; + } +#endif + /// /// Given a set of points this method will format the points into a boundary contour and triangulate, returning /// a set of indexes that corresponds to the original ordering.