void OnPostprocessModel(GameObject g) { Init(); //if (storage == null) return; ModelImporter importer = (ModelImporter)assetImporter; if (importer.generateSecondaryUV) { // Auto UVs: Adjust UV padding per mesh //if (!storage.modifiedAssetPathList.Contains(assetPath) && g.tag == "BakeryProcessed") return; //if (ftLightmaps.IsModelProcessed(assetPath)) return; //g.tag = "BakeryProcessed"; Debug.Log("Bakery: processing auto-unwrapped asset " + assetPath); if (storage != null) { ftLightmaps.MarkModelProcessed(assetPath, true); } uparams = new UnwrapParam(); UnwrapParam.SetDefaults(out uparams); uparams.angleError = importer.secondaryUVAngleDistortion * 0.01f; uparams.areaError = importer.secondaryUVAreaDistortion * 0.01f; uparams.hardAngle = importer.secondaryUVHardAngle; #if UNITY_2017_1_OR_NEWER deserializedSuccess = false; var props = importer.extraUserProperties; for (int p = 0; p < props.Length; p++) { if (props[p].Substring(0, 7) == "#BAKERY") { var json = props[p].Substring(7); deserialized = JsonUtility.FromJson <ftGlobalStorage.AdjustedMesh>(json); deserializedSuccess = true; break; } } #endif if (storage != null) { storage.InitModifiedMeshMap(assetPath); } AdjustUV(g.transform); } else { if (storage == null) { return; } Debug.Log("Bakery: checking for UV overlaps in " + assetPath); //if (g.tag == "BakeryProcessed") g.tag = ""; ftLightmaps.MarkModelProcessed(assetPath, true);//false); // Manual UVs: check if overlapping CheckUVOverlap(g, assetPath); } if (g.tag == "BakeryProcessed") { g.tag = ""; // remove legacy mark } }
public virtual void UnwrapXatlas(Mesh m, UnwrapParam param) { }
/// <summary> /// Optmizes the mesh geometry, and generates a UV2 channel (if object is marked as LightmapStatic, or generateLightmapUVs is true). /// </summary> /// <remarks>This is only applicable to meshes with triangle topology. Quad meshes are not affected by this function.</remarks> /// <param name="mesh">The ProBuilder mesh component to be optimized.</param> /// <param name="generateLightmapUVs">If the Auto UV2 preference is disabled this parameter can be used to force UV2s to be built.</param> public static void Optimize(this ProBuilderMesh mesh, bool generateLightmapUVs = false) { if (mesh == null) { throw new ArgumentNullException("mesh"); } Mesh umesh = mesh.mesh; if (umesh == null || umesh.vertexCount < 1) { return; } bool skipMeshProcessing = false; // @todo Support mesh compression for topologies other than Triangles. for (int i = 0; !skipMeshProcessing && i < umesh.subMeshCount; i++) { if (umesh.GetTopology(i) != MeshTopology.Triangles) { skipMeshProcessing = true; } } if (!skipMeshProcessing) { bool autoLightmap = Lightmapping.autoUnwrapLightmapUV; #if UNITY_2019_2_OR_NEWER bool lightmapUVs = generateLightmapUVs || (autoLightmap && mesh.gameObject.HasStaticFlag(StaticEditorFlags.ContributeGI)); #else bool lightmapUVs = generateLightmapUVs || (autoLightmap && mesh.gameObject.HasStaticFlag(StaticEditorFlags.LightmapStatic)); #endif var usedInParticuleSystem = UnityEngine.ProBuilder.MeshUtility.IsUsedInParticleSystem(mesh); // if generating UV2, the process is to manually split the mesh into individual triangles, // generate uv2, then re-assemble with vertex collapsing where possible. // if not generating uv2, just collapse vertices. if (lightmapUVs) { Vertex[] vertices = UnityEngine.ProBuilder.MeshUtility.GeneratePerTriangleMesh(umesh); float time = Time.realtimeSinceStartup; UnwrapParam unwrap = Lightmapping.GetUnwrapParam(mesh.unwrapParameters); Vector2[] uv2 = Unwrapping.GeneratePerTriangleUV(umesh, unwrap); // If GenerateUV2() takes longer than 3 seconds (!), show a warning prompting user to disable auto-uv2 generation. if ((Time.realtimeSinceStartup - time) > 3f) { Log.Warning(string.Format("Generate UV2 for \"{0}\" took {1} seconds! You may want to consider disabling Auto-UV2 generation in the `Preferences > ProBuilder` tab.", mesh.name, (Time.realtimeSinceStartup - time).ToString("F2"))); } if (uv2.Length == vertices.Length) { for (int i = 0; i < uv2.Length; i++) { vertices[i].uv2 = uv2[i]; } } else { Log.Warning("Generate UV2 failed. The returned size of UV2 array != mesh.vertexCount"); } UnityEngine.ProBuilder.MeshUtility.CollapseSharedVertices(umesh, vertices); } else { UnityEngine.ProBuilder.MeshUtility.CollapseSharedVertices(umesh); } if (usedInParticuleSystem) { UnityEngine.ProBuilder.MeshUtility.RestoreParticleSystem(mesh); } } if (s_AutoResizeCollisions) { RebuildColliders(mesh); } if (meshOptimized != null) { meshOptimized(mesh, umesh); } if (Experimental.meshesAreAssets) { TryCacheMesh(mesh); } UnityEditor.EditorUtility.SetDirty(mesh); }
internal static void GenerateLightmapUVsForSelectedMeshFilters(UnwrapParam unwrapParam, bool includeChildren = false) { List <Mesh> meshesToUpdate = new List <Mesh>(); Dictionary <Mesh, Mesh> meshes = new Dictionary <Mesh, Mesh>(); var meshFilters = includeChildren ? Selection.GetFiltered <MeshFilter>(SelectionMode.OnlyUserModifiable | SelectionMode.Deep) : Selection.GetFiltered <MeshFilter>(SelectionMode.OnlyUserModifiable); if (meshFilters.Length == 0) { return; } var undoLvl = Undo.GetCurrentGroup(); Undo.SetCurrentGroupName("Generate Lightmap UVs"); for (int i = 0; i < meshFilters.Length; i++) { EditorUtility.DisplayProgressBar("Unwrapping Lightmap UVs", meshFilters[i].gameObject.name, (float)i / (float)meshFilters.Length); Undo.RecordObject(meshFilters[i], "Unwrap"); // updating existing meshes var path = AssetDatabase.GetAssetPath(meshFilters[i].sharedMesh); if (Path.GetExtension(path) != ".SyncMesh") { if (!meshesToUpdate.Contains(meshFilters[i].sharedMesh)) { Unwrapping.GenerateSecondaryUVSet(meshFilters[i].sharedMesh); meshesToUpdate.Add(meshFilters[i].sharedMesh); } continue; } if (!meshes.ContainsKey(meshFilters[i].sharedMesh)) { var dir = Path.Combine(Path.GetDirectoryName(path), "Lightmapping"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var name = Path.GetFileName(path); var newPath = Path.Combine(dir, Path.GetFileNameWithoutExtension(name) + ".mesh"); Mesh newmesh; if (File.Exists(newPath)) { newmesh = AssetDatabase.LoadAssetAtPath <Mesh>(newPath); } else { newmesh = Object.Instantiate <Mesh>(meshFilters[i].sharedMesh); } Unwrapping.GenerateSecondaryUVSet(newmesh); AssetDatabase.CreateAsset(newmesh, newPath); meshes.Add(meshFilters[i].sharedMesh, newmesh); meshFilters[i].sharedMesh = newmesh; } else { meshFilters[i].sharedMesh = meshes[meshFilters[i].sharedMesh]; } } AssetDatabase.SaveAssets(); EditorUtility.ClearProgressBar(); Undo.CollapseUndoOperations(undoLvl); }
private void OnEnable() { UnwrapParam.SetDefaults(out unwrapParam); }
public void CombineMeshes(Material mat) // -> Combine all the maesh with a specif material. { Meshcombinervtwo myScript = (Meshcombinervtwo)target; GameObject newGameObject = new GameObject(); newGameObject.AddComponent <MeshFilter>(); newGameObject.AddComponent <MeshRenderer>(); newGameObject.GetComponent <Renderer>().sharedMaterial = null; newGameObject.name = "Combine_" + mat.name; Undo.RegisterCreatedObjectUndo(newGameObject, "CombineMat" + mat.name); myScript.list_CreatedObjects.Add(newGameObject); bool OneMesh = false; // This variable is used to know if there is at least one mesh to combine newGameObject.transform.rotation = Quaternion.identity; // Init position to zero newGameObject.transform.SetParent(myScript.transform); newGameObject.transform.localPosition = new Vector3(0, 0, 0); // Init position to Vector3(0,0,0) newGameObject.isStatic = true; MeshFilter[] filters = myScript.gameObject.GetComponentsInChildren <MeshFilter>(); // Find all the children with MeshFilter component Mesh finalMesh = new Mesh(); // Create the new mesh CombineInstance[] combiners = new CombineInstance[filters.Length]; // Struct used to describe meshes to be combined using Mesh.CombineMeshes. for (int i = 0; i < filters.Length; i++) // Check all the children { if (filters[i].transform == myScript.gameObject.transform) // Do not select the parent himself { continue; } if (filters[i].gameObject.GetComponent <Renderer>() == null) // Check if there is Renderer component { continue; } bool checkTag = false; for (int j = 0; j < myScript.list_Tags.Count; j++) // Check tag to know if you need to ignore this gameobject { if (filters[i].gameObject.tag == myScript.list_Tags[j]) { checkTag = true; } } if (mat == filters[i].gameObject.GetComponent <Renderer>().sharedMaterial&& !checkTag && // Add this gameObject to the combiner filters[i].gameObject.GetComponent <Renderer>().enabled) { combiners[i].subMeshIndex = 0; combiners[i].mesh = filters[i].sharedMesh; combiners[i].transform = filters[i].transform.localToWorldMatrix; myScript.list_CombineObjects.Add(filters[i].gameObject); SerializedObject serializedObject3 = new UnityEditor.SerializedObject(filters[i].gameObject.GetComponents <Renderer>()); serializedObject3.Update(); SerializedProperty tmpSer2 = serializedObject3.FindProperty("m_Enabled"); tmpSer2.boolValue = false; serializedObject3.ApplyModifiedProperties(); OneMesh = true; } } finalMesh.CombineMeshes(combiners); // Combine the new mesh newGameObject.GetComponent <MeshFilter>().sharedMesh = finalMesh; // Create the new Mesh Filter newGameObject.GetComponent <Renderer>().material = mat; // ADd the good material if (!OneMesh) // If there is nothing to combine delete the object { if (myScript.gameObject.GetComponent <MeshFilter>()) { myScript.gameObject.GetComponent <MeshFilter>().sharedMesh = null; } } else { UnwrapParam param = new UnwrapParam(); // enable lightmap UnwrapParam.SetDefaults(out param); Unwrapping.GenerateSecondaryUVSet(finalMesh, param); } }
public void DisplayGUI() { MegaScatterMeshTexture mod = (MegaScatterMeshTexture)target; EditorGUILayout.LabelField("Objs: " + mod.objcount + " scattered: " + mod.scattercount + " verts: " + mod.vertcount); mod.seed = EditorGUILayout.IntField("Seed", mod.seed); mod.countmode = (MegaScatterMode)EditorGUILayout.EnumPopup("Count Mode", mod.countmode); mod.Density = EditorGUILayout.FloatField("Density", mod.Density); mod.forcecount = EditorGUILayout.IntField("Count", mod.forcecount); mod.meshPerShape = EditorGUILayout.Toggle("Mesh Per Color", mod.meshPerShape); mod.globalScale = EditorGUILayout.Vector3Field("Global Scale", mod.globalScale); mod.scatterWidth = EditorGUILayout.FloatField("Width", mod.scatterWidth); mod.scatterLength = EditorGUILayout.FloatField("Length", mod.scatterLength); Texture2D scatterTexture = (Texture2D)EditorGUILayout.ObjectField("Texture", mod.scatterTexture, typeof(Texture2D), true); if (scatterTexture != mod.scatterTexture) { if (scatterTexture != null) { string texturePath = AssetDatabase.GetAssetPath(scatterTexture); TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (textureImporter.isReadable) { mod.scatterTexture = scatterTexture; } else { EditorUtility.DisplayDialog("Scatter Texture Select", "Texture is not set to Readable", "OK"); } } else { mod.scatterTexture = scatterTexture; } } mod.alphaDensity = EditorGUILayout.Toggle("Alpha Density", mod.alphaDensity); Texture2D scaleTexture = (Texture2D)EditorGUILayout.ObjectField("Scale", mod.scaleTexture, typeof(Texture2D), true); if (scaleTexture != mod.scaleTexture) { if (scaleTexture != null) { string texturePath = AssetDatabase.GetAssetPath(scaleTexture); TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (textureImporter.isReadable) { mod.scaleTexture = scaleTexture; } else { EditorUtility.DisplayDialog("Scale Texture Select", "Texture is not set to Readable", "OK"); } } else { mod.scaleTexture = scaleTexture; } } mod.mintexscale = EditorGUILayout.Slider("Min Scale", mod.mintexscale, 0.0f, 1.0f); mod.maxtexscale = EditorGUILayout.Slider("Max Scale", mod.maxtexscale, 0.0f, 1.0f); mod.minsizetoadd = EditorGUILayout.Slider("Min Size To Add", mod.minsizetoadd, 0.0f, 1.0f); mod.texturecollider = (Collider)EditorGUILayout.ObjectField("Texture Object", mod.texturecollider, typeof(Collider), true); mod.queryObject = (MegaScatterQuery)EditorGUILayout.ObjectField("Query Object", mod.queryObject, typeof(MegaScatterQuery), true); mod.dostaticbatching = EditorGUILayout.Toggle("Static Batching", mod.dostaticbatching); mod.raycast = EditorGUILayout.BeginToggleGroup("Raycast", mod.raycast); mod.NeedsGround = EditorGUILayout.Toggle("Needs Ground", mod.NeedsGround); mod.collisionOffset = EditorGUILayout.FloatField("Collision Offset", mod.collisionOffset); mod.showignoreobjs = EditorGUILayout.Foldout(mod.showignoreobjs, "Show Ignore Objects"); if (mod.showignoreobjs) { if (GUILayout.Button("Add Ignore Obj")) { mod.ignoreobjs.Add(new MegaScatterCollisionObj()); } EditorGUILayout.BeginVertical("box"); EditorGUILayout.LabelField("Ignore Objects"); for (int i = 0; i < mod.ignoreobjs.Count; i++) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("" + i + ":", GUILayout.MaxWidth(20)); GUILayout.Label("On", GUILayout.MaxWidth(20)); mod.ignoreobjs[i].active = EditorGUILayout.Toggle("", mod.ignoreobjs[i].active, GUILayout.MaxWidth(20)); GUILayout.Label("Children", GUILayout.MaxWidth(52)); mod.ignoreobjs[i].includechildren = EditorGUILayout.Toggle("", mod.ignoreobjs[i].includechildren, GUILayout.MaxWidth(20)); mod.ignoreobjs[i].collider = (Collider)EditorGUILayout.ObjectField("", mod.ignoreobjs[i].collider, typeof(Collider), true, GUILayout.MaxWidth(180)); //mod.ignoreobjs[i] = (Collider)EditorGUILayout.ObjectField("" + i + ":", mod.ignoreobjs[i], typeof(Collider), true); if (GUILayout.Button("Delete", GUILayout.MaxWidth(50))) { mod.ignoreobjs.RemoveAt(i); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } if (mod.raycast) { if (mod.surfaces.Count == 0) { EditorGUILayout.HelpBox("No Surface Objects Defined! No Objects will be scattered", MessageType.Info, true); } } mod.showsurfaceobjs = EditorGUILayout.Foldout(mod.showsurfaceobjs, "Show Surface Objects"); if (mod.showsurfaceobjs) { if (GUILayout.Button("Add Surface Obj")) { mod.surfaces.Add(new MegaScatterCollisionObj()); } EditorGUILayout.BeginVertical("box"); EditorGUILayout.LabelField("Surface Objects"); for (int i = 0; i < mod.surfaces.Count; i++) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("" + i + ":"); mod.surfaces[i].active = EditorGUILayout.Toggle("", mod.surfaces[i].active, GUILayout.MaxWidth(20)); mod.surfaces[i].collider = (Collider)EditorGUILayout.ObjectField("", mod.surfaces[i].collider, typeof(Collider), true); mod.surfaces[i].prebuildenable = EditorGUILayout.Toggle("", mod.surfaces[i].prebuildenable, GUILayout.MaxWidth(20)); mod.surfaces[i].postbuilddisable = EditorGUILayout.Toggle("", mod.surfaces[i].postbuilddisable, GUILayout.MaxWidth(20)); //mod.ignoreobjs[i] = (Collider)EditorGUILayout.ObjectField("" + i + ":", mod.ignoreobjs[i], typeof(Collider), true); if (GUILayout.Button("Delete", GUILayout.MaxWidth(50))) { mod.surfaces.RemoveAt(i); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndToggleGroup(); mod.hideObjects = EditorGUILayout.Toggle("Hide Objects", mod.hideObjects); mod.buildOnStart = EditorGUILayout.Toggle("Build on Start", mod.buildOnStart); mod.useCoRoutine = EditorGUILayout.Toggle("Scatter Over Frames", mod.useCoRoutine); mod.NumPerFrame = EditorGUILayout.IntField("Number Per Frame", mod.NumPerFrame); mod.colorMesh = EditorGUILayout.Toggle("Color Mesh", mod.colorMesh); mod.displaygizmo = EditorGUILayout.Toggle("Display Gizmo", mod.displaygizmo); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Hide/Show Objects")) { mod.HideShow(); } if (GUILayout.Button("Remove Objects")) { mod.RemoveObjects(); } if (GUILayout.Button("Add Mesh")) { MegaScatterLayer inf = new MegaScatterLayer(); mod.layers.Add(inf); mod.currentEdit = mod.layers.Count - 1; } EditorGUILayout.EndHorizontal(); mod.showlightmap = EditorGUILayout.Foldout(mod.showlightmap, "Lightmap Params"); if (mod.showlightmap) { mod.genLightMap = EditorGUILayout.BeginToggleGroup("Lightmap Enable", mod.genLightMap); mod.angleError = EditorGUILayout.Slider("Angle Error", mod.angleError, 0.0f, 1.0f); mod.areaError = EditorGUILayout.Slider("Area Error", mod.areaError, 0.0f, 1.0f); mod.hardAngle = EditorGUILayout.FloatField("Hard Angle", mod.hardAngle); mod.packMargin = EditorGUILayout.FloatField("Pack Margin", mod.packMargin); if (GUILayout.Button("Build Lightmap UVS")) { if (mod.genLightMap) { UnwrapParam uv = new UnwrapParam(); //UnwrapParam.SetDefaults(out uv); uv.angleError = mod.angleError; uv.areaError = mod.areaError; uv.hardAngle = mod.hardAngle; uv.packMargin = mod.packMargin; int count = mod.gameObject.transform.childCount; //GetChildCount(); for (int c = 0; c < count; c++) { float a = (float)c / (float)count; if (EditorUtility.DisplayCancelableProgressBar("Building LightMap UVs", "Mesh " + c + " of " + count, a)) { break; } GameObject obj = mod.gameObject.transform.GetChild(c).gameObject; MeshFilter mf = obj.GetComponent <MeshFilter>(); if (mf) { Mesh mesh = mf.sharedMesh; if (mesh) { Unwrapping.GenerateSecondaryUVSet(mesh, uv); } } } EditorUtility.ClearProgressBar(); } } EditorGUILayout.EndToggleGroup(); } mod.showadvanced = EditorGUILayout.Foldout(mod.showadvanced, "Advanced"); if (mod.showadvanced) { mod.FailCount = EditorGUILayout.IntField("Fail Count", mod.FailCount); mod.PosFailCount = EditorGUILayout.IntField("Pos Fail Count", mod.PosFailCount); } EditorGUILayout.BeginVertical("box"); EditorGUILayout.LabelField("Layers"); for (int i = 0; i < mod.layers.Count; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("" + i + " - " + mod.layers[i].LayerName); mod.layers[i].Enabled = EditorGUILayout.Toggle("", mod.layers[i].Enabled, GUILayout.MaxWidth(20)); if (GUILayout.Button("Edit", GUILayout.MaxWidth(50))) { mod.currentEdit = i; EditorUtility.SetDirty(mod); } if (GUILayout.Button("Delete", GUILayout.MaxWidth(50))) { mod.layers.RemoveAt(i); } if (GUILayout.Button("U", GUILayout.MaxWidth(20))) { if (i > 0) { MegaScatterMeshEditor.SwapInf(mod, i, i - 1); } } if (GUILayout.Button("D", GUILayout.MaxWidth(22))) { if (i < mod.layers.Count - 1) { MegaScatterMeshEditor.SwapInf(mod, i, i + 1); } } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); GUI.backgroundColor = Color.green; if (GUILayout.Button("Update", GUILayout.Height(30))) { mod.update = true; EditorUtility.SetDirty(target); } GUI.backgroundColor = Color.white; if (mod.currentEdit >= mod.layers.Count) { mod.currentEdit = mod.layers.Count - 1; EditorUtility.SetDirty(mod); } int ci = mod.currentEdit; if (ci >= 0) { MegaScatterLayer inf = mod.layers[ci]; EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Copy", GUILayout.Width(50))) { MegaScatterLayer.copylayer = inf; } if (MegaScatterLayer.copylayer != null) { if (GUILayout.Button("Paste from " + MegaScatterLayer.copylayer.LayerName)) { inf.Copy(MegaScatterLayer.copylayer); } } EditorGUILayout.EndHorizontal(); inf.LayerName = EditorGUILayout.TextField("Name", inf.LayerName); inf.Enabled = EditorGUILayout.BeginToggleGroup("Enabled", inf.Enabled); inf.markstatic = EditorGUILayout.Toggle("Mark Static", inf.markstatic); EditorGUILayout.BeginVertical("box"); if (GUILayout.Button("Add Color Mask")) { inf.scattercols.Add(new MegaScatterCol()); } for (int cv = 0; cv < inf.scattercols.Count; cv++) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("Mask Col " + cv + ":"); inf.scattercols[cv].lowcol = EditorGUILayout.ColorField("", inf.scattercols[cv].lowcol, GUILayout.MaxWidth(50)); inf.scattercols[cv].highcol = EditorGUILayout.ColorField("", inf.scattercols[cv].highcol, GUILayout.MaxWidth(50)); if (GUILayout.Button("Delete", GUILayout.MaxWidth(50))) { inf.scattercols.RemoveAt(cv); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); inf.obj = (GameObject)EditorGUILayout.ObjectField("Object", inf.obj, typeof(GameObject), true); inf.forcecount = EditorGUILayout.IntField("Force Count", inf.forcecount); inf.maxcount = EditorGUILayout.IntField("Max Count", inf.maxcount); inf.weight = EditorGUILayout.FloatField("Weight", inf.weight); inf.scale = EditorGUILayout.FloatField("Scale", inf.scale); inf.offsetLow = EditorGUILayout.Vector3Field("Offset Low", inf.offsetLow); inf.offsetHigh = EditorGUILayout.Vector3Field("Offset High", inf.offsetHigh); inf.prerot = EditorGUILayout.Vector3Field("Pre Rot", inf.prerot); inf.rotLow = EditorGUILayout.Vector3Field("Rot Low", inf.rotLow); inf.rotHigh = EditorGUILayout.Vector3Field("Rot High", inf.rotHigh); inf.uniformScaling = EditorGUILayout.Toggle("Uniform Scaling", inf.uniformScaling); if (inf.uniformScaling) { inf.uniscalemode = (MegaScatterScaleMode)EditorGUILayout.EnumPopup("Mode", inf.uniscalemode); inf.uniscaleLow = EditorGUILayout.FloatField("Scale Low", inf.uniscaleLow); inf.uniscaleHigh = EditorGUILayout.FloatField("Scale High", inf.uniscaleHigh); } else { inf.scaleLow = EditorGUILayout.Vector3Field("Scale Low", inf.scaleLow); inf.scaleHigh = EditorGUILayout.Vector3Field("Scale High", inf.scaleHigh); } inf.snap = EditorGUILayout.Vector3Field("Snap", inf.snap); inf.snapRot = EditorGUILayout.Vector3Field("Snap Rot", inf.snapRot); inf.distCrv = EditorGUILayout.CurveField("Dist Curve", inf.distCrv); inf.seed = EditorGUILayout.IntField("Seed", inf.seed); inf.noOverlap = EditorGUILayout.Toggle("No Overlap", inf.noOverlap); inf.clearOverlap = EditorGUILayout.Toggle("Clear Overlap", inf.clearOverlap); inf.radius = EditorGUILayout.FloatField("Radius", inf.radius); inf.colradiusadj = EditorGUILayout.FloatField("Col Radius Adj", inf.colradiusadj); inf.raycount = EditorGUILayout.IntSlider("Ray Count", inf.raycount, 1, 8); inf.align = EditorGUILayout.Slider("Align", inf.align, 0.0f, 1.0f); inf.minslope = EditorGUILayout.Slider("Min Slope", inf.minslope, 0.0f, 90.0f); inf.maxslope = EditorGUILayout.Slider("Max Slope", inf.maxslope, 0.0f, 90.0f); inf.collisionOffset = EditorGUILayout.FloatField("Collision Offset", inf.collisionOffset); inf.useheight = EditorGUILayout.BeginToggleGroup("Use Height Limits", inf.useheight); inf.minheight = EditorGUILayout.FloatField("Min Height", inf.minheight); inf.maxheight = EditorGUILayout.FloatField("Max Height", inf.maxheight); EditorGUILayout.EndToggleGroup(); if (mod.colorMesh) { inf.colcurve = EditorGUILayout.CurveField("Col Curve", inf.colcurve); inf.showcolvari = EditorGUILayout.Foldout(inf.showcolvari, "Color Variations"); if (inf.showcolvari) { EditorGUILayout.BeginVertical("box"); Texture2D colorTexture = (Texture2D)EditorGUILayout.ObjectField("Color", inf.colorTexture, typeof(Texture2D), true); if (colorTexture != inf.colorTexture) { if (colorTexture != null) { string texturePath = AssetDatabase.GetAssetPath(colorTexture); TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (textureImporter.isReadable) { inf.colorTexture = colorTexture; } else { EditorUtility.DisplayDialog("Color Texture Select", "Texture is not set to Readable", "OK"); } } else { inf.colorTexture = colorTexture; } } if (GUILayout.Button("Add Color")) { inf.colvariations.Add(Color.white); } for (int cv = 0; cv < inf.colvariations.Count; cv++) { EditorGUILayout.BeginHorizontal(); inf.colvariations[cv] = EditorGUILayout.ColorField("" + cv + ":", inf.colvariations[cv]); if (GUILayout.Button("Delete", GUILayout.MaxWidth(50))) { inf.colvariations.RemoveAt(cv); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } } inf.vertexlimit = EditorGUILayout.IntSlider("Vertex Limit", inf.vertexlimit, 1000, 65535); inf.buildtangents = EditorGUILayout.Toggle("Build Tangents", inf.buildtangents); inf.nocollider = EditorGUILayout.Toggle("No Collider", inf.nocollider); inf.buildcollider = EditorGUILayout.Toggle("Build Collider", inf.buildcollider); inf.proxymesh = (Mesh)EditorGUILayout.ObjectField("Collider Mesh", inf.proxymesh, typeof(Mesh), true); inf.vertexnoise = EditorGUILayout.BeginToggleGroup("Vertex Noise", inf.vertexnoise); inf.noisescale = EditorGUILayout.FloatField("Noise Scale", inf.noisescale); inf.strength = EditorGUILayout.Vector3Field("Strength", inf.strength); EditorGUILayout.EndToggleGroup(); EditorGUILayout.EndToggleGroup(); if (GUILayout.Button("Delete")) { mod.layers.RemoveAt(ci); mod.currentEdit = 0; EditorUtility.SetDirty(mod); } EditorGUILayout.EndVertical(); GUI.backgroundColor = Color.green; if (GUILayout.Button("Update", GUILayout.Height(30))) { mod.update = true; EditorUtility.SetDirty(target); } GUI.backgroundColor = Color.white; } }
static string QuadsToMesh( MeshFilter mf, // output mesh filter quadByUV quads, // input structure -> quads string undoTitle // title for undo operation ) { // output a quad list to a mesh structure if (mf == null || // no output MeshFilter quads == null || // OR no quad list quads.Count <= 0) // OR no quad entries { return(""); } // get original asset path and convert to a path we can load from/save to string path = AssetDatabase.GetAssetPath(mf.sharedMesh); string suffix = path.Substring(path.LastIndexOf(".")); string name = path.Replace(suffix, ".asset"); // get a previous instance of the mesh. if none, create new asset at path. Mesh m = AssetDatabase.LoadAssetAtPath <Mesh>(name); if (m == null) { // no old asset could be loaded. create new asset with new GUID. AssetDatabase.CreateAsset(new Mesh(), name); // create file in DB AssetDatabase.SaveAssets(); // save changes AssetDatabase.Refresh(); // update DB m = AssetDatabase.LoadAssetAtPath <Mesh>(name); // reload from new path } // now dump every quad into the mesh. decimate vertices by only saving unique sets HashSet <Vertex> allVertices = new HashSet <Vertex>(); // unique vertex entries of (P,N,UV) List <List <Vertex> > allQuads = new List <List <Vertex> >(); // list of quad faces for indexing foreach (Vector2 UV in quads.Keys) // by UV color { foreach (Vector3 N in quads[UV].Keys) // by normal direction { foreach (float r in quads[UV][N].Keys) // by row { foreach (HashSet <Vector3> A in quads[UV][N][r]) // for every "quad vertex set A" { // dump every quads contents into the lists // get clockwise winding, create vertex entries List <Vector3> v = SortVerticesClockwise(A, N); // raw A,B,C,D vectors List <Vertex> e = new List <Vertex>(); // face vertex entries foreach (Vector3 p in v) // create vertex entry { e.Add(new Vertex(p, N, UV)); } allVertices.UnionWith(e); // add them to the global list // now create the references and add them to the face list List <Vertex> singleQuad = new List <Vertex>(); singleQuad.AddRange // add vertex-links for A+B triangle (new Vertex[] { e[0], e[1], e[2], e[0], e[2], e[3] }); allQuads.Add(singleQuad); // add to global quad face list } } } } // convert the vertex lists to arrays. (V,N,UV)-lists have to be of same size (WTF, Unity?) List <Vertex> entries = new List <Vertex>(allVertices); List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Color32> colors = new List <Color32>(); foreach (Vertex e in entries) { e.Dump(vertices, normals, uvs, colors); } // relink the faces to a proper index into the dumped lists List <int> faces = new List <int>(); foreach (List <Vertex> vertexIndices in allQuads) { foreach (Vertex e in vertexIndices) { faces.Add(entries.IndexOf(e)); } } // set final contents of output mesh m.Clear(); // clear old contents first m.vertices = vertices.ToArray(); // vertices m.normals = normals.ToArray(); // normals m.uv = uvs.ToArray(); // UV1 m.colors32 = colors.ToArray(); // vertex colors m.SetTriangles(faces.ToArray(), 0); // triangles indices // optimize structures m.Optimize(); m.RecalculateBounds(); // generate lightmap set as UV2 UnwrapParam up; // unwrapping parameters UnwrapParam.SetDefaults(out up); // set to default up.hardAngle *= 4; // increase hard angles for less seams up.packMargin *= 4; // increase margin (otherwise: black streaks) Unwrapping.GenerateSecondaryUVSet(m, up); // generate UV2 // save changes, update AssetDatabase again AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); // update the MeshFilter to use the generated mesh Undo.RecordObject(mf, undoTitle); mf.sharedMesh = m; // check if we have to update a MeshCollider as well MeshCollider mc = mf.GetComponent <MeshCollider>(); if (mc != null) { // if a MeshCollider is present, also update it's shared mesh Undo.RecordObject(mc, undoTitle); mc.sharedMesh = m; } // return the title of the converted new mesh asset return(name); }