Compare commits

...

4 Commits

Author SHA1 Message Date
Dominik Gut
3583fc0d97 Splash image fixed 2025-05-16 16:09:24 +02:00
Dominik Gut
c4068122ce Menu Scroll Bug fixed 2025-05-16 14:46:30 +02:00
Dominik Gut
7ee781a0e6 Update Grotto1-3 (Lightmaps, Videos on 'no-postprocessing'-layer, Menukarte) 2025-05-16 08:45:54 +02:00
Dominik Gut
89d90bb274 Grotto2 (Küche) drawcalls reduced (meshes combined) + Package Easy Mesh Combiner 2025-05-16 05:46:47 +02:00
576 changed files with 85143 additions and 540377 deletions

View File

@ -25,7 +25,6 @@ Material:
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _METALLICSPECGLOSSMAP
- _NORMALMAP
m_InvalidKeywords: []
m_LightmapFlags: 4
@ -68,7 +67,7 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: cfbfeafcbb7c2db488438b88670b6be9, type: 3}
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
@ -120,7 +119,7 @@ Material:
- _Parallax: 0.02
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.486
- _Smoothness: 0.255
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

View File

@ -37,8 +37,8 @@ Material:
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: -2}
m_Offset: {x: 0, y: 1.06}
m_Scale: {x: 1, y: -1}
m_Offset: {x: 0, y: 1}
- _MainTex_R:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

View File

