void OnEnable() { if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } m_Mesh = (ProBuilderMesh)target; if (!m_Mesh) { return; } m_GameObjectsSerializedObject = new SerializedObject(serializedObject.targetObjects.Select(t => ((Component)t).gameObject).ToArray()); m_UnwrapParameters = serializedObject.FindProperty("m_UnwrapParameters"); m_StaticEditorFlags = m_GameObjectsSerializedObject.FindProperty("m_StaticEditorFlags"); m_MeshRenderer = m_Mesh.gameObject.GetComponent <Renderer>(); SelectionRenderState s = EditorUtility.GetSelectionRenderState(); EditorUtility.SetSelectionRenderState(m_MeshRenderer, editor != null ? s & SelectionRenderState.Outline : s); foreach (var mesh in Selection.transforms.GetComponents <ProBuilderMesh>()) { EditorUtility.SynchronizeWithMeshFilter(mesh); } VertexManipulationTool.beforeMeshModification += OnBeginMeshModification; VertexManipulationTool.afterMeshModification += OnFinishMeshModification; }
static void UndoRedoPerformed() { // material preview when dragging in scene-view is done by applying then undoing changes. we don't want to // rebuild the mesh every single frame when dragging. if (SceneDragAndDropListener.isDragging) { return; } // Synchronize just checks that the mesh is not null, and UV2 is still valid. This should be very cheap except // for the FindObjectsOfType call. foreach (var mesh in Object.FindObjectsOfType <ProBuilderMesh>()) { var versionID = mesh.versionID; EditorUtility.SynchronizeWithMeshFilter(mesh); mesh.InvalidateCaches(); mesh.versionID = versionID; } foreach (var mesh in InternalUtility.GetComponents <ProBuilderMesh>(Selection.transforms)) { var versionID = mesh.versionID; mesh.InvalidateCaches(); mesh.Rebuild(); mesh.Optimize(); mesh.versionID = versionID; } ProBuilderEditor.Refresh(); SceneView.RepaintAll(); }
static void UndoRedoPerformed() { // material preview when dragging in scene-view is done by applying then undoing changes. we don't want to // rebuild the mesh every single frame when dragging. if (SceneDragAndDropListener.isDragging) { return; } // Two passes // 1. Ensure every ProBuilderMesh in the scene has a valid mesh // 2. Rebuild every ProBuilderMesh in the selection to reflect undone changes. // Synchronize just checks that the mesh is not null, and UV2 is still valid. This should be very cheap except // for the FindObjectsOfType call. foreach (var mesh in Object.FindObjectsOfType <ProBuilderMesh>()) { EditorUtility.SynchronizeWithMeshFilter(mesh); mesh.InvalidateCaches(); } foreach (var mesh in InternalUtility.GetComponents <ProBuilderMesh>(Selection.transforms)) { mesh.InvalidateCaches(); using (new ProBuilderMesh.NonVersionedEditScope(mesh)) { mesh.Rebuild(); mesh.Optimize(); } } ProBuilderEditor.Refresh(); }
public static void DoStrip(ProBuilderMesh pb) { try { GameObject go = pb.gameObject; Renderer ren = go.GetComponent <Renderer>(); if (ren != null) { EditorUtility.SetSelectionRenderState(ren, EditorSelectedRenderState.Highlight | EditorSelectedRenderState.Wireframe); } if (EditorUtility.IsPrefabAsset(go)) { return; } EditorUtility.SynchronizeWithMeshFilter(pb); if (pb.mesh == null) { DestroyProBuilderMeshAndDependencies(go, pb, false); return; } string cachedMeshPath; Mesh cachedMesh; // if meshes are assets and the mesh cache is valid don't duplicate the mesh to an instance. if (Experimental.meshesAreAssets && EditorMeshUtility.GetCachedMesh(pb, out cachedMeshPath, out cachedMesh)) { DestroyProBuilderMeshAndDependencies(go, pb, true); } else { Mesh m = UnityEngine.ProBuilder.MeshUtility.DeepCopy(pb.mesh); DestroyProBuilderMeshAndDependencies(go, pb); go.GetComponent <MeshFilter>().sharedMesh = m; if (go.TryGetComponent(out MeshCollider meshCollider)) { meshCollider.sharedMesh = m; } } } catch {} }
static void PrefabInstanceUpdated(GameObject go) { if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } foreach (ProBuilderMesh pb in go.GetComponentsInChildren <ProBuilderMesh>()) { EditorUtility.SynchronizeWithMeshFilter(pb); pb.ToMesh(); pb.Refresh(); pb.Optimize(); } }
/** * Used to catch prefab modifications that otherwise wouldn't be registered on the usual 'Awake' verify. * - Dragging prefabs out of Project * - 'Revert' prefab changes * - 'Apply' prefab changes */ static void HierarchyWindowChanged() { if (!EditorApplication.isPlaying) { bool meshesAreAssets = Experimental.meshesAreAssets; // on duplication, or copy paste, this rebuilds the mesh structures of the new objects foreach (ProBuilderMesh pb in Selection.transforms.GetComponents <ProBuilderMesh>()) { if (!meshesAreAssets) { EditorUtility.SynchronizeWithMeshFilter(pb); } } } }
/// <summary> /// Hide the default unity wireframe renderer /// </summary> void SetOverrideWireframe(bool overrideWireframe) { const EditorSelectedRenderState k_DefaultSelectedRenderState = EditorSelectedRenderState.Highlight | EditorSelectedRenderState.Wireframe; foreach (var mesh in Selection.transforms.GetComponents <ProBuilderMesh>()) { // Disable Wireframe for meshes when ProBuilder is active EditorUtility.SetSelectionRenderState( mesh.renderer, overrideWireframe ? k_DefaultSelectedRenderState & ~(EditorSelectedRenderState.Wireframe) : k_DefaultSelectedRenderState); EditorUtility.SynchronizeWithMeshFilter(mesh); } SceneView.RepaintAll(); }
public static void OnPostprocessScene() { var invisibleFaceMaterial = Resources.Load <Material>("Materials/InvisibleFace"); // Hide nodraw faces if present. foreach (var pb in Object.FindObjectsOfType <ProBuilderMesh>()) { if (pb.GetComponent <MeshRenderer>() == null) { continue; } if (pb.GetComponent <MeshRenderer>().sharedMaterials.Any(x => x != null && x.name.Contains("NoDraw"))) { Material[] mats = pb.GetComponent <MeshRenderer>().sharedMaterials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains("NoDraw")) { mats[i] = invisibleFaceMaterial; } } pb.GetComponent <MeshRenderer>().sharedMaterials = mats; } } if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } foreach (var entity in Resources.FindObjectsOfTypeAll <EntityBehaviour>()) { if (entity.manageVisibility) { entity.OnEnterPlayMode(); } } foreach (var mesh in Object.FindObjectsOfType <ProBuilderMesh>()) { EditorUtility.SynchronizeWithMeshFilter(mesh); if (mesh.mesh == null) { continue; } GameObject gameObject = mesh.gameObject; var entity = ProcessLegacyEntity(gameObject); #if ENABLE_DRIVEN_PROPERTIES // clear editor-only HideFlags and serialization ignores mesh.ClearDrivenProperties(); var filter = gameObject.DemandComponent <MeshFilter>(); filter.hideFlags = HideFlags.None; mesh.mesh.hideFlags = HideFlags.None; // Reassign the MeshFilter and MeshCollider properties _after_ clearing HideFlags and driven properties // to ensure that they are dirtied for serialization and thus included in the build filter.sharedMesh = mesh.mesh; if (mesh.TryGetComponent(out MeshCollider collider)) { collider.sharedMesh = mesh.mesh; } #endif // early out if we're not planning to remove the ProBuilderMesh component if (m_ScriptStripping == false) { continue; } if (mesh.TryGetComponent <BezierShape>(out BezierShape bezier)) { Object.DestroyImmediate(bezier); } if (mesh.TryGetComponent <PolyShape>(out PolyShape poly)) { Object.DestroyImmediate(poly); } mesh.preserveMeshAssetOnDestroy = true; Object.DestroyImmediate(mesh); Object.DestroyImmediate(entity); } }
internal static void OnObjectSelectionChanged() { // GameObjects returns both parent and child when both are selected, where transforms only returns the // top-most transform. s_UnitySelectionChangeMeshes.Clear(); s_ElementSelection.Clear(); s_ActiveMesh = null; var gameObjects = Selection.gameObjects; for (int i = 0, c = gameObjects.Length; i < c; i++) { #if UNITY_2019_3_OR_NEWER ProBuilderMesh mesh; if (gameObjects[i].TryGetComponent <ProBuilderMesh>(out mesh)) #else var mesh = gameObjects[i].GetComponent <ProBuilderMesh>(); if (mesh != null) #endif { if (gameObjects[i] == Selection.activeGameObject) { s_ActiveMesh = mesh; } s_UnitySelectionChangeMeshes.Add(mesh); } } for (int i = 0, c = s_TopSelection.Count; i < c; i++) { if (!s_UnitySelectionChangeMeshes.Contains(s_TopSelection[i])) { if (s_TopSelection[i] != null) { UndoUtility.RecordSelection(s_TopSelection[i], "Selection Change"); } s_TopSelection[i].ClearSelection(); } } s_TopSelection.Clear(); foreach (var mesh in s_UnitySelectionChangeMeshes) { // don't add prefabs or assets to the mesh selection if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh.gameObject))) { EditorUtility.SynchronizeWithMeshFilter(mesh); s_TopSelection.Add(mesh); } } InvalidateCaches(); if (objectSelectionChanged != null) { objectSelectionChanged(); } s_UnitySelectionChangeMeshes.Clear(); }
public static void DoStrip(ProBuilderMesh pb) { try { GameObject go = pb.gameObject; Renderer ren = go.GetComponent <Renderer>(); if (ren != null) { EditorUtility.SetSelectionRenderState(ren, EditorUtility.GetSelectionRenderState()); } if (EditorUtility.IsPrefabAsset(go)) { return; } EditorUtility.SynchronizeWithMeshFilter(pb); if (pb.mesh == null) { DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } return; } string cachedMeshPath; Mesh cachedMesh; // if meshes are assets and the mesh cache is valid don't duplicate the mesh to an instance. if (Experimental.meshesAreAssets && EditorMeshUtility.GetCachedMesh(pb, out cachedMeshPath, out cachedMesh)) { pb.preserveMeshAssetOnDestroy = true; DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } } else { Mesh m = UnityEngine.ProBuilder.MeshUtility.DeepCopy(pb.mesh); DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } go.GetComponent <MeshFilter>().sharedMesh = m; if (go.GetComponent <MeshCollider>()) { go.GetComponent <MeshCollider>().sharedMesh = m; } } } catch {} }
public static void OnPostprocessScene() { var invisibleFaceMaterial = Resources.Load <Material>("Materials/InvisibleFace"); var pbMeshes = (ProBuilderMesh[])Resources.FindObjectsOfTypeAll(typeof(ProBuilderMesh)); // Hide nodraw faces if present. foreach (var pb in pbMeshes) { if (pb.GetComponent <MeshRenderer>() == null || UnityEditor.EditorUtility.IsPersistent(pb)) { continue; } if (pb.GetComponent <MeshRenderer>().sharedMaterials.Any(x => x != null && x.name.Contains("NoDraw"))) { Material[] mats = pb.GetComponent <MeshRenderer>().sharedMaterials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains("NoDraw")) { mats[i] = invisibleFaceMaterial; } } pb.GetComponent <MeshRenderer>().sharedMaterials = mats; } } if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } var renderersToStrip = new List <Renderer>(); foreach (var entity in Resources.FindObjectsOfTypeAll <EntityBehaviour>()) { if (entity.manageVisibility) { entity.OnEnterPlayMode(); } if ((entity is TriggerBehaviour || entity is ColliderBehaviour) && entity.gameObject.TryGetComponent(out MeshRenderer renderer)) { renderersToStrip.Add(renderer); } } foreach (var mesh in pbMeshes) { if (UnityEditor.EditorUtility.IsPersistent(mesh)) { continue; } EditorUtility.SynchronizeWithMeshFilter(mesh); if (mesh.mesh == null) { continue; } GameObject gameObject = mesh.gameObject; var entity = ProcessLegacyEntity(gameObject); #if ENABLE_DRIVEN_PROPERTIES // clear editor-only HideFlags and serialization ignores mesh.ClearDrivenProperties(); var filter = gameObject.DemandComponent <MeshFilter>(); filter.hideFlags = HideFlags.None; mesh.mesh.hideFlags = HideFlags.None; // Reassign the MeshFilter and MeshCollider properties _after_ clearing HideFlags and driven properties // to ensure that they are dirtied for serialization and thus included in the build filter.sharedMesh = mesh.mesh; if (mesh.TryGetComponent(out MeshCollider collider)) { collider.sharedMesh = mesh.mesh; } #endif // early out if we're not planning to remove the ProBuilderMesh component if (m_ScriptStripping == false) { continue; } StripProBuilderScripts.DestroyProBuilderMeshAndDependencies(gameObject, mesh, true); } foreach (var renderer in renderersToStrip) { Undo.DestroyObjectImmediate(renderer); } }