internal override void OnBrushApply(BrushTarget brushTarget, BrushSettings brushSettings) { // false means no ToMesh or Refresh, true does. Optional addl bool runs pb_Object.Optimize() brushTarget.editableObject.Apply(true); if (ProBuilderBridge.ProBuilderExists() && brushTarget.editableObject.isProBuilderObject) { ProBuilderBridge.Refresh(brushTarget.gameObject); } UpdateTempComponent(brushTarget, brushSettings); }
/// <summary> /// Generate a static preview for a ProBuilderMesh. /// </summary> /// <returns>Static preview of the given ProBuilderMesh.</returns> internal Texture2D GenerateProBuilderPreview() { GameObject copy = GameObject.Instantiate <GameObject>(m_Asset as GameObject); copy.hideFlags = HideFlags.HideAndDontSave; ProBuilderBridge.ToMesh(copy); ProBuilderBridge.Refresh(copy); MeshFilter mf = copy.GetComponent <MeshFilter>(); Editor meshEditor = Editor.CreateEditor(mf.sharedMesh); Texture2D preview = meshEditor.RenderStaticPreview(null, null, k_PreviewSize.x, k_PreviewSize.y); ScriptableObject.DestroyImmediate(meshEditor); ScriptableObject.DestroyImmediate(copy); return(preview); }
internal override void UndoRedoPerformed(List <GameObject> modified) { modifiedMeshes = new HashSet <PolyMesh>(modifiedMeshes.Where(x => x != null)); #if PROBUILDER_4_0_OR_NEWER if (ProBuilderBridge.ProBuilderExists()) { // delete & undo causes cases where object is not null but the reference to it's pb_Object is HashSet <GameObject> remove = new HashSet <GameObject>(); foreach (GameObject pb in modifiedPbMeshes) { try { ProBuilderBridge.ToMesh(pb); ProBuilderBridge.Refresh(pb); ProBuilderBridge.Optimize(pb); } catch { remove.Add(pb); } } if (remove.Count() > 0) { modifiedPbMeshes.SymmetricExceptWith(remove); } } #endif foreach (PolyMesh m in modifiedMeshes) { m.UpdateMeshFromData(); } base.UndoRedoPerformed(modified); }
/// <summary> /// Applies mesh changes back to the pb_Object (if necessary). Optionally does a /// mesh rebuild. /// </summary> /// <param name="rebuildMesh">Only applies to ProBuilder meshes.</param> /// <param name="optimize">Determines if the mesh collisions are rebuilt (if that option is enabled) or if /// the mehs is a probuilder object, the mesh is optimized (condensed to share verts, other /// otpimziations etc) </param> internal void Apply(bool rebuildMesh, bool optimize = false) { if (m_PolybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream) { if (PolyEditor.instance.tool == BrushTool.RaiseLower || PolyEditor.instance.tool == BrushTool.Smooth) { if (s_RebuildNormals.value && (modifiedChannels & MeshChannel.Position) > 0) { PolyMeshUtility.RecalculateNormals(editMesh); } if (optimize) { graphicsMesh.RecalculateBounds(); UpdateMeshCollider(); } } editMesh.ApplyAttributesToUnityMesh(graphicsMesh, modifiedChannels); graphicsMesh.UploadMeshData(false); EditorUtility.SetDirty(gameObjectAttached.GetComponent <Renderer>()); if (m_PolybrushMesh.componentsCache.MeshFilter) { Undo.RecordObject(m_PolybrushMesh.componentsCache.MeshFilter, "Assign Polymesh to MeshFilter"); } if (m_PolybrushMesh) { m_PolybrushMesh.SynchronizeWithMeshRenderer(); } } #if PROBUILDER_4_0_OR_NEWER // if it's a probuilder object rebuild the mesh without optimization if (isProBuilderObject) { ProBuilderBridge.SetPositions(gameObjectAttached, editMesh.vertices); ProBuilderBridge.SetTangents(gameObjectAttached, editMesh.tangents); if (editMesh.colors != null && editMesh.colors.Length == editMesh.vertexCount) { Color[] colors = System.Array.ConvertAll(editMesh.colors, x => (Color)x); ProBuilderBridge.SetColors(gameObjectAttached, colors); } if (rebuildMesh) { ProBuilderBridge.ToMesh(gameObjectAttached); ProBuilderBridge.Refresh(gameObjectAttached, optimize ? ProBuilderBridge.RefreshMask.All : (ProBuilderBridge.RefreshMask.Colors | ProBuilderBridge.RefreshMask.Normals | ProBuilderBridge.RefreshMask.Tangents)); } } #endif if (m_PolybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream) { modifiedChannels = MeshChannel.Null; return; } if (PolyEditor.instance.tool == BrushTool.RaiseLower || PolyEditor.instance.tool == BrushTool.Smooth) { if (s_RebuildNormals.value)// && (modifiedChannels & MeshChannel.Position) > 0) { PolyMeshUtility.RecalculateNormals(editMesh); } if (optimize) { UpdateMeshCollider(); graphicsMesh.RecalculateBounds(); } } editMesh.ApplyAttributesToUnityMesh(graphicsMesh, modifiedChannels); if (m_PolybrushMesh.componentsCache.MeshFilter) { Undo.RecordObject(m_PolybrushMesh.componentsCache.MeshFilter, "Assign Polymesh to MeshFilter"); } m_PolybrushMesh.SynchronizeWithMeshRenderer(); modifiedChannels = MeshChannel.Null; }
private void Initialize(GameObject go) { CheckBackwardCompatiblity(go); gameObjectAttached = go; isProBuilderObject = false; #if PROBUILDER_4_0_OR_NEWER if (ProBuilderBridge.ProBuilderExists()) { isProBuilderObject = ProBuilderBridge.IsValidProBuilderMesh(gameObjectAttached); } #endif Mesh mesh = null; MeshRenderer meshRenderer = gameObjectAttached.GetComponent <MeshRenderer>(); meshFilter = gameObjectAttached.GetComponent <MeshFilter>(); _skinMeshRenderer = gameObjectAttached.GetComponent <SkinnedMeshRenderer>(); originalMesh = go.GetMesh(); if (originalMesh == null && _skinMeshRenderer != null) { originalMesh = _skinMeshRenderer.sharedMesh; } m_PolybrushMesh = gameObjectAttached.GetComponent <PolybrushMesh>(); if (m_PolybrushMesh == null) { m_PolybrushMesh = Undo.AddComponent <PolybrushMesh>(gameObjectAttached); m_PolybrushMesh.Initialize(); m_PolybrushMesh.mode = (s_UseAdditionalVertexStreams) ? PolybrushMesh.Mode.AdditionalVertexStream : PolybrushMesh.Mode.Mesh; } //attach the skinmesh ref to the polybrushmesh //it will be used when making a prefab containing a skin mesh. The limitation here is that the skin mesh must comes from an asset (which is 99.9999% of the time) if (_skinMeshRenderer != null) { Mesh sharedMesh = _skinMeshRenderer.sharedMesh; if (AssetDatabase.Contains(sharedMesh)) { m_PolybrushMesh.skinMeshRef = sharedMesh; } } #if PROBUILDER_4_0_OR_NEWER // if it's a probuilder object rebuild the mesh without optimization if (isProBuilderObject) { if (ProBuilderBridge.IsValidProBuilderMesh(gameObjectAttached)) { ProBuilderBridge.ToMesh(gameObjectAttached); ProBuilderBridge.Refresh(gameObjectAttached); } } #endif if (meshRenderer != null || _skinMeshRenderer != null) { mesh = m_PolybrushMesh.storedMesh; if (mesh == null) { mesh = PolyMeshUtility.DeepCopy(originalMesh); hadVertexStreams = false; } else { //prevents leak if (!MeshInstanceMatchesGameObject(mesh, gameObjectAttached)) { mesh = PolyMeshUtility.DeepCopy(mesh); } } mesh.name = k_MeshInstancePrefix + gameObjectAttached.GetInstanceID(); } polybrushMesh.SetMesh(mesh); PrefabUtility.RecordPrefabInstancePropertyModifications(polybrushMesh); _graphicsMesh = m_PolybrushMesh.storedMesh; source = polybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream? ModelSource.AdditionalVertexStreams : PolyEditorUtility.GetMeshGUID(originalMesh); GenerateCompositeMesh(); }