@ -69,7 +69,7 @@ TextureImporter:
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -45,7 +45,7 @@ TextureImporter:
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -45,7 +45,7 @@ TextureImporter:
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
spriteMeshType: 0
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b8b440160a98d1f489a9cc9d8aee405c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b2e7fc1fa2e07934e81429c1e0e78b4e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 025b94e332aaa3f439e82fc54a16dc42
timeCreated: 1575203498
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: fdf2798169aa8b849b8945135b07c507
timeCreated: 1575203542
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2d42cc6f949491249a7b0cab7d8b97f7
folderAsset: yes
timeCreated: 1548710849
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6e3c7d63750a70841b786c043ffce964
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,87 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using UnityEditor.Build;
public class EasyMeshCombinerCompressedTextures : AssetPostprocessor, IActiveBuildTargetChanged
{
//This class manages the Compressed Textures generated by merge done in the Editor, creating
//Compressed Textures for the merges, according to the Platform currently active in the Editor.
//This code is executed automatically by the editor whenever an asset is imported.
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
{
//Prepare the list of imported assets of compressed textures
List<string> compressedTextureImportedAssets = new List<string>();
//Check all new imported assets...
foreach (string assetPath in importedAssets)
if (assetPath.ToLower().Contains("/mt assets/_assetsdata/atlases") == true)
compressedTextureImportedAssets.Add(assetPath);
//Process each compressed texture generated by EMC merge done in Editor
foreach (string assetPath in compressedTextureImportedAssets)
if (assetPath.Contains("EMC-NMin") == true || assetPath.Contains("EMC-HMin") == true)
{
//Skip this asset if is a RAW texture, uncompressed
if (assetPath.Contains("RAW.asset") == true)
continue;
//Create a copy of this texture, but in raw state, if not have
if (File.Exists(("Assets/Plugins/MT Assets/_AssetsData/Atlases/" + Path.GetFileNameWithoutExtension(assetPath) + " RAW.asset")) == false)
AssetDatabase.CopyAsset(assetPath, ("Assets/Plugins/MT Assets/_AssetsData/Atlases/" + Path.GetFileNameWithoutExtension(assetPath) + " RAW.asset"));
//Load the raw version of this texture
Texture2D rawTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(assetPath.Replace(".asset", " RAW.asset"), typeof(Texture2D));
//Load the pixels of raw texture
Color[] rawTexturePixels = rawTexture.GetPixels();
//Check if the raw texture have alpha
bool rawTextureHaveAlpha = false;
foreach (Color pixel in rawTexturePixels)
if (pixel.a < 1.0f)
{
rawTextureHaveAlpha = true;
break;
}
//If is a Normal Map raw texture, inform that have a alpha, to ensure best quality on normal map
if (rawTexture.isDataSRGB == false) //<- Normal Maps use Linear instead of sRGB
rawTextureHaveAlpha = true;
//Detect the color format to use for the copy compressed texture
TextureFormat targetFormat = TextureFormat.Alpha8;
if (rawTextureHaveAlpha == true)
targetFormat = TextureFormat.RGBA32;
if (rawTextureHaveAlpha == false)
targetFormat = TextureFormat.RGB24;
//Copy the raw version of this texture and compress it to desired compression level (RGBA32 to DXT5/ETC2 and RGB24 to DXT1/ETC1)
Texture2D tempTexture = new Texture2D(rawTexture.width, rawTexture.height, targetFormat, rawTexture.mipmapCount, (!rawTexture.isDataSRGB));
tempTexture.SetPixels(0, 0, rawTexture.width, rawTexture.height, rawTexturePixels, 0);
tempTexture.Apply();
if (assetPath.Contains("EMC-NMin") == true)
tempTexture.Compress(false);
if (assetPath.Contains("EMC-HMin") == true)
tempTexture.Compress(true);
//Overwrite the texture used by merge, to be the new compressed texture
if (!AssetDatabase.IsValidFolder("Assets/Plugins/MT Assets/_AssetsData/Atlases/Temp"))
AssetDatabase.CreateFolder("Assets/Plugins/MT Assets/_AssetsData/Atlases", "Temp");
AssetDatabase.CreateAsset(tempTexture, ("Assets/Plugins/MT Assets/_AssetsData/Atlases/Temp/" + Path.GetFileNameWithoutExtension(assetPath) + ".asset"));
File.Delete(assetPath);
File.Move(("Assets/Plugins/MT Assets/_AssetsData/Atlases/Temp/" + Path.GetFileNameWithoutExtension(assetPath) + ".asset"), assetPath);
File.Delete(("Assets/Plugins/MT Assets/_AssetsData/Atlases/Temp/" + Path.GetFileNameWithoutExtension(assetPath) + ".asset.meta"));
}
//Update the asset database
AssetDatabase.Refresh();
}
public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget)
{
//Force reimport the Atlases folder of MT Assets
AssetDatabase.ImportAsset("Assets/Plugins/MT Assets/_AssetsData/Atlases", ImportAssetOptions.ImportRecursive | ImportAssetOptions.DontDownloadFromCacheServer);
AssetDatabase.Refresh();
}
public int callbackOrder { get { return 0; } }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5e69d6a5f3b0a04ea22ae7b3887f0f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c620b7e1afbd8a942a487e6bacd8404b
folderAsset: yes
timeCreated: 1571441202
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,166 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MTAssets.EasyMeshCombiner.Editor
{
/*
* This script is the Dataset of the scriptable object "Preferences". This script saves Easy Mesh Combiner preferences.
*/
public class MeshCombinerPreferences : ScriptableObject
{
public enum AfterMerge
{
DisableOriginalMeshes,
DeactiveOriginalGameObjects,
DoNothing
}
public enum MergeMethod
{
OneMeshPerMaterial,
AllInOne,
JustMaterialColors
}
public enum AtlasSize
{
Pixels32x32,
Pixels64x64,
Pixels128x128,
Pixels256x256,
Pixels512x512,
Pixels1024x1024,
Pixels2048x2048,
Pixels4096x4096,
Pixels8192x8192
}
public enum MipMapEdgesSize
{
Pixels0x0,
Pixels16x16,
Pixels32x32,
Pixels64x64,
Pixels128x128,
Pixels256x256,
Pixels512x512,
Pixels1024x1024,
}
public enum AtlasPadding
{
Pixels0x0,
Pixels2x2,
Pixels4x4,
Pixels8x8,
Pixels16x16,
}
public enum MergeTiledTextures
{
SkipAll,
LegacyMode
}
public enum TextureCompression
{
Disabled,
NormalQuality,
HighQuality
}
public enum LightmapMode
{
RecycleData,
GenerateData
}
public enum MaterialGlobalIllumination
{
None,
Realtime,
Baked
}
[System.Serializable]
public class OneMeshPerMaterialParams
{
public bool addMeshCollider = false;
}
[System.Serializable]
public class AllInOneParams
{
public Material materialToUse;
public int maxTexturesPerAtlas = 12;
public AtlasSize atlasResolution = AtlasSize.Pixels1024x1024;
public MipMapEdgesSize mipMapEdgesSize = MipMapEdgesSize.Pixels64x64;
public AtlasPadding atlasPadding = AtlasPadding.Pixels0x0;
public MergeTiledTextures mergeTiledTextures = MergeTiledTextures.LegacyMode;
public bool useDefaultMainTextureProperty = true;
public string mainTexturePropertyToFind = "_MainTex";
public string mainTexturePropertyToInsert = "_MainTex";
public bool materialColorSupport = false;
public string materialColorPropertyToFind = "_Color";
public bool metallicMapSupport = false;
public string metallicMapPropertyToFind = "_MetallicGlossMap";
public string metallicMapPropertyToInsert = "_MetallicGlossMap";
public bool specularMapSupport = false;
public string specularMapPropertyToFind = "_SpecGlossMap";
public string specularMapPropertyToInsert = "_SpecGlossMap";
public bool normalMapSupport = false;
public string normalMapPropertyToFind = "_BumpMap";
public string normalMapPropertyToInsert = "_BumpMap";
public bool normalMap2Support = false;
public string normalMap2PropertyFind = "_DetailNormalMap";
public string normalMap2PropertyToInsert = "_DetailNormalMap";
public bool heightMapSupport = false;
public string heightMapPropertyToFind = "_ParallaxMap";
public string heightMapPropertyToInsert = "_ParallaxMap";
public bool occlusionMapSupport = false;
public string occlusionMapPropertyToFind = "_OcclusionMap";
public string occlusionMapPropertyToInsert = "_OcclusionMap";
public bool detailAlbedoMapSupport = false;
public string detailMapPropertyToFind = "_DetailAlbedoMap";
public string detailMapPropertyToInsert = "_DetailAlbedoMap";
public bool detailMaskSupport = false;
public string detailMaskPropertyToFind = "_DetailMask";
public string detailMaskPropertyToInsert = "_DetailMask";
public bool emissionMapSupport = false;
public string emissionMapPropertyToFind = "_EmissionMap";
public string emissionMapPropertyToInsert = "_EmissionMap";
public string emissionColorPropertyToFind = "_EmissionColor";
public MaterialGlobalIllumination emissionLightType = MaterialGlobalIllumination.None;
public bool pinkNormalMapsFix = true;
public TextureCompression textureCompression = TextureCompression.Disabled;
public bool addMeshCollider = false;
public bool highlightUvVertices = false;
}
[System.Serializable]
public class JustMaterialColorsParams
{
public Material materialToUse;
public bool useDefaultColorProperty = true;
public string colorPropertyToFind = "_Color";
public string mainTexturePropertyToInsert = "_MainTex";
public TextureCompression textureCompression = TextureCompression.Disabled;
public bool addMeshCollider = false;
}
public string projectName;
public Rect windowPosition;
public bool representLogsInScene = true;
public AfterMerge afterMerge = AfterMerge.DisableOriginalMeshes;
public MergeMethod mergeMethod = MergeMethod.OneMeshPerMaterial;
public OneMeshPerMaterialParams oneMeshPerMaterialParams = new OneMeshPerMaterialParams();
public AllInOneParams allInOneParams = new AllInOneParams();
public JustMaterialColorsParams justMaterialColorsParams = new JustMaterialColorsParams();
public bool combineChildrens = true;
public bool combineInactives = false;
public bool lightmapSupport = false;
public LightmapMode lightmapMode = LightmapMode.GenerateData;
public bool lightmapUseDefaultGenerationParams = true;
public float lightmapParamAngleError = 0.08f; //default: 0.08
public float lightmapParamAreaError = 0.15f; //default: 0.15
public float lightmapParamHardAngle = 88.0f; //default: 88.0
public float lightmapParamPackMargin = 0.04f; //default: 0.04
public bool saveMeshInAssets = true;
public bool savePrefabOfThis = false;
public string prefabName = "prefab";
public string nameOfThisMerge = "Combined Meshes";
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 9168bd0e7d7ff4e409b67e0c31e28ca7
timeCreated: 1571441231
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,105 @@
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
namespace MTAssets.EasyMeshCombiner.Editor
{
/*
* This class is responsible for displaying the welcome message when installing this asset.
*/
[InitializeOnLoad]
class Greetings
{
//This asset parameters
public static string assetName = "Easy Mesh Combiner";
public static string pathForThisAsset = "Assets/Plugins/MT Assets/Easy Mesh Combiner";
public static string pathForThisAssetDocumentation = "/_Documentation/Documentation (Open With Browser).html";
public static string optionalObservation = "";
public static string pathToGreetingsFile = "Assets/Plugins/MT Assets/_AssetsData/Greetings/GreetingsData.Emc.ini";
public static string linkForAssetStorePage = "https://assetstore.unity.com/publishers/40306";
public static string linkForDiscordCommunity = "https://discord.gg/44aGAt4Sv4";
//Greetings script methods
static Greetings()
{
//Run the script after Unity compiles
EditorApplication.delayCall += Run;
}
static void Run()
{
//Create base directory "_AssetsData" and "Greetings" if not exists yet
CreateBaseDirectoriesIfNotExists();
//Verify if the greetings message already showed, if not yet, show the message
VerifyAndShowAssetGreentingsMessageIfNeverShowedYet();
}
public static void CreateBaseDirectoriesIfNotExists()
{
//Create the directory to feedbacks folder, of this asset
if (!AssetDatabase.IsValidFolder("Assets/Plugins/MT Assets"))
AssetDatabase.CreateFolder("Assets/Plugins", "MT Assets");
if (!AssetDatabase.IsValidFolder("Assets/Plugins/MT Assets/_AssetsData"))
AssetDatabase.CreateFolder("Assets/Plugins/MT Assets", "_AssetsData");
if (!AssetDatabase.IsValidFolder("Assets/Plugins/MT Assets/_AssetsData/Greetings"))
AssetDatabase.CreateFolder("Assets/Plugins/MT Assets/_AssetsData", "Greetings");
}
public static void VerifyAndShowAssetGreentingsMessageIfNeverShowedYet()
{
//If the greetings file not exists
if (AssetDatabase.LoadAssetAtPath(pathToGreetingsFile, typeof(object)) == null)
{
//Create a new greetings file
File.WriteAllText(pathToGreetingsFile, "Done");
//Show greetings and save
Regex regexFilter = new Regex("Assets/");
bool optionClicked = EditorUtility.DisplayDialog(assetName + " was imported!",
"The " + assetName + " was imported for your project. Please do not change the directory of the files for this asset. You should be able to locate it in the folder \"" + regexFilter.Replace(pathForThisAsset, "", 1) + "\"" +
"\n\n" +
((string.IsNullOrEmpty(optionalObservation) == false) ? optionalObservation + "\n\n" : "") +
"Remember to read the documentation to understand how to use this asset and get the most out of it!" +
"\n\n" +
"You can get support at email (mtassets@windsoft.xyz)" +
"\n\n" +
"- Thank you for purchasing the asset! :)",
"Ok, Cool!", "Open Documentation");
//If clicked on "Ok, Cool!"
if (optionClicked == true)
{
//Select the folder of project
UnityEngine.Object assetFolder = (UnityEngine.Object)AssetDatabase.LoadAssetAtPath(pathForThisAsset, typeof(UnityEngine.Object));
Selection.activeObject = assetFolder;
EditorGUIUtility.PingObject(assetFolder);
}
//If clicked on "Open Documentation"
if (optionClicked == false)
{
//Select the folder of project
UnityEngine.Object docItem = (UnityEngine.Object)AssetDatabase.LoadAssetAtPath(pathForThisAsset + pathForThisAssetDocumentation, typeof(UnityEngine.Object));
Selection.activeObject = docItem;
EditorGUIUtility.PingObject(docItem);
AssetDatabase.OpenAsset(docItem);
}
//Show discord MT Assets Community invite
bool joinOptionClicked = EditorUtility.DisplayDialog("MT Assets Community on Discord",
"The MT Assets Community on Discord is a place where you can get support for the MT Assets tools, you will also be able to send suggestions, ask questions, find out about news in advance and " +
"interact with the community of devs and customers who also use MT Assets tools. It is worth checking!\n\nWould you like to join the MT Assets Community on Discord?",
"Join MT Assets Community on Discord!", "No, thank you");
//If clicked on Join the Community
if (joinOptionClicked == true)
Help.BrowseURL(Greetings.linkForDiscordCommunity);
//Update files
AssetDatabase.Refresh();
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2039de207d96fa1418fca3e37e0bb85c
timeCreated: 1544918828
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3d2d03a6fac17c044a82a57721605f21
folderAsset: yes
timeCreated: 1571665254
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 06319526e165e4c4b9d1e530e0f1110e
timeCreated: 1571778662
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 3cc9f4f19194bb14eb0be711ed2210b1
timeCreated: 1572052278
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: d4b9f5cbc67a57c48a0fc92b9b22ac5f
timeCreated: 1571665267
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 8bce6b5d631d70c48807b8ac203c5392
timeCreated: 1572052559
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,103 @@
fileFormatVersion: 2
guid: e91200c7f48a7ca4ea58d3d21eeac124
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,86 @@
using UnityEngine;
using UnityEditor;
using System.IO;
namespace MTAssets.EasyMeshCombiner.Editor
{
/*
* This class is responsible for creating the menu for this asset.
*/
public class Menu : MonoBehaviour
{
//Right click menu items
[MenuItem("GameObject/Combine Meshes", false, 30)]
static void OpenMeshCombinerToolWithHierarchy()
{
MeshCombinerTool.OpenWindow();
}
//Menu items
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/Mesh Combiner Tool", false, 10)]
static void OpenMeshCombinerTool()
{
MeshCombinerTool.OpenWindow();
}
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/View Changelog", false, 10)]
static void OpenChangeLog()
{
string filePath = Greetings.pathForThisAsset + "/List Of Changes.txt";
if (File.Exists(filePath) == true)
AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath(filePath, typeof(TextAsset)));
if (File.Exists(filePath) == false)
EditorUtility.DisplayDialog(
"Error",
"Unable to open file. The file has been deleted, or moved. Please, to correct this problem and avoid future problems with this tool, remove the directory from this asset and install it again.",
"Ok");
}
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/Read Documentation", false, 30)]
static void ReadDocumentation()
{
EditorUtility.DisplayDialog(
"Read Documentation",
"The Documentation HTML file will open in your default application.",
"Cool!");
string filePath = Greetings.pathForThisAsset + Greetings.pathForThisAssetDocumentation;
if (File.Exists(filePath) == true)
AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath(filePath, typeof(TextAsset)));
if (File.Exists(filePath) == false)
EditorUtility.DisplayDialog(
"Error",
"Unable to open file. The file has been deleted, or moved. Please, to correct this problem and avoid future problems with this tool, remove the directory from this asset and install it again.",
"Ok");
}
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/More Assets", false, 30)]
static void MoreAssets()
{
Help.BrowseURL(Greetings.linkForAssetStorePage);
}
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/Get Support", false, 30)]
static void GetSupport()
{
EditorUtility.DisplayDialog(
"Support",
"If you have any questions, problems or want to contact me, just contact me by email (mtassets@windsoft.xyz).",
"Got it!");
}
[MenuItem("Tools/MT Assets/Easy Mesh Combiner/Discord Community", false, 30)]
static void JoinTheCommunity()
{
Help.BrowseURL(Greetings.linkForDiscordCommunity);
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b407ff593966f6e4397dd7a063a34846
timeCreated: 1544916341
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6d4806b6822fe964fb927325da05511c
timeCreated: 1548711569
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cb17cc495afdfac40a1054a82a4ce260
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2062e948587d34a49b904451e71686f2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,99 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;
namespace MTAssets.EasyMeshCombiner
{
/*
* This is a script that is part of the essential library for "MT Assets" assets.
*/
[AddComponentMenu("")] //Hide this script in component menu.
public class MTAssetsEditorUi : MonoBehaviour
{
#if UNITY_EDITOR
//Public methods
//This method disable gizmo of a script that have a icon
public static bool DisableGizmosInSceneView(string scriptClassNameToDisable, bool isGizmosDisabled)
{
/*
* This method disables Gizmos in scene view, for this component
*/
if (isGizmosDisabled == true)
return true;
//Try to disable
try
{
//Get all data of Unity Gizmos manager window
var Annotation = System.Type.GetType("UnityEditor.Annotation, UnityEditor");
var ClassId = Annotation.GetField("classID");
var ScriptClass = Annotation.GetField("scriptClass");
var Flags = Annotation.GetField("flags");
var IconEnabled = Annotation.GetField("iconEnabled");
System.Type AnnotationUtility = System.Type.GetType("UnityEditor.AnnotationUtility, UnityEditor");
var GetAnnotations = AnnotationUtility.GetMethod("GetAnnotations", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
var SetIconEnabled = AnnotationUtility.GetMethod("SetIconEnabled", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
//Scann all Gizmos of Unity, of this project
System.Array annotations = (System.Array)GetAnnotations.Invoke(null, null);
foreach (var a in annotations)
{
int classId = (int)ClassId.GetValue(a);
string scriptClass = (string)ScriptClass.GetValue(a);
int flags = (int)Flags.GetValue(a);
int iconEnabled = (int)IconEnabled.GetValue(a);
// this is done to ignore any built in types
if (string.IsNullOrEmpty(scriptClass))
{
continue;
}
const int HasIcon = 1;
bool hasIconFlag = (flags & HasIcon) == HasIcon;
//If the current gizmo is of the class desired, disable the gizmo in scene
if (scriptClass == scriptClassNameToDisable)
{
if (hasIconFlag && (iconEnabled != 0))
{
/*UnityEngine.Debug.LogWarning(string.Format("Script:'{0}' is not ment to show its icon in the scene view and will auto hide now. " +
"Icon auto hide is checked on script recompile, if you'd like to change this please remove it from the config", scriptClass));*/
SetIconEnabled.Invoke(null, new object[] { classId, scriptClass, 0 });
}
}
}
return true;
}
//Catch any error
catch (System.Exception exception)
{
string exceptionOcurred = "";
exceptionOcurred = exception.Message;
if (exceptionOcurred != null)
exceptionOcurred = "";
return false;
}
}
//This method returns the current width of inspector window
public static Rect GetInspectorWindowSize()
{
//Returns the current size of inspector window
return EditorGUILayout.GetControlRect(true, 0f);
}
#endif
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b341aafd810fa5c4ca132d2c0e886ab2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 46fa253953ac8cc47a4d6699a4670b78
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,54 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;
namespace MTAssets.EasyMeshCombiner
{
/*
* This is a script that is part of the essential library for "MT Assets" assets.
*/
[AddComponentMenu("")] //Hide this script in component menu.
public class MTAssetsMathematics : MonoBehaviour
{
//This method, randomize a specific list
public static List<T> RandomizeThisList<T>(List<T> list)
{
int count = list.Count;
int last = count - 1;
for (int i = 0; i < last; ++i)
{
int r = UnityEngine.Random.Range(i, count);
var tmp = list[i];
list[i] = list[r];
list[r] = tmp;
}
return list;
}
//This method return a half position between two Vector 3
public static Vector3 GetHalfPositionBetweenTwoPoints(Vector3 pointA, Vector3 pointB)
{
return Vector3.Lerp(pointA, pointB, 0.5f);
}
}
//Extensions classes
public static class ListMethodsExtensions
{
//Return the count of elements in list
public static void RemoveAllNullItems<T>(this List<T> list)
{
for (int i = list.Count - 1; i >= 0; i--)
if (list[i] == null)
list.RemoveAt(i);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e7382ac35b2fcb4ca1cfa4e81cd9b33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,327 @@
/////////////////////
MT ASSETS
CHANGELOG
/////////////////////
v3.2.0
- Added support for Emissive Maps and Emissive Map Colors. Support is in experimental status.
- Demo scenes have been updated.
- The documentation has been updated to reflect the new changes.
v3.1.0
- The default format generated by EMC texture processing has been changed from ARGB32 to RGBA32.
- Added options to copy the Primary UV of the merged mesh to other UV Channels in the Combined Mesh Manager.
- In the "Material To Use" variables in the Editor, a "+" button has been added that allows you to quickly create a new
Material, and save it locally in the project.
- Fixed a bug that caused some merged models to appear darker, when they had Normal Maps.
- Fixed a bug that very rarely caused merging to fail due to the 64k vertex limit error.
- It is now possible to control the compression quality of textures generated by EMC, through the "Just Material Colors"
and "All In One" merge methods. This control is done through the "Texture Compression" property.
- Pink Normal Maps fix has been extended for better compatibility.
- The Lightmaps Support framework has been revised, and more settings are available.
- Now, the meshes resulting from merging done in the Editor have a Suffix, to make it easier to find them later.
- Some new reliability mechanisms for Lightmap Support, have been added.
- Support for Material Colors has been added. You can now enable Material Colors support in blends that use the "All
In One" method. When activating this feature, the texture that will go to the Atlas will be colored with its
respective Material color, in the same way that Shaders do.
- Now, textures not found in their original materials before merging in "All In One", will no longer be highlighted
in the Atlas as the Red color, but the White color so that they are still compatible with the Material Colors.
- The EMC demo scenes have been updated to demonstrate new functionality and for greater clarity.
- The documentation has been updated to address the new changes.
v3.0.7
- ****
WARNING:
- In this version, the Easy Mesh Combiner path has been changed from "/Assets/MT Assets" to
"/Assets/Plugins/MT Assets", for better organization of your project. Because of this, before installing this new
version in your project, delete the "Easy Mesh Combiner" directory present inside your project
in "/Assets/MT Assets".
The folder "/Assets/MT Assets/_AssetsData" must be kept if you intend to undo any merges already made at some
point. But if you want to move this folder, undo all existing merges in your project, then delete this folder. After
that, just redo the merges and then the files will be generated in the new default path automatically by the tool.
If you have any questions, feel free to contact support at "mtassets@windsoft.xyz"!
****
- Some small adjustments have been made to the tool's UI to improve it.
- The tool has been updated to fully support Unity 6+!
- There is MUCH, MUCH more to come soon! :)
v3.0.6
- In HDRP and URP the default selected properties names for main textures have been changed to match the new
default names for Shader properties.
v3.0.5
- In this small update, the tool has been updated to include links to the new MT Assets Community on Discord. You
can join the community for support, ask your questions, submit suggestions, and interact with the dev
community! Come be part of the community and make it even better!
MT Assets Community on Discord: https://discord.gg/44aGAt4Sv4
v3.0.4
- An attempt was made to fix a bug that messed up the position of the mesh resulting from the merge when merging
meshes thar are in movement using the Runtime Mesh Combiner. There are new best practices and recommendations
for you to combine meshes that are in movement during your game's runtime, please read the Documentation for
more details!
IMPORTANT: IF YOU ARE STILL HAVING AN ISSUE WITH THIS MOVING MESHES MERGE BUG DURING RUNTIME, PLEASE REPORT THE
ISSUE TO SUPPORT VIA EMAIL "mtassets@windsoft.xyz", I WILL BE HAPPY TO HELP! :)
- The Runtime Merge Demo scene has been updated to show merging effects in a static environment (meshes that are
not moving) and in an environment with moving meshes (meshes that are moving across the scene).
- Now the Runtime Mesh Combiner component will no longer merge meshes if you place it in a GameObject that already
contains a Mesh Filter and Mesh Renderer component, as the Runtime Mesh Combiner needs a GameObject that does
not contain these two components in order to merge without problems.
- The documentation has been updated to contain new tips and more details on how the Runtime Mesh Combiner
component works, especially regarding moving mesh merges during Runtime.
v3.0.3
- Now the officially supported minimum version is Unity 2019.4 or higher. Support for this version of Unity or
higher will make it possible to add different new features and improvements in the future. This change also aims
to ensure that the tool can always have mature, stable and continuous update support!
- Minor layout adjustments have been made to the Mesh Combiner Tool's UI to ensure greater perfection in the
latest Unity versions.
v3.0.2
- Added one more helpful hint to Easy Mesh Combiner documentation.
v3.0.1
- ** WARNING: This is a major update for the Easy Mesh Combiner! Several improvements have been made and
incredible new additions too! **
-
- The documentation has been completely redone and updated as well. Now the new documentation is more modern
and more beautiful, it can be found in the folder "_Documentation/Documentation.html" and you can open it
directly from within your Unity Editor. If your project still has the old "Documentation.zip" file, you can
delete it without any problems.
- Some fields that were used only for internal codes, but which were not used for external scripts, were hidden
to avoid confusion.
- Some minor changes, optimizations and improvements have been made to the Editor UI.
- Some extra warnings have been added to make sure you stay on top of everything before merging!
- Now, after the merge is finished, Easy Mesh Combiner will display the merge processing time.
- The Combined Meshes Manager has been rewritten to adapt to the new functions of the Easy Mesh Combiner. He
also underwent some minor optimization and UI changes.
- The Combined Meshes Manager UI will now adapt according to the chosen blending method and other parameters.
- Combined Meshes Manager now has a bulletin board to communicate with you if you encounter any problems with
the merge.
- It will now be possible to export the Atlas generated during the merge. Through the Combined Meshes Manager.
- Easy Mesh Combiner now has a selection of "Combine Method". Through this selection, you can choose which
Combine Method Easy Mesh Combiner will use to combine your meshes!
(If you are a user of the Skinned Mesh Combiner MT tool, you already know how it works!)
- New Combine Method added: One Mesh Per Material. This method of blending works identically to the way in which
Easy Mesh Combiner has always worked! This is the standard Combine Method.
- New Combine Method added: All In One. This method of merging supports and generates Atlas from the meshes that
have been selected for merging. In this merge method the Easy Mesh Combiner will combine the meshes that
have Tilings (in order to preserve the quality of these meshes as much as possible) and combine the meshes that
do not have Tilings, all together, generating an Atlas with various textures. You can decide how many textures
an Atlas can have, if you want to have a better control of the quality that each texture will have in the Atlas.
After all, only the mesh resulting from the merge will remain.
- New Combine Method added: Just Material Colors. This method of blending only works with meshes that use only
colors in their materials, instead of textures. This blending method combines all meshes in just one mesh, then
extracts the color from all materials and creates a single Atals texture that works as a color palette,
containing all colors for all meshes combined. This will always optimize your meshes to generate only 1 Draw
Call at all times, while still retaining their original colors of the materials.
- Now, when activating "Lightmaps Support", you will see a button called "Deselect Excessive". By clicking on
this button, Easy Mesh Combiner will deselect any excess GameObjects.
- Fixed a bug that caused the vertex count to be increased after merge, in some rare cases.
- Fixed a bug that caused the vertex count to be increased after merge, in some rare cases (For Runtime Mesh
Combiner too).
- New function added to be performed after performing a merge: Now, when completing a merge with Easy Mesh Combiner
you can choose the option "Do Nothing" and so Easy Mesh Combiner will do absolutely nothing after performing
your merge! (For Editor)
- New function added to be performed after performing a merge: Now, when completing a merge with Easy Mesh Combiner
you can choose the option "Do Nothing" and so Easy Mesh Combiner will do absolutely nothing after performing
your merge! (For Runtime Mesh Combiner too)
v2.6.4
- Fixed some minor bugs and minor code changes.
- The option to Optimize the mesh resulting from the merge has been added to the combined mesh manager.
- An option to optimize the mesh was added to the Runtime Mesh Combiner component.
- Now the management buttons of the combined mesh through the Editor, send messages for each action performed.
- A button for quickly adding the Mesh Collider component, has been added to the combined mesh manager.
- The documentation has been updated to contain minor changes and additions made in this version.
v2.6.3
- A bug has been fixed that caused the selection gizmos not to be hidden, after closing the merge window in
the Editor, without combining any mesh.
- The UI of the merge window in the Editor, has undergone some improvements.
- The options for recalculating normals and tangens have been moved from the merge window to the management
component of the combined mesh, which is on the mesh resulting from the merge.
- Fixed a bug that caused disabled daughter meshes to still be combined, even if the "Combine Inactives"
option was unchecked.
- The "Combined Meshes Manager" component now has an option so that it is possible to export the mesh resulting
from the merge, as OBJ, so the editing of this mesh in external modeling software is made easier.
- Now the "Combine On Start" option of the "Runtime Mesh Combiner" has the options of "On Start" and "On Awake",
for greater control of when the merging should occur.
- Now the GameObject that contains the mesh resulting from the merge will always be placed very close to the
first selected GameObject and in addition, it will also be the child of the first selected GameObject.
- The component icons have been slightly updated.
- Now the official version of the Easy Mesh Combiner, is 2019.3.x.
- The documentation has been updated.
v2.5.2
- Correction of small bugs.
- There's more to come, soon!
v2.5.1
- It is now possible to disable the calculation of normals and tangents of the meshes resulting from the merging.
- Correction of small bugs.
- Documentation updated.
v2.4.3
- Correction of small bugs.
v2.4.2
- A bug has been fixed that caused the automatic deactivation of some scripts' Gizmos to stop working.
- Fixed a bug where changing Easy Mesh Combiner UI parameters did not work on some versions
of Unity 2019.3.x.
v2.4.1
- Combined Meshes Manager is now not displayed in the component list.
- Now the Gizmos of the RuntimeMeshCombiner and other components are no longer displayed.
- Now, by default, the option to launch debug logs on the console, is enabled so that in case of any
runtime merging error, you know. You can always disable it if you prefer!
- The documentation has been updated to ensure greater clarity, volume of information, tips and minor corrections!
- Fixed a bug in the creation of prefabs, which affected versions newer to Unity 2018.3.
- Now the meshes that are disabled, will not be included in the run-time merges, even if they are in the list
to merge.
- Easy Mesh Combiner will no longer issue merge warnings about possible problems with Lightmaps, if you
have not checked the support option for Lightmaps.
v2.4.0
- Following the rhythm of Unity Engine versions and to guarantee the good permanent support of this asset,
now the minimum recommended version is 2018.1, however, you can still use this asset in the 2017.4 LTS
version if you prefer. This will allow this asset to always have the latest features and better and
more effective support!
- Fixed a bug that caused the merging of very large meshes to suffer from distortions in the 2018.1
version of Unity.
- Fixed a bug that caused GameObjects to be active, but with MeshFilters disabled, also be combined
while selecting all meshes or a GameObject that contains all meshes in the scenario.
- Easy Mesh Combiner is now able to give an automatic name to the prefab you want to save.
- To avoid problems, Easy Mesh Combiner will now only display the combined mesh management buttons,
in the original meshes and no longer in their respective prefabs.
- The combined mesh manager interface has undergone some changes for clarity. Now the selection of
meshes combined by materials has a scrollview to make things more organized.
v2.3.0
- In this version, some unused files have been removed from the package. For example, the demo scene
materials now use standard Unity shaders. Nothing that will affect the way the EMC works.
- All resources, persistent asset data and other files are now saved in "MT Assets/_AssetsData".
This makes it easy to manage all files generated by MT assets and if you need to remove any asset,
just delete the asset folder. So, even if you want to remove some MT assets from your project, or
update it, you will not lose any files or information that you would like to keep!
v2.2.1
- Fixed a bug that caused the compilation or loading time of the scene execution to increase considerably
in the editor.
v2.2.0
- Now you no longer need to check the option of more than 64,000 vertices to combine giant meshes.
Easy Mesh Combiner can automatically identify the size of the meshes and will select whether the
resulting mesh will be 16 bits or 32 bits.
v2.1.1
- Fixed a compatibility issue with Unity version 2018.1.
v2.1.0
- This major update has brought several enhancements, feature additions, and enhancements to EMC's workflow!
- This update may cause your combined mesh managers of version 1.7.1 or lower to stop working as they
should. Back up your project to revert changes if you prefer. The new combined mesh manager is
better and smarter, read on.
- Minor additions to the asset menu.
- Improvement of some asset codes.
- Improvements to undo actions.
- Updated UI! Easy Mesh Combiner is now more intuitive and optimized for use in the Editor!
- Improvements in displaying merge statistics.
- Added merge log. Through it, you can identify problems in meshes before you merge, and also get
the root of what is causing the problem.
- All EMC source code has been rewritten, optimized and revamped!
- Easy Mesh Combiner will now keep your merge preferences even if you close the editor window.
- Now the merge window continues to update even while it is not in focus. So you can select meshes
while everything is updated automatically!
- Now the Easy Mesh Combiner window will remember which position you left it when you closed it.
- Valid GameObjects selected for merge will now be highlighted in blue. Invalid GameObjects will
be highlighted in red in your scene. (Highlights only appear with the merge window open).
- The option to add a comment to the GameObject resulting from the merge has been removed,
however, you can now choose the name of this GameObject before merging.
- Easy Mesh Combiner should now work smoothly on versions older than 2017.4, but mesh support
with more than 65,000 vertices will not work on versions older than 2017.4.
- Now, when you finish a merge, only 1 new GameObject will be generated that will contain a
single mesh resulting from the merge!
- The resulting GameObject merge will now be positioned as close as possible to the selected
GameObjects to be merged into the hierarchy. The resulting GameObject from the merge will no
longer appear at the end of your scene hierarchy.
- Several improvements made to the combined mesh manager. You now have better mesh management after the merge.
- Fixed a bug where previously disabled meshes are enabled when undoing a merge!
- Fixed a bug when importing this asset for the first time, where a file error message was displayed.
It was more common with Windows 10 users.
- Several interface improvements.
- Fixing a bug that caused Unity to crash (in some versions) upon completion of a merge.
- Documentation updated.
- Added a feature so you can merge and unmerge at runtime, so you can optimize your game even
as it runs, quickly and optimally!
- Added new sample scene to show merge at runtime.
- You can have a complete debug of the merge process at run time.
- Fixed a compatibility issue with prefab creation in the latest versions of Unity.
- The management of combined mesh prefabs has also been improved.
- Better organization of source code.
- There was a slight change in the asset API. Now, to access the API methods of this
asset, use "using MTAssets.EasyMeshCombiner".
- Added function to select all original GameObjects containing X material in combined mesh
manager (after merging using Editor).
v1.7.1
- More interface improvements.
- Small corrections.
- Fix a bug with the welcome message.
- Small housekeeping in scripts
- Added an option to select all the original meshes of a merge.
- You can now include a comment in the GameObject resulting from the merge.
v1.6.2
- Workflow Improvement
- Fixes and enhancements in the user interface
- Improvements in integrated materials
- The compatibility of the tool has been extended among more Unity versions!
v1.6.1
- Small improvements in code.
v1.6
- Improvements in tool interface.
v1.5
- Your merge preferences will now persist even if the merge window is closed.
- Fix of small bugs.
- Small improvements in tool interface.
- Now you can save prefabs from the merge, quickly, just by activating an option before the merge!
v1.4
- The minimum support version is now Unity 2018.1.0f2. This change was made to ensure future improvements to the tool! Stay tuned!
- The 65,000 vertices limit has been removed! Now you can combine your knits without worrying about this limitation!
- Now the tool interface shows the information you are merging.
v1.3
- Small improvements in documentation.
- Improved support for lightmaps in merged meshes!
- Addition of explanations on the merge of meshes and generation of lightmaps in the documentation.
v1.2
- A lot of minor improvements.
- Fix small bugs.
v1.1
- Do not worry about duplicates when saving the meshes combined in your project file!
- If you have saved the merge files in your project files, and you want to undo the merge,
all unnecessary files are also deleted from your project. So you do not worry about memory problems!
- The combined mesh manager now shows you a warning if it detects that one of the meshes combined
does not have any important files.
- The documentation has been contemplated with the new details!
v1.0
- The Easy Mesh Combiner has just been released! I will always be working to support and add new features!
Do you have any suggestions, Bug reports or any problems with using this asset? Contact by email!
(mtassets@windsoft.xyz)
/////////////////////
Email for support
mtassets@windsoft.xyz
/////////////////////

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 96d1a3e90cecf644da53be88a271d326
timeCreated: 1545776247
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
/////////////////////
MT ASSETS
/////////////////////
In this tool, the files or folders listed below can be deleted from your project, without
negatively affects the installation of this tool. You can delete them if you want to reduce disc use,
if you prefer, and this action will not cause problems for the overall operation of the tool.
- "/_Documentation"
- "/_ScenesDemo"
- "DemoScene (Example Of Editor Merge).unity"
- "DemoScene (Example Of Runtime Merge).unity"
Each of these files can be re-installed on your project by re-importing this tool. Feel free to contact
MT Assets Support if you have any questions.
/////////////////////
Email for support
mtassets@windsoft.xyz
/////////////////////

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8fb0949b21591a946af005527de78174
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a7754f83ec2ba914aa2b5cbc596f5fcc
folderAsset: yes
timeCreated: 1548972319
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,713 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine.SceneManagement;
using System.IO;
#endif
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
namespace MTAssets.EasyMeshCombiner
{
/*
This class is responsible for the functioning of the "Combined Meshes Manager" component, and all its functions.
*/
/*
* The Easy Mesh Combiner was developed by Marcos Tomaz in 2019.
* Need help? Contact me (mtassets@windsoft.xyz)
*/
[AddComponentMenu("")] //Hide this script in component menu.
public class CombinedMeshesManager : MonoBehaviour
{
#if UNITY_EDITOR
//------------------------------------------- START OF PARAMETERS OF INFORMATION OF MERGE -----------------------------------------
//Enums of script
public enum MergeMethod
{
OneMeshPerMaterial,
AllInOne,
JustMaterialColors
}
public enum UndoMethod
{
EnableOriginalMeshes,
ReactiveOriginalGameObjects,
DoNothing
}
public enum AssetType
{
Unknown,
Mesh,
Texture,
Material
}
//Classes of script
[System.Serializable]
public class OriginalGameObjectWithMesh
{
//Class that stores a original GameObject With Mesh data, to restore on undo merge.
public GameObject gameObject;
public bool originalGoState;
public MeshRenderer meshRenderer;
public bool originalMrState;
public OriginalGameObjectWithMesh(GameObject gameObject, bool originalGoState, MeshRenderer meshRenderer, bool originalMrState)
{
this.gameObject = gameObject;
this.originalGoState = originalGoState;
this.meshRenderer = meshRenderer;
this.originalMrState = originalMrState;
}
}
[System.Serializable]
public class PathAndTypeOfAAsset
{
//Class that stores path and type of a asset
public AssetType type = AssetType.Unknown;
public string path;
public PathAndTypeOfAAsset(AssetType type, string path)
{
this.type = type;
this.path = path;
}
}
//Variables of script, informations about this merge
///<summary>[WARNING] This variable is only available in the Editor and will not be included in the compilation of your project, in the final Build.</summary>
[HideInInspector]
public MergeMethod mergeMethodUsed;
///<summary>[WARNING] This variable is only available in the Editor and will not be included in the compilation of your project, in the final Build.</summary>
[HideInInspector]
public UndoMethod undoMethod;
///<summary>[WARNING] This variable is only available in the Editor and will not be included in the compilation of your project, in the final Build.</summary>
[HideInInspector]
public List<OriginalGameObjectWithMesh> originalsGameObjectsWithMesh = new List<OriginalGameObjectWithMesh>();
///<summary>[WARNING] This variable is only available in the Editor and will not be included in the compilation of your project, in the final Build.</summary>
[HideInInspector]
public List<PathAndTypeOfAAsset> pathsAndTypesOfAssetsOfThisMerge = new List<PathAndTypeOfAAsset>();
///<summary>[WARNING] This variable is only available in the Editor and will not be included in the compilation of your project, in the final Build.</summary>
[HideInInspector]
public bool thisIsPrefab = false;
//------------------------------------------ END OF PARAMETERS OF INFORMATION OF MERGE ------------------------------------------
//Private variables of Editor Methods
[HideInInspector]
[SerializeField]
private int exportToObjStartIndexOffSet = 0;
[HideInInspector]
[SerializeField]
private bool hideWarningsForThisMerge = false;
//Private variables of Editor Interface
private bool gizmosOfThisComponentIsDisabled = false;
//The UI of this component
#region INTERFACE_CODE
[UnityEditor.CustomEditor(typeof(CombinedMeshesManager))]
public class CustomInspector : UnityEditor.Editor
{
//Private temp variables
Vector2 scrollviewMaterials = Vector2.zero;
List<string> warningsOfChecks = new List<string>();
public override void OnInspectorGUI()
{
//Start the undo event support, draw default inspector and monitor of changes
CombinedMeshesManager script = (CombinedMeshesManager)target;
EditorGUI.BeginChangeCheck();
Undo.RecordObject(target, "Undo Event");
script.gizmosOfThisComponentIsDisabled = MTAssetsEditorUi.DisableGizmosInSceneView("CombinedMeshesManager", script.gizmosOfThisComponentIsDisabled);
//Start of UI
EditorGUILayout.HelpBox("This GameObject contains the meshes you previously combined. Through this component you can manage the mesh resulting from the merge.", MessageType.Info);
GUILayout.Space(10);
//Show the merge method used in this merge
GUIStyle titulo = new GUIStyle();
titulo.fontSize = 16;
titulo.normal.textColor = new Color(0, 79.0f / 250.0f, 3.0f / 250.0f);
titulo.alignment = TextAnchor.MiddleCenter;
if (script.mergeMethodUsed == MergeMethod.OneMeshPerMaterial)
EditorGUILayout.LabelField("Merged Using One Mesh Per Material", titulo);
if (script.mergeMethodUsed == MergeMethod.AllInOne)
EditorGUILayout.LabelField("Merged Using All In One", titulo);
if (script.mergeMethodUsed == MergeMethod.JustMaterialColors)
EditorGUILayout.LabelField("Merged Using Just Material Colors", titulo);
//Show warning box, if necessary
RunFilesAndCheckersAndGenerateWarningBoxIfNecessary(script);
GUILayout.Space(10);
//Render the box of materials and assets
RenderTheBoxOfMaterialsAndAssetsManagement(script);
//Select all original gameObjects
if (GUILayout.Button("Select All Original GameObjects", GUILayout.Height(30)))
{
List<GameObject> gameObjects = new List<GameObject>();
foreach (OriginalGameObjectWithMesh ogo in script.originalsGameObjectsWithMesh)
gameObjects.Add(ogo.gameObject);
Selection.objects = gameObjects.ToArray();
}
GUILayout.Space(10);
//Render the management buttons of this mesh
RenderTheMainManagementButtonsForThisMesh(script);
GUILayout.Space(10);
EditorGUILayout.LabelField("More Informations About", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.BeginVertical("box");
StringBuilder informationsBuild = new StringBuilder();
informationsBuild.Append("What will be done after undoing the merge\n");
if (script.undoMethod == UndoMethod.EnableOriginalMeshes)
informationsBuild.Append("The original Mesh Renderers will return to their original state.");
if (script.undoMethod == UndoMethod.ReactiveOriginalGameObjects)
informationsBuild.Append("The original GameObjects will return to their original state.");
if (script.undoMethod == UndoMethod.DoNothing)
informationsBuild.Append("Nothing will be done.");
informationsBuild.Append("\n\nAbout this GameObject\n");
if (script.thisIsPrefab == true)
informationsBuild.Append("This merged GameObject is or was originally generated as a Prefab. If you decide to undo the merging, the generated files will not be deleted, in order to avoid breaking the copy of this prefab in other scenes.");
if (script.thisIsPrefab == false)
informationsBuild.Append("This merged GameObject is not and was not originally generated as a Prefab. If you decide to undo the merge, the generated files will be deleted automatically, too.");
EditorGUILayout.HelpBox(informationsBuild.ToString(), MessageType.Info);
EditorGUILayout.EndVertical();
//Final space
GUILayout.Space(10);
//Stop paint of GUI, if this gameobject no more exists
if (script == null)
return;
//Apply changes on script, case is not playing in editor
if (GUI.changed == true && Application.isPlaying == false)
{
EditorUtility.SetDirty(script);
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(script.gameObject.scene);
}
if (EditorGUI.EndChangeCheck() == true)
{
}
}
private void RunFilesAndCheckersAndGenerateWarningBoxIfNecessary(CombinedMeshesManager script)
{
//This method will run some checkers and verifications and, if needed will show a box with warnings about merge
warningsOfChecks.Clear();
//Verify if has missing files of merge, if data save in assets option is enabled
bool haveFilesMissing = false;
foreach (PathAndTypeOfAAsset item in script.pathsAndTypesOfAssetsOfThisMerge)
if (File.Exists(item.path) == false)
haveFilesMissing = true;
if (haveFilesMissing == true)
warningsOfChecks.Add("It appears that one or more files that were generated for this merge, are missing or have been moved from their original locations. If your merge is not as expected, try to redo it.");
//Verify it the mesh of mesh filter is missing
MeshFilter mergedMesh = script.GetComponent<MeshFilter>();
if (mergedMesh.sharedMesh == null)
warningsOfChecks.Add("It looks like there are missing mesh file in this merge. To solve this problem, you can undo this merge and re-do it again!");
//Verify if some original GameObject is not present more
bool haveOriginalGameObjectsMissing = false;
foreach (OriginalGameObjectWithMesh obj in script.originalsGameObjectsWithMesh)
if (obj.gameObject == null || obj.meshRenderer == null)
haveOriginalGameObjectsMissing = true;
if (haveOriginalGameObjectsMissing == true)
warningsOfChecks.Add("It seems that some of the original GameObjects or MeshRenderers that make up this merge are no longer present in this scene, or have been deleted. The original GameObjects that are not found cannot be restored to their original state if you decide to undo this merge.");
//Show the warnings
if (warningsOfChecks.Count > 0)
{
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal("box");
GUIStyle tituloBox = new GUIStyle();
tituloBox.fontStyle = FontStyle.Bold;
tituloBox.alignment = TextAnchor.MiddleLeft;
EditorGUILayout.LabelField("Warnings For This Merge (" + warningsOfChecks.Count + ")", tituloBox);
if (script.hideWarningsForThisMerge == true)
if (GUILayout.Button("Show", GUILayout.Height(18), GUILayout.Width(50)))
script.hideWarningsForThisMerge = false;
if (script.hideWarningsForThisMerge == false)
if (GUILayout.Button("Hide", GUILayout.Height(18), GUILayout.Width(50)))
script.hideWarningsForThisMerge = true;
EditorGUILayout.EndHorizontal();
if (script.hideWarningsForThisMerge == false)
{
EditorGUILayout.BeginVertical("box");
foreach (string str in warningsOfChecks)
EditorGUILayout.HelpBox(str, MessageType.Warning);
EditorGUILayout.EndVertical();
}
}
}
private void RenderTheBoxOfMaterialsAndAssetsManagement(CombinedMeshesManager script)
{
//If this is this mesh was generated by One Mesh Per Material
if (script.mergeMethodUsed == MergeMethod.OneMeshPerMaterial)
{
//Create a scroll view to select all gameobjects where material is equal to...
EditorGUILayout.LabelField("Selection By Materials", EditorStyles.boldLabel);
GUILayout.Space(10);
//Select all original gameObjects with X material
Dictionary<Material, List<GameObject>> objects = new Dictionary<Material, List<GameObject>>();
foreach (OriginalGameObjectWithMesh oGo in script.originalsGameObjectsWithMesh)
{
if (oGo == null || oGo.meshRenderer == null)
continue;
for (int i = 0; i < oGo.meshRenderer.sharedMaterials.Length; i++)
{
Material mat = oGo.meshRenderer.sharedMaterials[i];
if (mat == null)
continue;
if (objects.ContainsKey(mat) == false)
objects.Add(mat, new List<GameObject>() { oGo.gameObject });
if (objects.ContainsKey(mat) == true)
objects[mat].Add(oGo.gameObject);
}
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Select All Original Meshes That Uses...", GUILayout.Width(320));
GUILayout.Space(MTAssetsEditorUi.GetInspectorWindowSize().x - 320);
EditorGUILayout.LabelField("Size", GUILayout.Width(30));
EditorGUILayout.IntField(objects.Keys.Count, GUILayout.Width(50));
EditorGUILayout.EndHorizontal();
GUILayout.BeginVertical("box");
scrollviewMaterials = EditorGUILayout.BeginScrollView(scrollviewMaterials, GUIStyle.none, GUI.skin.verticalScrollbar, GUILayout.Width(MTAssetsEditorUi.GetInspectorWindowSize().x), GUILayout.Height(150));
if (objects.Keys.Count == 0)
EditorGUILayout.HelpBox("Oops! The original materials of this merge were not found!", MessageType.Info);
if (objects.Keys.Count > 0)
foreach (var key in objects.Keys)
if (GUILayout.Button("\"" + key.name + "\" Material", GUILayout.Height(24)))
Selection.objects = objects[key].ToArray();
EditorGUILayout.EndScrollView();
GUILayout.EndVertical();
}
//If this is this mesh was generated by other merge method
if (script.mergeMethodUsed != MergeMethod.OneMeshPerMaterial)
{
//Create a scroll view to view all generated files...
EditorGUILayout.LabelField("All Generated Assets", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("All Generated Assets In This Merge...", GUILayout.Width(320));
GUILayout.Space(MTAssetsEditorUi.GetInspectorWindowSize().x - 320);
EditorGUILayout.LabelField("Size", GUILayout.Width(30));
EditorGUILayout.IntField(script.pathsAndTypesOfAssetsOfThisMerge.Count, GUILayout.Width(50));
EditorGUILayout.EndHorizontal();
GUILayout.BeginVertical("box");
scrollviewMaterials = EditorGUILayout.BeginScrollView(scrollviewMaterials, GUIStyle.none, GUI.skin.verticalScrollbar, GUILayout.Width(MTAssetsEditorUi.GetInspectorWindowSize().x), GUILayout.Height(118));
foreach (PathAndTypeOfAAsset item in script.pathsAndTypesOfAssetsOfThisMerge)
DrawItemOfListOfResourcesInStats(item.path);
EditorGUILayout.EndScrollView();
GUILayout.EndVertical();
//Draw export options
DrawExportAllAtlasOrMaterialsOption(script);
}
}
private void RenderTheMainManagementButtonsForThisMesh(CombinedMeshesManager script)
{
//This method will render the buttons to manage this merge
EditorGUILayout.LabelField("Management Of This Merge", EditorStyles.boldLabel);
GUILayout.Space(10);
if (script.GetComponent<MeshCollider>() == null)
if (GUILayout.Button("Add Mesh Collider To This Mesh", GUILayout.Height(30)))
{
script.gameObject.AddComponent<MeshCollider>();
Debug.Log("A Mesh Collider was added to this mesh!.");
}
if (GUILayout.Button("Recalculate Normals Of This Mesh", GUILayout.Height(30)))
{
script.GetComponent<MeshFilter>().sharedMesh.RecalculateNormals();
Debug.Log("The normals of this mesh resulting from the merging were recalculated.");
}
if (GUILayout.Button("Recalculate Tangents Of This Mesh", GUILayout.Height(30)))
{
script.GetComponent<MeshFilter>().sharedMesh.RecalculateTangents();
Debug.Log("The tangents of this mesh resulting from the merging were recalculated.");
}
if (GUILayout.Button("Copy Primary UV to UV2", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv2 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV2 successfully!");
}
if (GUILayout.Button("Copy Primary UV to UV3", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv3 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV3 successfully!");
}
if (GUILayout.Button("Copy Primary UV to UV4", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv4 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV4 successfully!");
}
if (GUILayout.Button("Copy Primary UV to UV5", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv5 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV5 successfully!");
}
if (GUILayout.Button("Copy Primary UV to UV6", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv6 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV6 successfully!");
}
if (GUILayout.Button("Copy Primary UV to UV7", GUILayout.Height(25)))
{
script.GetComponent<MeshFilter>().sharedMesh.uv7 = script.GetComponent<MeshFilter>().sharedMesh.uv;
#if UNITY_EDITOR
EditorUtility.SetDirty(script.GetComponent<MeshFilter>().sharedMesh);
#endif
Debug.Log("The Primary UV of mesh \"" + script.GetComponent<MeshFilter>().sharedMesh.name + "\" was copied to UV7 successfully!");
}
if (GUILayout.Button("Export This Mesh As OBJ", GUILayout.Height(30)))
script.ExportMeshAsObj(script);
if (GUILayout.Button("Optimize This Mesh", GUILayout.Height(30)))
{
script.GetComponent<MeshFilter>().sharedMesh.Optimize();
Debug.Log("The mesh resulting from the merge has been optimized!");
}
if (GUILayout.Button("Undo And Delete This Merge", GUILayout.Height(30)))
{
bool confirmation = EditorUtility.DisplayDialog("Undo",
"This combined mesh and your GameObject will be deleted and removed from your scene. The original GameObjects/Meshes will be restored to their original state before the merge.\n\nAre you sure you want to undo this merge?",
"Yes",
"No");
if (confirmation == true)
script.UndoAndDeleteThisMerge();
}
}
private void DrawItemOfListOfResourcesInStats(string filePath)
{
//Get the type of asset
Type assetType = AssetDatabase.GetMainAssetTypeAtPath(filePath);
//Load the asset
var asset = AssetDatabase.LoadAssetAtPath(filePath, assetType);
//Draw the item and represent the desired file
GUILayout.Space(2);
EditorGUILayout.BeginHorizontal();
if (assetType == null)
{
assetType = typeof(object);
}
if (assetType != null)
{
if (assetType != typeof(Texture) && assetType != typeof(Texture2D))
{
GUILayout.Box("R", GUILayout.Width(28), GUILayout.Height(28));
}
if (assetType == typeof(Texture) || assetType == typeof(Texture2D))
{
GUIStyle estiloIcone = new GUIStyle();
estiloIcone.border = new RectOffset(0, 0, 0, 0);
estiloIcone.margin = new RectOffset(4, 0, 4, 0);
GUILayout.Box((Texture)asset, estiloIcone, GUILayout.Width(28), GUILayout.Height(28));
}
}
EditorGUILayout.BeginVertical();
if (asset == null)
EditorGUILayout.LabelField("Resource Not Found", EditorStyles.boldLabel);
if (asset != null)
EditorGUILayout.LabelField(asset.name, EditorStyles.boldLabel);
GUILayout.Space(-3);
if (assetType == typeof(Mesh))
EditorGUILayout.LabelField("Mesh/" + Path.GetExtension(filePath));
if (assetType == typeof(Texture) || assetType == typeof(Texture2D))
EditorGUILayout.LabelField("Texture/" + Path.GetExtension(filePath));
if (assetType == typeof(Material))
EditorGUILayout.LabelField("Material/" + Path.GetExtension(filePath));
if (assetType == typeof(object))
EditorGUILayout.LabelField("Unknow/???");
EditorGUILayout.EndVertical();
GUILayout.Space(20);
EditorGUILayout.BeginVertical();
GUILayout.Space(8);
if (GUILayout.Button("Resource", GUILayout.Height(20)))
{
EditorGUIUtility.PingObject(asset);
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
GUILayout.Space(2);
}
private void DrawExportAllAtlasOrMaterialsOption(CombinedMeshesManager script)
{
//Draw buttons to export resources
EditorGUILayout.BeginHorizontal();
//Create button to export all textures
if (GUILayout.Button("Export All Atlas", GUILayout.Height(30)))
{
//Open selection of folder
string folder = EditorUtility.OpenFolderPanel("Select Folder To Save", "", "");
if (String.IsNullOrEmpty(folder) == true)
return;
//Show progress bar
EditorUtility.DisplayProgressBar("A moment", "Exporting Atlas as PNG", 1.0f);
//For file of list of assets saved
foreach (PathAndTypeOfAAsset item in script.pathsAndTypesOfAssetsOfThisMerge)
{
//Load type of asset and the asset
var asset = AssetDatabase.LoadAssetAtPath(item.path, typeof(object));
var type = typeof(object);
if (asset != null)
type = asset.GetType();
if (asset == null)
{
EditorUtility.DisplayDialog("Atlas Not Found", "It was not possible to export the texture, as it was not found in the directory below\n\n" + item.path, "Continue");
continue;
}
if (asset != null && type != typeof(Texture2D))
continue;
if (asset != null && type == typeof(Texture2D))
{
Texture2D texture = asset as Texture2D;
byte[] mainTextureBytes = texture.EncodeToPNG();
File.WriteAllBytes(folder + "/" + asset.name + ".png", mainTextureBytes);
}
}
//Clear progress bar
EditorUtility.ClearProgressBar();
//Show warning
EditorUtility.DisplayDialog("Done", "Exporting process is finished. All atlas generated by this merge, was exported to path below\n\n" + folder, "Ok");
}
//Create button to export all materials
if (GUILayout.Button("Export Material", GUILayout.Height(30)))
{
//Open selection of folder
string folder = EditorUtility.OpenFolderPanel("Select Folder To Save", "", "");
if (String.IsNullOrEmpty(folder) == true)
return;
//Show progress bar
EditorUtility.DisplayProgressBar("A moment", "Exporting Materials", 1.0f);
//For file of list of assets saved
foreach (PathAndTypeOfAAsset item in script.pathsAndTypesOfAssetsOfThisMerge)
{
//Load type of asset and the asset
var asset = AssetDatabase.LoadAssetAtPath(item.path, typeof(object));
var type = typeof(object);
if (asset != null)
type = asset.GetType();
if (asset == null)
{
EditorUtility.DisplayDialog("Materials Not Found", "It was not possible to export the material, as it was not found in the directory below\n\n" + item.path, "Continue");
continue;
}
if (asset != null && type != typeof(Material))
continue;
if (asset != null && type == typeof(Material))
{
File.Copy(item.path, folder + "/" + asset.name + ".mat");
}
}
//Clear progress bar
EditorUtility.ClearProgressBar();
//Show warning
EditorUtility.DisplayDialog("Done", "Exporting process is finished. All materials generated by this merge, was exported to path below\n\n" + folder, "Ok");
}
EditorGUILayout.EndHorizontal();
}
}
#endregion
//Core Methods
private void UndoAndDeleteThisMerge()
{
//Show progress bar
EditorUtility.DisplayProgressBar("A moment", "Undoing...", 1.0f);
//Undo the merge according the type of merge
if (undoMethod == UndoMethod.EnableOriginalMeshes)
foreach (OriginalGameObjectWithMesh original in originalsGameObjectsWithMesh)
{
//Skip, if is null
if (original.meshRenderer == null)
continue;
original.meshRenderer.enabled = original.originalMrState;
}
if (undoMethod == UndoMethod.ReactiveOriginalGameObjects)
foreach (OriginalGameObjectWithMesh original in originalsGameObjectsWithMesh)
{
//Skip, if is null
if (original.gameObject == null)
continue;
original.gameObject.SetActive(original.originalGoState);
}
//Delete unused assets, if this is not a prefab
if (thisIsPrefab == false)
foreach (PathAndTypeOfAAsset item in pathsAndTypesOfAssetsOfThisMerge)
{
if (AssetDatabase.LoadAssetAtPath(item.path, typeof(object)) != null)
AssetDatabase.DeleteAsset(item.path);
if (AssetDatabase.LoadAssetAtPath(item.path.Replace(".asset", " RAW.asset"), typeof(object)) != null)
AssetDatabase.DeleteAsset(item.path.Replace(".asset", " RAW.asset"));
}
//Set scene as dirty
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene());
//Show dialog
Debug.Log("The merge was successfully undone. All of the original GameObject/Meshes that this Manager could still access have been restored!\n\nIf you had chosen to save the merged meshes to your project files, all useless mesh files were deleted automatically!");
//Destroy this merge
DestroyImmediate(this.gameObject, true);
//Clear progress bar
EditorUtility.ClearProgressBar();
}
private void ExportMeshAsObj(CombinedMeshesManager script)
{
//Open the export window
string folder = EditorUtility.OpenFolderPanel("Select Folder To Export", "", "");
if (String.IsNullOrEmpty(folder) == true)
return;
//Show progress bar
EditorUtility.DisplayProgressBar("A moment", "Exporting Mesh as OBJ", 1.0f);
//Get this mesh
MeshRenderer meshRenderer = this.gameObject.GetComponent<MeshRenderer>();
MeshFilter meshFilter = this.gameObject.GetComponent<MeshFilter>();
//Start export of mesh
exportToObjStartIndexOffSet = 0;
StringBuilder meshString = new StringBuilder();
meshString.Append("#" + meshFilter.sharedMesh.name + ".obj"
+ "\n#" + System.DateTime.Now.ToLongDateString()
+ "\n#" + System.DateTime.Now.ToLongTimeString()
+ "\n#-------"
+ "\n\n");
Transform transform = this.gameObject.transform;
Vector3 originalPosition = transform.position;
transform.position = Vector3.zero;
meshString.Append(ExportToObjProcessTransform(transform, script));
string meshStringResult = meshString.ToString();
using (StreamWriter stringWriter = new StreamWriter(folder + "/" + meshFilter.sharedMesh.name + ".obj"))
{
stringWriter.Write(meshStringResult);
}
transform.position = originalPosition;
exportToObjStartIndexOffSet = 0;
//Clear progress bar
EditorUtility.ClearProgressBar();
//Show warning
Debug.Log("The mesh was successfully exported to the directory \"" + folder + "\".");
}
//Tools Methods For Core Methods
private static string ExportToObjProcessTransform(Transform transform, CombinedMeshesManager script)
{
StringBuilder meshString = new StringBuilder();
meshString.Append("#" + transform.name
+ "\n#-------"
+ "\n");
meshString.Append("g ").Append(transform.name).Append("\n");
MeshFilter mf = transform.GetComponent<MeshFilter>();
if (mf)
meshString.Append(ExportToObjMeshToString(mf, transform, script));
for (int i = 0; i < transform.childCount; i++)
meshString.Append(ExportToObjProcessTransform(transform.GetChild(i), script));
return meshString.ToString();
}
private static string ExportToObjMeshToString(MeshFilter mf, Transform t, CombinedMeshesManager script)
{
Vector3 s = t.localScale;
Vector3 p = t.localPosition;
Quaternion r = t.localRotation;
int numVertices = 0;
Mesh m = mf.sharedMesh;
if (!m)
return "####Error####";
Material[] mats = mf.GetComponent<MeshRenderer>().sharedMaterials;
StringBuilder sb = new StringBuilder();
foreach (Vector3 vv in m.vertices)
{
Vector3 v = t.TransformPoint(vv);
numVertices++;
sb.Append(string.Format("v {0} {1} {2}\n", v.x, v.y, -v.z));
}
sb.Append("\n");
foreach (Vector3 nn in m.normals)
{
Vector3 v = r * nn;
sb.Append(string.Format("vn {0} {1} {2}\n", -v.x, -v.y, v.z));
}
sb.Append("\n");
foreach (Vector3 v in m.uv)
{
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
}
for (int material = 0; material < m.subMeshCount; material++)
{
sb.Append("\n");
sb.Append("usemtl ").Append(mats[material].name).Append("\n");
sb.Append("usemap ").Append(mats[material].name).Append("\n");
int[] triangles = m.GetTriangles(material);
for (int i = 0; i < triangles.Length; i += 3)
{
sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
triangles[i] + 1 + script.exportToObjStartIndexOffSet, triangles[i + 1] + 1 + script.exportToObjStartIndexOffSet, triangles[i + 2] + 1 + script.exportToObjStartIndexOffSet));
}
}
script.exportToObjStartIndexOffSet += numVertices;
return sb.ToString();
}
#endif
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 41659897ac0c84f49977383a29dd0100
timeCreated: 1548972541
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: e5168e147f30ae54c9f1548c5e1c0492, type: 3}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: e5168e147f30ae54c9f1548c5e1c0492
timeCreated: 1548972520
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,722 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace MTAssets.EasyMeshCombiner
{
/*
This class is responsible for the functioning of the "Runtime Mesh Combiner" component, and all its functions.
*/
/*
* The Easy Mesh Combiner was developed by Marcos Tomaz in 2019.
* Need help? Contact me (mtassets@windsoft.xyz)
*/
[AddComponentMenu("MT Assets/Easy Mesh Combiner/Runtime Mesh Combiner")] //Add this component in a category of addComponent menu
public class RuntimeMeshCombiner : MonoBehaviour
{
//Private constants
private int MAX_VERTICES_FOR_16BITS_MESH = 50000; //Not change this
//Classes of script
private class GameObjectWithMesh
{
//Class that stores a valid gameobject that contains a mesh
public GameObject gameObject;
public MeshFilter meshFilter;
public MeshRenderer meshRenderer;
public GameObjectWithMesh(GameObject gameObject, MeshFilter meshFilter, MeshRenderer meshRenderer)
{
this.gameObject = gameObject;
this.meshFilter = meshFilter;
this.meshRenderer = meshRenderer;
}
}
private class OriginalGameObjectWithMesh
{
//Class that stores a original GameObject With Mesh data, to restore on undo merge.
public GameObject gameObject;
public bool originalGoState;
public MeshRenderer meshRenderer;
public bool originalMrState;
public OriginalGameObjectWithMesh(GameObject gameObject, bool originalGoState, MeshRenderer meshRenderer, bool originalMrState)
{
this.gameObject = gameObject;
this.originalGoState = originalGoState;
this.meshRenderer = meshRenderer;
this.originalMrState = originalMrState;
}
}
private class SubMeshToCombine
{
//Class that stores a mesh filter/renderer and respective submesh index, to combine
public Transform transform;
public MeshFilter meshFilter;
public MeshRenderer meshRenderer;
public int subMeshIndex;
public SubMeshToCombine(Transform transform, MeshFilter meshFilter, MeshRenderer meshRenderer, int subMeshIndex)
{
this.transform = transform;
this.meshFilter = meshFilter;
this.meshRenderer = meshRenderer;
this.subMeshIndex = subMeshIndex;
}
}
//Enums of script
public enum CombineOnStart
{
Disabled,
OnStart,
OnAwake
}
public enum AfterMerge
{
DisableOriginalMeshes,
DeactiveOriginalGameObjects,
DoNothing
}
//Variables of script
private Vector3 originalPosition = Vector3.zero;
private Vector3 originalEulerAngles = Vector3.zero;
private Vector3 originalScale = Vector3.zero;
private List<OriginalGameObjectWithMesh> originalGameObjectsWithMeshToRestore = new List<OriginalGameObjectWithMesh>();
private bool targetMeshesMerged = false;
//Variables of merge
[HideInInspector]
public AfterMerge afterMerge;
[HideInInspector]
public bool addMeshColliderAfter = true;
[HideInInspector]
public CombineOnStart combineMeshesAtStartUp = CombineOnStart.Disabled;
[HideInInspector]
public bool combineInChildren = false;
[HideInInspector]
public bool combineInactives = false;
[HideInInspector]
public bool recalculateNormals = true;
[HideInInspector]
public bool recalculateTangents = true;
[HideInInspector]
public bool optimizeResultingMesh = false;
[HideInInspector]
public List<GameObject> targetMeshes = new List<GameObject>();
[HideInInspector]
public bool showDebugLogs = true;
[HideInInspector]
public bool garbageCollectorAfterUndo = true;
public UnityEvent onDoneMerge;
public UnityEvent onDoneUnmerge;
//The UI of this component
#if UNITY_EDITOR
//Private variables of Interface
private bool gizmosOfThisComponentIsDisabled = false;
#region INTERFACE_CODE
[UnityEditor.CustomEditor(typeof(RuntimeMeshCombiner))]
public class CustomInspector : UnityEditor.Editor
{
//Private temp variables
public Vector2 targetMeshes_ScrollPos;
public override void OnInspectorGUI()
{
//Start the undo event support, draw default inspector and monitor of changes
RuntimeMeshCombiner script = (RuntimeMeshCombiner)target;
EditorGUI.BeginChangeCheck();
Undo.RecordObject(target, "Undo Event");
script.gizmosOfThisComponentIsDisabled = MTAssetsEditorUi.DisableGizmosInSceneView("RuntimeMeshCombiner", script.gizmosOfThisComponentIsDisabled);
//Support reminder
GUILayout.Space(10);
EditorGUILayout.HelpBox("Remember to read the Easy Mesh Combiner documentation to understand how to use it.\nGet support at: mtassets@windsoft.xyz", MessageType.None);
//Check if the component already have a Mesh Renderer and Mesh Filter components, if already have, show a warning
MeshFilter meshFilter = script.GetComponent<MeshFilter>();
MeshRenderer meshRenderer = script.GetComponent<MeshRenderer>();
if (script.isTargetMeshesMerged() == false)
if (meshFilter != null || meshRenderer != null)
{
GUILayout.Space(10);
EditorGUILayout.HelpBox("It looks like this component already contains a Mesh Filter and/or Mesh Renderer component. The Runtime Mesh Combiner will save the mesh resulting from the merge in this GameObject and therefore it needs a GameObject that does not contain either of these two components. Please remove the Mesh Filter and Mesh Renderer from this GameObject or place the Runtime Mesh Combiner in a new empty GameObject, otherwise the API will not allow merges to be done.", MessageType.Error);
}
//Start of preferences
GUILayout.Space(10);
EditorGUILayout.LabelField("Preferences", EditorStyles.boldLabel);
GUILayout.Space(10);
script.afterMerge = (AfterMerge)EditorGUILayout.EnumPopup(new GUIContent("After Combine",
"What do you do after you complete the merge?\n\nDisable Original Meshes - The original meshes will be deactivated, so all the colliders and other components of the scenario will be kept intact, but the meshes will still be combined!\n\nDeactive Original GameObjects - All original GameObjects will be disabled. When you do not need to keep colliders and other active components in the scene, this is a good option!\n\nRelax, however, it is possible to undo the merge later and re-activate everything again!"),
script.afterMerge);
if (script.afterMerge == AfterMerge.DeactiveOriginalGameObjects)
{
EditorGUI.indentLevel += 1;
script.addMeshColliderAfter = (bool)EditorGUILayout.Toggle(new GUIContent("Add Mesh Collider After",
"Add Mesh Collider to the merge mesh after combining?"),
script.addMeshColliderAfter);
EditorGUI.indentLevel -= 1;
}
script.combineMeshesAtStartUp = (CombineOnStart)EditorGUILayout.EnumPopup(new GUIContent("Combine On Start",
"Here you can enable or disable automatic meshing of meshes, right at the beginning of the execution of this scene in your game." +
"\n\nDisabled - Auto merge will not be performed." +
"\n\nOnAwake - Merging will take place in your game's Awake. Awake is executed before all the Start methods in your scene." +
"\n\nOnStart - The merging will be done at the Start of your game."),
script.combineMeshesAtStartUp);
script.combineInChildren = EditorGUILayout.Toggle(new GUIContent("Combine Childrens Too",
"If this option is enabled, the EMC will combine the GameObjects children of the registered GameObjects for merging, too!"),
script.combineInChildren);
script.combineInactives = EditorGUILayout.Toggle(new GUIContent("Combine Inactives Too",
"If this option is active, the EMC will combine inactive GameObjects as well, even if they are registered in the list of meshes to be merged."),
script.combineInactives);
script.recalculateNormals = EditorGUILayout.Toggle(new GUIContent("Recalculate Normals",
"Enable this and the EMC will recalculate the normals of the mesh resulting from the merge. The EMC will preserve the normal data for the original fabrics if this is disabled."),
script.recalculateNormals);
script.recalculateTangents = EditorGUILayout.Toggle(new GUIContent("Recalculate Tangents",
"Enable this and the EMC will recalculate the tangents of the mesh resulting from the merge. The EMC will preserve the tangent data for the original meshes if this is disabled."),
script.recalculateTangents);
script.optimizeResultingMesh = EditorGUILayout.Toggle(new GUIContent("Optimize Resulting Mesh",
"If this option is enabled, the Runtime Mesh Combiner will optimize the mesh resulting from the merge. This may lead to performance gains in rendering the mesh resulting from the merging, through the mechanism of Unity.\n\nThis can slightly increase the mesh processing time."),
script.optimizeResultingMesh);
script.garbageCollectorAfterUndo = EditorGUILayout.Toggle(new GUIContent("Run GC After Undo",
"Garbage Collector will free up memory that was used by unnecessary assets after undoing a merge, but this can negatively impact your game performance, depending on the complexity of the mesh combined. Run garbage collector after undoing a merge?"),
script.garbageCollectorAfterUndo);
//Start of target meshes
GUILayout.Space(10);
EditorGUILayout.LabelField("Target Meshes", EditorStyles.boldLabel);
GUILayout.Space(10);
Texture2D removeItemIcon = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/Plugins/MT Assets/Easy Mesh Combiner/Editor/Images/Remove.png", typeof(Texture2D));
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Target Meshes To Merge", GUILayout.Width(145));
GUILayout.Space(MTAssetsEditorUi.GetInspectorWindowSize().x - 145);
EditorGUILayout.LabelField("Size", GUILayout.Width(30));
EditorGUILayout.IntField(script.targetMeshes.Count, GUILayout.Width(50));
EditorGUILayout.EndHorizontal();
GUILayout.BeginVertical("box");
targetMeshes_ScrollPos = EditorGUILayout.BeginScrollView(targetMeshes_ScrollPos, GUIStyle.none, GUI.skin.verticalScrollbar, GUILayout.Width(MTAssetsEditorUi.GetInspectorWindowSize().x), GUILayout.Height(100));
if (script.targetMeshes.Count == 0)
EditorGUILayout.HelpBox("Oops! No GameObjects with meshes was registered to be combined! If you want to subscribe any, click the button below!", MessageType.Info);
if (script.targetMeshes.Count > 0)
for (int i = 0; i < script.targetMeshes.Count; i++)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button(removeItemIcon, GUILayout.Width(25), GUILayout.Height(16)))
script.targetMeshes.RemoveAt(i);
script.targetMeshes[i] = (GameObject)EditorGUILayout.ObjectField(new GUIContent("GameObject " + i.ToString(), "The mesh found in this GameObject will be combined. Click the button to the left if you want to remove this GameObject from the list."), script.targetMeshes[i], typeof(GameObject), true, GUILayout.Height(16));
GUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
GUILayout.EndVertical();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Add New Slot"))
{
script.targetMeshes.Add(null);
targetMeshes_ScrollPos.y += 999999;
}
if (script.targetMeshes.Count > 0)
if (GUILayout.Button("Remove Empty Slots", GUILayout.Width(Screen.width * 0.48f)))
for (int i = script.targetMeshes.Count - 1; i >= 0; i--)
if (script.targetMeshes[i] == null)
script.targetMeshes.RemoveAt(i);
GUILayout.EndHorizontal();
//Merge Events
GUILayout.Space(10);
EditorGUILayout.LabelField("Merge Events", EditorStyles.boldLabel);
GUILayout.Space(10);
DrawDefaultInspector();
//Start of debug
GUILayout.Space(10);
EditorGUILayout.LabelField("Debug", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.Toggle(new GUIContent("Target Meshes Merged",
"Are the target meshes currently combined?"),
script.isTargetMeshesMerged());
if (script.showDebugLogs == true)
EditorGUILayout.HelpBox("Excessive debug logs can cause performance fluctuations in your game. Just enable this function while debugging your merge and game.", MessageType.Warning);
script.showDebugLogs = EditorGUILayout.Toggle(new GUIContent("Show Debug Logs",
"Debug logs notify you if the combiner encounters any invalid or similar mesh, but excessive debug logs can cause performance fluctuations in your game. View logs for debugging?"),
script.showDebugLogs);
//Final space
GUILayout.Space(10);
//Stop paint of GUI, if this gameobject no more exists
if (script == null)
return;
//Apply changes on script, case is not playing in editor
if (GUI.changed == true && Application.isPlaying == false)
{
EditorUtility.SetDirty(script);
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(script.gameObject.scene);
}
if (EditorGUI.EndChangeCheck() == true)
{
}
}
}
#endregion
#endif
//Component code
void Awake()
{
//Combine meshes on start
if (combineMeshesAtStartUp == CombineOnStart.OnAwake)
{
if (showDebugLogs == true)
Debug.Log("The merge started in Runtime Combiner \"" + this.gameObject.name + "\".");
CombineMeshes();
}
}
void Start()
{
//Combine meshes on start
if (combineMeshesAtStartUp == CombineOnStart.OnStart)
{
if (showDebugLogs == true)
Debug.Log("The merge started in Runtime Combiner \"" + this.gameObject.name + "\".");
CombineMeshes();
}
}
GameObjectWithMesh[] GetValidatedTargetGameObjects()
{
//Validate the target gameobjects and return a list of valids GameObjects with mesh
//Get all found gameobjects in targets gameobjects
List<Transform> foundGameObjects = new List<Transform>();
for (int i = 0; i < targetMeshes.Count; i++)
{
//Skips if this target mesh is null
if (targetMeshes[i] == null)
{
continue;
}
if (combineInChildren == true)
{
Transform[] childrenGameObjectsInThis = targetMeshes[i].GetComponentsInChildren<Transform>(true);
foreach (Transform trs in childrenGameObjectsInThis)
if (foundGameObjects.Contains(trs) == false) //<-- Check if this GameObject has already been added to the list before adding it, to avoid duplicates
foundGameObjects.Add(trs);
}
if (combineInChildren == false)
{
Transform thisGameObjectTrs = targetMeshes[i].GetComponent<Transform>();
if (foundGameObjects.Contains(thisGameObjectTrs) == false) //<-- Check if this GameObject has already been added to the list before adding it, to avoid duplicates
foundGameObjects.Add(thisGameObjectTrs);
}
}
//Validate each found gameobject and split gameobjects that contains mesh filter or/and mesh renderer, and add to list of valid gameObjects
List<GameObjectWithMesh> gameObjectsWithMesh = new List<GameObjectWithMesh>();
for (int i = 0; i < foundGameObjects.Count; i++)
{
MeshFilter mf = foundGameObjects[i].GetComponent<MeshFilter>();
MeshRenderer mr = foundGameObjects[i].GetComponent<MeshRenderer>();
if (mf != null || mr != null)
{
//If combine inactives is disabled, and mesh filter component is disabled in this object, skips this
if (combineInactives == false && mr.enabled == false)
continue;
if (combineInactives == false && foundGameObjects[i].gameObject.activeSelf == false)
continue;
if (combineInactives == false && foundGameObjects[i].gameObject.activeInHierarchy == false)
continue;
gameObjectsWithMesh.Add(new GameObjectWithMesh(foundGameObjects[i].gameObject, mf, mr));
}
}
//Verify if each gameObject with mesh, is valid and have correct components settings
List<GameObjectWithMesh> validsGameObjectsWithMesh = new List<GameObjectWithMesh>();
for (int i = 0; i < gameObjectsWithMesh.Count; i++)
{
bool canAddToValidGameObjects = true;
//Verify if MeshFilter is null
if (gameObjectsWithMesh[i].meshFilter == null)
{
if (showDebugLogs == true)
{
Debug.LogError("GameObject \"" + gameObjectsWithMesh[i].gameObject.name + "\" does not have the Mesh Filter component, so it is not a valid mesh and will be ignored in the merge process.");
}
canAddToValidGameObjects = false;
}
//Verify if MeshRenderer is null
if (gameObjectsWithMesh[i].meshRenderer == null)
{
if (showDebugLogs == true)
{
Debug.LogError("GameObject \"" + gameObjectsWithMesh[i].gameObject.name + "\" does not have the Mesh Renderer component, so it is not a valid mesh and will be ignored in the merge process.");
}
canAddToValidGameObjects = false;
}
//Verify if SharedMesh is null
if (gameObjectsWithMesh[i].meshFilter != null && gameObjectsWithMesh[i].meshFilter.sharedMesh == null)
{
if (showDebugLogs == true)
{
Debug.LogError("GameObject \"" + gameObjectsWithMesh[i].gameObject.name + "\" does not have a Mesh in Mesh Filter component, so it is not a valid mesh and will be ignored in the merge process.");
}
canAddToValidGameObjects = false;
}
//Verify if count of materials is different of count of submeshes
if (gameObjectsWithMesh[i].meshFilter != null && gameObjectsWithMesh[i].meshRenderer != null && gameObjectsWithMesh[i].meshFilter.sharedMesh != null)
{
if (gameObjectsWithMesh[i].meshFilter.sharedMesh.subMeshCount != gameObjectsWithMesh[i].meshRenderer.sharedMaterials.Length)
{
if (showDebugLogs == true)
{
Debug.LogError("The Mesh Renderer component found in GameObject \"" + gameObjectsWithMesh[i].gameObject.name + "\" has more or less material needed. The mesh that is in this GameObject has " + gameObjectsWithMesh[i].meshFilter.sharedMesh.subMeshCount.ToString() + " submeshes, but has a number of " + gameObjectsWithMesh[i].meshRenderer.sharedMaterials.Length.ToString() + " materials. This mesh will be ignored during the merge process.");
}
canAddToValidGameObjects = false;
}
}
//Verify if has null materials in MeshRenderer
if (gameObjectsWithMesh[i].meshRenderer != null)
{
for (int x = 0; x < gameObjectsWithMesh[i].meshRenderer.sharedMaterials.Length; x++)
{
if (gameObjectsWithMesh[i].meshRenderer.sharedMaterials[x] == null)
{
if (showDebugLogs == true)
{
Debug.LogError("Material " + x.ToString() + " in Mesh Renderer present in component \"" + gameObjectsWithMesh[i].gameObject.name + "\" is null. For the merge process to work well, all materials must be completed. This GameObject will be ignored in the merge process.");
}
canAddToValidGameObjects = false;
}
}
}
//Verify if this gameobject is already merged
if (gameObjectsWithMesh[i].gameObject.GetComponent<CombinedMeshesManager>() != null)
{
if (showDebugLogs == true)
{
Debug.LogError("GameObject \"" + gameObjectsWithMesh[i].gameObject.name + "\" is the result of a previous merge, so it will be ignored by this merge.");
}
canAddToValidGameObjects = false;
}
//If can add to valid GameObjects, add this gameobject
if (canAddToValidGameObjects == true)
{
validsGameObjectsWithMesh.Add(gameObjectsWithMesh[i]);
}
}
return validsGameObjectsWithMesh.ToArray();
}
//API Methods
public bool CombineMeshes()
{
//If meshes already are merged
if (isTargetMeshesMerged() == true)
{
if (showDebugLogs == true)
Debug.Log("The Runtime Combiner \"" + this.gameObject.name + "\" meshes are already combined!");
return true;
}
//If meshes is not merged
if (isTargetMeshesMerged() == false)
{
//If this component already have a Mesh Filter and/or Mesh Renderer, cancel the merge
if (this.gameObject.GetComponent<MeshFilter>() != null || this.gameObject.GetComponent<MeshRenderer>() != null)
{
if (showDebugLogs == true)
Debug.LogError("Unable to merge. Apparently the GameObject \"" + this.gameObject.name + "\" already contains the Mesh Filter and/or Mesh Renderer component. The Runtime Mesh Combiner needs a GameObject that does not contain these two components. Please remove them or place the Runtime Mesh Combiner in a new GameObject and try again.");
return false;
}
//Get the original position, rotation and scale of this GameObject and reset
originalPosition = this.gameObject.transform.position;
originalEulerAngles = this.gameObject.transform.eulerAngles;
originalScale = this.gameObject.transform.lossyScale;
this.gameObject.transform.position = Vector3.zero;
this.gameObject.transform.eulerAngles = Vector3.zero;
this.gameObject.transform.localScale = Vector3.one;
//Get the GameObjectsWithMesh validated
GameObjectWithMesh[] validsGameObjectsWithMesh = GetValidatedTargetGameObjects();
//Verify if has valid gameObjects
if (validsGameObjectsWithMesh.Length == 0)
{
if (showDebugLogs == true)
Debug.LogError("No valid, meshed GameObjects were found in the target GameObjects list. Therefore the merge was interrupted.");
return false;
}
//Separate each submesh according to your material
Dictionary<Material, List<SubMeshToCombine>> subMeshesPerMaterial = new Dictionary<Material, List<SubMeshToCombine>>();
for (int i = 0; i < validsGameObjectsWithMesh.Length; i++)
{
GameObjectWithMesh thisGoWithMesh = validsGameObjectsWithMesh[i];
for (int x = 0; x < thisGoWithMesh.meshFilter.sharedMesh.subMeshCount; x++)
{
Material currentMaterial = thisGoWithMesh.meshRenderer.sharedMaterials[x];
if (subMeshesPerMaterial.ContainsKey(currentMaterial) == true)
{
subMeshesPerMaterial[currentMaterial].Add(new SubMeshToCombine(thisGoWithMesh.gameObject.transform, thisGoWithMesh.meshFilter, thisGoWithMesh.meshRenderer, x));
}
if (subMeshesPerMaterial.ContainsKey(currentMaterial) == false)
{
subMeshesPerMaterial.Add(currentMaterial, new List<SubMeshToCombine>() { new SubMeshToCombine(thisGoWithMesh.gameObject.transform, thisGoWithMesh.meshFilter, thisGoWithMesh.meshRenderer, x) });
}
}
}
//Configure this GameObject
MeshFilter holderMeshFilter = this.gameObject.AddComponent<MeshFilter>();
MeshRenderer holderMeshRenderer = this.gameObject.AddComponent<MeshRenderer>();
//Count the vertex in valids gameobjects
int vertexCountInValidsGameObjects = 0;
foreach (GameObjectWithMesh obj in validsGameObjectsWithMesh)
{
vertexCountInValidsGameObjects += obj.meshFilter.sharedMesh.vertexCount;
}
//Combine the submeshes into one submesh according the material
List<Mesh> combinedSubmehesPerMaterial = new List<Mesh>();
foreach (var key in subMeshesPerMaterial)
{
//Get the submeshes to merge, of current material
List<SubMeshToCombine> subMeshesOfCurrentMaterial = key.Value;
//Combine instances of submeshes from this material
List<CombineInstance> combineInstancesOfCurrentMaterial = new List<CombineInstance>();
//Process each submesh
for (int i = 0; i < subMeshesOfCurrentMaterial.Count; i++)
{
CombineInstance combineInstance = new CombineInstance();
combineInstance.mesh = subMeshesOfCurrentMaterial[i].meshFilter.sharedMesh;
combineInstance.subMeshIndex = subMeshesOfCurrentMaterial[i].subMeshIndex;
combineInstance.transform = subMeshesOfCurrentMaterial[i].transform.localToWorldMatrix;
combineInstancesOfCurrentMaterial.Add(combineInstance);
}
//Create the submesh with all submeshes with current material, and set limitation of vertices
Mesh mesh = new Mesh();
#if UNITY_2017_4 || UNITY_2018_1_OR_NEWER
if (vertexCountInValidsGameObjects <= MAX_VERTICES_FOR_16BITS_MESH)
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt16;
if (vertexCountInValidsGameObjects > MAX_VERTICES_FOR_16BITS_MESH)
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
mesh.CombineMeshes(combineInstancesOfCurrentMaterial.ToArray(), true, true);
//Add to list of combined submeshes per material
combinedSubmehesPerMaterial.Add(mesh);
}
//Process each submeshes per material, creating final combine instances
List<CombineInstance> finalCombineInstances = new List<CombineInstance>();
foreach (Mesh mesh in combinedSubmehesPerMaterial)
{
CombineInstance combineInstanceOfThisSubMesh = new CombineInstance();
combineInstanceOfThisSubMesh.mesh = mesh;
combineInstanceOfThisSubMesh.subMeshIndex = 0;
combineInstanceOfThisSubMesh.transform = Matrix4x4.identity;
finalCombineInstances.Add(combineInstanceOfThisSubMesh);
}
//Create the final mesh that contains all submeshes divided per material
Mesh finalMesh = new Mesh();
#if UNITY_2017_4 || UNITY_2018_1_OR_NEWER
if (vertexCountInValidsGameObjects <= MAX_VERTICES_FOR_16BITS_MESH)
finalMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt16;
if (vertexCountInValidsGameObjects > MAX_VERTICES_FOR_16BITS_MESH)
finalMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
#if !UNITY_2017_4 && !UNITY_2018_1_OR_NEWER
if (vertexCountInValidsGameObjects > MAX_VERTICES_FOR_16BITS_MESH)
Debug.Log("The sum of vertices in the target GameObjects is greater than 65k. The resulting mesh may contain artifacts or be deformed. You can work around this issue only if your version of Unity is 2017.4 or higher.");
#endif
finalMesh.name = this.gameObject.name + " (Temp Merge)";
finalMesh.CombineMeshes(finalCombineInstances.ToArray(), false);
finalMesh.RecalculateBounds();
if (recalculateNormals == true)
finalMesh.RecalculateNormals();
if (recalculateTangents == true)
finalMesh.RecalculateTangents();
if (optimizeResultingMesh == true)
finalMesh.Optimize();
//Polulate this GameObject with the data of combined mesh
holderMeshFilter.sharedMesh = finalMesh;
List<Material> materialsForSubMeshes = new List<Material>();
foreach (var key in subMeshesPerMaterial)
{
materialsForSubMeshes.Add(key.Key);
}
holderMeshRenderer.sharedMaterials = materialsForSubMeshes.ToArray();
//Deactive original GameObjects if is desired
if (afterMerge == AfterMerge.DeactiveOriginalGameObjects)
{
foreach (GameObjectWithMesh obj in validsGameObjectsWithMesh)
{
originalGameObjectsWithMeshToRestore.Add(new OriginalGameObjectWithMesh(obj.gameObject, obj.gameObject.activeSelf, obj.meshRenderer, obj.meshRenderer.enabled));
obj.gameObject.SetActive(false);
}
//Add mesh collider, after merge, if disable gameobjects originals
if (addMeshColliderAfter == true)
{
this.gameObject.AddComponent<MeshCollider>();
}
}
//Disable original mesh filters and renderers if is desired
if (afterMerge == AfterMerge.DisableOriginalMeshes)
{
foreach (GameObjectWithMesh obj in validsGameObjectsWithMesh)
{
originalGameObjectsWithMeshToRestore.Add(new OriginalGameObjectWithMesh(obj.gameObject, obj.gameObject.activeSelf, obj.meshRenderer, obj.meshRenderer.enabled));
obj.meshRenderer.enabled = false;
}
}
//Do nothing if is desired
if (afterMerge == AfterMerge.DoNothing)
{
}
//Apply the original position, rotation and scale of this GameObject again
this.gameObject.transform.position = originalPosition;
this.gameObject.transform.eulerAngles = originalEulerAngles;
this.gameObject.transform.localScale = originalScale;
//Show stats
if (showDebugLogs == true)
Debug.Log("The merge has been successfully completed in Runtime Combiner \"" + this.gameObject.name + "\"!");
//Run events
if (onDoneMerge != null)
{
onDoneMerge.Invoke();
}
targetMeshesMerged = true;
return true;
}
return false;
}
public bool UndoMerge()
{
//If meshes already uncombined
if (isTargetMeshesMerged() == false)
{
if (showDebugLogs == true)
Debug.Log("The Runtime Combiner \"" + this.gameObject.name + "\" meshes are already uncombined!");
return true;
}
//If meshes are merged
if (isTargetMeshesMerged() == true)
{
//Undo the merge according the type of merge
if (afterMerge == AfterMerge.DisableOriginalMeshes)
{
foreach (OriginalGameObjectWithMesh original in originalGameObjectsWithMeshToRestore)
{
//Skip, if is null
if (original.meshRenderer == null)
{
continue;
}
original.meshRenderer.enabled = original.originalMrState;
}
}
if (afterMerge == AfterMerge.DeactiveOriginalGameObjects)
{
foreach (OriginalGameObjectWithMesh original in originalGameObjectsWithMeshToRestore)
{
//Skip, if is null
if (original.gameObject == null)
{
continue;
}
original.gameObject.SetActive(original.originalGoState);
}
if (addMeshColliderAfter == true)
{
MeshCollider meshCollider = this.GetComponent<MeshCollider>();
//Remove the mesh collider
if (meshCollider != null)
{
Destroy(meshCollider);
}
}
}
if (afterMerge == AfterMerge.DoNothing)
{
}
//Reset variables
originalGameObjectsWithMeshToRestore.Clear();
//Remove unecessary components
Destroy(this.GetComponent<MeshRenderer>());
Destroy(this.GetComponent<MeshFilter>());
if (garbageCollectorAfterUndo == true)
{
Resources.UnloadUnusedAssets();
System.GC.Collect();
}
//Show stats
if (showDebugLogs == true)
Debug.Log("The Runtime Combiner \"" + this.gameObject.name + "\" merge was successfully undone!");
//Run events
if (onDoneUnmerge != null)
{
onDoneUnmerge.Invoke();
}
targetMeshesMerged = false;
return true;
}
return false;
}
public bool isTargetMeshesMerged()
{
//Return if the meshes are merged
return targetMeshesMerged;
}
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 8556e5c749b98bd4fbf643d3644be6cf
timeCreated: 1572089712
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 976b8d340887eba489742b4c188773f5, type: 3}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 976b8d340887eba489742b4c188773f5
timeCreated: 1572134897
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,87 @@
/////////////////////
MT ASSETS
Credits
/////////////////////
- Fence Model
created by George Piskas
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/FullPreview/Index.cfm/ID/600091 (Free)
- Grass Model
created by Dultcraft Shop
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/FullPreview/Index.cfm/ID/703699 (Free)
- Low Poly Tree
created by PaulsenDesign
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/FullPreview/Index.cfm/ID/961487 (Free)
- Barrel
created by GetDeadEntertainment
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/3d-barrels-industrial-container-1685817 (Free)
- Container
created by Sezar1
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/free-obj-mode-shipping-container/1051656 (Free)
- Big Bin
created by SPACESCAN
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/skip-bin-3d-model-1569563 (Free)
- Wooden Box
created by RensiCG
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/wooden-box-3d-model-1617331 (Free)
- Bucket
created by Medbrat23
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/3d-bucket-1714572 (Free)
- Trash Container
created by zavorad
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/trash-container-3d-model-1652950 (Free)
- Explosive Barrel
created by HuNtEr_3DdD
used through TurboSquid's "Royalty Free License", just as a demonstration model of the operation of this asset.
available in
https://www.turbosquid.com/3d-models/explosive-barrel-low-poly-3d-model-1590597 (Free)
- Traffic Light
created by dimonewave
used through SketchFab "CC Attribution", just as a demonstration model of the operation of this asset.
available in
https://sketchfab.com/3d-models/traffic-light-rust-0f326e6c609546bb9d32381529445550 (Free)
Please note that: All third party assets (that were not created by MT Assets) included here, are used based on
the license of the original authors contained in each asset link. You cannot use the third party assets included
in this package, if you want to use them in your creation, purchase them from each link (informed above) and
make sure you have permission from the author or carefully read the license that is in each link.
However, any asset in this package, which is not listed here, was created by MT Assets, and since you have purchased
this package, you can use them in accordance with the license contained on this package's page on the Asset Store.
If you have any questions about licensing or permission to use assets, do not hesitate to contact us through
mtassets@windsoft.xyz
/////////////////////
Email for support
mtassets@windsoft.xyz
/////////////////////

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4d4c7616c9fa8a247a4cab5a862eadc9
timeCreated: 1545776247
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 69ed9448dd5a473468e8f91b47652e33
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9ab66425ecfaf2747a0d21bf59d1a40e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1df97316e649d2b48b6bf83016f152d2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 820bd2285408fe947893c2f0049e8892
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,31 @@
/* Default Paee CSS */
@import url(default-style/a.css);
@import url(default-style/body.css);
@import url(default-style/footer.css);
@import url(default-style/fullscreenCodeViewer.css);
@import url(default-style/fullscreenImageViewer.css);
@import url(default-style/fullScreenLoading.css);
@import url(default-style/goToTopButton.css);
@import url(default-style/hr.css);
@import url(default-style/processingTime.css);
@import url(default-style/readProgress.css);
@import url(default-style/scrollbar.css);
@import url(default-style/subbody.css);
@import url(default-style/topbar.css);
/* Tool Tags CSS */
@import url(tool-tags-style/achiev.css);
@import url(tool-tags-style/code.css);
@import url(tool-tags-style/detach.css);
@import url(tool-tags-style/icon.css);
@import url(tool-tags-style/frame.css);
@import url(tool-tags-style/image.css);
@import url(tool-tags-style/info.css);
@import url(tool-tags-style/list.css);
@import url(tool-tags-style/table.css);
@import url(tool-tags-style/topicSubtitle.css);
@import url(tool-tags-style/topicTitle.css);
@import url(tool-tags-style/video.css);
@import url(tool-tags-style/warn.css);

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e7955044de381744aa4d11fcdd795804
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7927399c489e1054690cdcca7227d386
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
a {
text-decoration: none;
color: #0046c0;
cursor: pointer;
}
a:link {
text-decoration: none;
color: #0046c0;
}
a:hover {
color: #0046c0;
text-decoration: underline dotted #3a505b;
}
a:visited {
color: #0046c0;
text-decoration: none;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a7f9e1447f9141f4a8e636a8499f754e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
html, body {
height: 100%;
width: 100%;
}
body {
background-color: #686868;
background-repeat: no-repeat;
background-size: 100% 100%;
font-family: Helvetica, sans-seri;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px;
color: #303030;
padding: 0;
margin: 0 auto !important;
overflow-y: scroll;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 26d5b791592301545843097002b43a1a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
.footer{
margin-top: 16px;
padding-top: 8px;
padding-left: 8px;
padding-right: 8px;
padding-bottom: 8px;
width: 95%;
max-width: 1280px;
background-color: #ffffff;
margin-left: auto;
margin-right: auto;
border-radius: 4px;
}
.footerSpacement{
height: 16px;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9b0ce2303115c8943803439b9fa0ab82
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,45 @@
.fullscreenLoadingContent{
width: 100%;
height: 100%;
position: fixed;
pointer-events: all;
opacity: 1.0;
z-index: 100;
transition: 200ms;
}
.fullscreenLoadingBg{
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 95%;
max-width: 1280px;
margin-left: auto;
margin-right: auto;
background-color: #ffffff;
line-height: 24px;
font-weight: bolder;
padding-left: 8px;
padding-right: 8px;
}
.fullscreenLoading{
display: grid;
grid-template-columns: 24px 8px auto;
background-color: #ffffff;
border-radius: 4px;
padding: 8px;
box-shadow: 0px 2px 16px -2px rgba(0, 0, 0, 0.165);
user-select: none;
}
.fullscreenLoading img{
height: 24px;
width: 24px;
animation-name: fullscreenLoading;
animation-duration: 800ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
pointer-events: none;
}
@keyframes fullscreenLoading {
100% { transform: rotateZ(360deg); }
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 80ac3a601a3bec54aa7a7b1d2c8c8ac3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
.fullscreenCodeBackground{
z-index: 800;
position: fixed;
width: 100%;
height: 100%;
background-color: #000000;
transition: all 250ms;
opacity: 0.0;
pointer-events: none;
cursor: zoom-out;
}
.fullscreenCodePopupContent{
z-index: 1000;
position: fixed;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transition: all 250ms;
opacity: 0.0;
pointer-events: none;
}
.fullscreenCodePopup{
background-color: #ffffff;
border-radius: 4px;
padding: 8px;
max-width: 95%;
max-height: 95%;
}
.fullscreenCodeSandboxViewer{
margin-top: 8px;
max-width: 100%;
max-height: 90%;
overflow: auto;
}
.fullscreenCodeSandboxViewer::-webkit-scrollbar {
height: 8px;
border-radius: 4px;
}
.fullscreenCodeSandboxViewer::-webkit-scrollbar-track {
background-color: #00000000;
border-radius: 4px;
}
.fullscreenCodeSandboxViewer::-webkit-scrollbar-thumb {
background: #00000061;
border-radius: 4px;
}
.fullscreenCodeSandboxViewer::-webkit-scrollbar-thumb:hover {
background: #00000061;
border-radius: 4px;
cursor: pointer;
}
.fullscreenCodePopupClose{
display: grid;
grid-template-columns: auto 30px;
}
.fullscreenCodePopupClose div:nth-child(1){
display: flex;
align-items: center;
justify-content: flex-start;
font-weight: bold;
font-size: 18;
}
.fullscreenCodePopupClose img{
width: 30px;
height: 30px;
border-radius: 4px;
pointer-events: none;
margin-left: 1px;
cursor: pointer;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9b25e538a36a9c649bf91b9282c8decb
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
.fullscreenImageBackground{
z-index: 800;
position: fixed;
width: 100%;
height: 100%;
background-color: #000000;
transition: all 250ms;
opacity: 0.0;
pointer-events: none;
cursor: zoom-out;
}
.fullscreenImagePopupContent{
z-index: 1000;
position: fixed;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transition: all 250ms;
opacity: 0.0;
pointer-events: none;
}
.fullscreenImagePopup{
background-color: #ffffff;
border-radius: 4px;
padding: 8px;
}
.fullscreenImagePopup img{
height: 92%;
max-width: auto;
border-radius: 4px;
pointer-events: none;
}
@media screen and (max-width: 720px){
/* IF IS MOBILE */
.fullscreenImagePopup img{
height: auto;
width: 100%;
margin-left: auto;
margin-right: auto;
}
.fullscreenImagePopup{
max-width: 95%;
}
}
.fullscreenImagePopupClose{
width: 32px;
height: 32px;
cursor: pointer;
pointer-events: none;
margin-left: calc(100% - 30px);
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e44c5c44e32c58849bf815db36e3c93f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
.gotoTopButton{
position: fixed;
right: 16px;
bottom: 16px;
width: 32px;
height: 32px;
background-color: #ffffff;
border-radius: 32px;
cursor: pointer;
transition: all 250ms;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
box-shadow: 0px 2px 16px -2px rgba(0, 0, 0, 0.56);
}
.gotoTopButton img{
margin-top: 1px;
margin-right: 1px;
width: 80%;
height: 80%;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 30d1569099da0d34ea413280d96fa81e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
hr {
border: 0;
height: 1px;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(206, 206, 206, 0.75), rgba(0, 0, 0, 0));
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fc1cad9dc0872c84890656ba5877759e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,6 @@
.processingTimeResult{
opacity: 0.5;
}
.processingTimeResult #processingTime{
display: inline;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3db358c00058c6144b025cd962d8a5c3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
.readProgressContainer {
z-index: 400;
position: fixed;
width: 100%;
height: 3px;
background: #d6d6d6;
top: 45;
left: 0;
}
.readProgressBar {
height: 3px;
background: linear-gradient(141deg, #b72c2c 0%, #9f1717 51%, #780c0c 75%);
width: 0%;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fb1444b6f546e7f469b03df4f8414556
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: #d6d6d6;
}
::-webkit-scrollbar-thumb {
background: #292929;
}
::-webkit-scrollbar-thumb:hover {
background: #292929;
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8cd72e66a70234342bf96057405bd2e7
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,224 @@
.subBody{
padding-top: 54px;
padding-left: 8px;
padding-right: 8px;
padding-bottom: 8px;
width: 95%;
max-width: 1280px;
background-color: #ffffff;
margin-left: auto;
margin-right: auto;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
display: grid;
grid-template-columns: 23% 1px auto;
}
@media screen and (max-width: 720px){
/* IF IS MOBILE */
.subBody {
display: block;
}
}
.subBodySummary{
height: 100px;
overflow-y: hidden;
overflow-x: hidden;
transition: all 0ms;
padding-right: 4px;
position: sticky;
top: 0;
}
@media screen and (max-width: 720px){
/* IF IS MOBILE */
.subBodySummary {
display: none;
}
}
.subBodySummary:hover{
overflow-y: scroll;
overflow-x: auto;
padding-right: 0px;
}
@-moz-document url-prefix() {
.subBodySummary{
padding-right: 17px;
}
.subBodySummary:hover{
padding-right: 0px;
}
}
.subBodySummary:nth-child(2){
margin-bottom: 100px;
}
.subBodySummary::-webkit-scrollbar {
width: 4px;
height: 4px;
border-radius: 4px;
}
.subBodySummary::-webkit-scrollbar-track {
background-color: rgba(0, 0, 0, 0.048);
border-radius: 4px;
}
.subBodySummary::-webkit-scrollbar-thumb {
background: #0000002f;
border-radius: 4px;
}
.subBodySummary::-webkit-scrollbar-thumb:hover {
background: #0000002f;
border-radius: 4px;
}
.subBodySummary a{
text-decoration: none;
color: #374f77;
cursor: pointer;
}
.subBodySummary a:hover{
text-decoration: underline dotted #3a505b;
}
.subBodySummaryTitleAndSearch{
display: grid;
grid-template-columns: auto 48px;
}
.subBodySummaryTitle{
display: block;
font-weight: bolder;
font-size: 16px;
text-align: left;
white-space: nowrap;
height: 36px;
margin-top: 12px;
margin-bottom: -4px;
margin-left: 18px;
overflow: hidden;
transition: all 250ms;
width: 224px;
}
.subBodySummarySearchBar{
display: none;
height: 36px;
margin-top: 12px;
margin-bottom: -4px;
margin-left: 18px;
overflow: hidden;
transition: all 250ms;
width: 224px;
}
.subBodySummarySearchBar input[type=text]{
width: 100%;
height: 24px;
outline: none;
border-color: black;
border-radius: 4px;
border-width: 1px;
box-sizing: border-box;
padding-left: 8px;
padding-right: 28px;
}
.subBodySummarySearchResults{
height: 2px;
text-align: center;
font-size: 10px;
transition: all 250ms;
margin-top: -6px;
margin-bottom: 18px;
opacity: 0;
}
.subBodySummarySearchStart{
display: flex;
align-items: center;
justify-content: center;
margin-bottom: -2px;
cursor: pointer;
}
.subBodySummarySearchStart img{
width: 16px;
height: 16px;
}
.subBodySummarySearchEnd{
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
position: absolute;
top: 18px;
left: 4px;
}
.subBodySummarySearchEnd img{
width: 12px;
height: 12px;
}
.subBodySummary ul{
padding-left: 18px;
list-style-type: disc;
}
.subBodySummary li{
font-size: 12px;
margin-right: 14px;
transition: all 150ms;
margin-top: 8px;
margin-bottom: 8px;
}
.summaryItem{
transition: all 150ms;
}
.summaryItemHighlighted{
background-color: rgba(0, 96, 138, 0.15);
padding-left: 4px;
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
border-top-left-radius: 8px;
}
.summaryItemNotConnected{
background-color: rgba(255, 0, 0, 0.15);
padding-left: 4px;
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
border-top-left-radius: 8px;
}
.summaryScrollDownIndicator{
display: flex;
align-items: center;
justify-content: center;
background-color: #ececec;
border-radius: 24px;
transition: opacity 250ms;
pointer-events: none;
animation-name: summaryScrollAnimation;
animation-duration: 1000ms;
animation-iteration-count: infinite;
}
.summaryScrollDownIndicator img{
height: 60%;
transition: all 0ms;
opacity: 0.0;
margin-top: 2px;
}
@keyframes summaryScrollAnimation {
0% { transform: translateY(0px); }
50% { transform: translateY(-4px); }
100% { transform: translateY(0px); }
}
.subBodyDivider{
width: 100%;
height: 100px;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(206, 206, 206, 0.75), rgba(0, 0, 0, 0));
position: sticky;
top: 0;
}
@media screen and (max-width: 720px){
/* IF IS MOBILE */
.subBodyDivider {
display: none;
}
}
.subBodyContent{
margin-left: 16px;
margin-right: 8px;
}
.endOfBodyContentPoint{
width: 100%;
height: 1px;
margin-top: -1px;
position: relative;
bottom: 20px;
}

Some files were not shown because too many files have changed in this diff Show More