diff --git a/Assets/UniGLTF/MeshUtility/Documentation/images/interface_2.jpg b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_2.jpg
index ce16445a5..aa2f3d15c 100644
Binary files a/Assets/UniGLTF/MeshUtility/Documentation/images/interface_2.jpg and b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_2.jpg differ
diff --git a/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg
new file mode 100644
index 000000000..712ee0531
Binary files /dev/null and b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg differ
diff --git a/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg.meta b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg.meta
new file mode 100644
index 000000000..f51cf076a
--- /dev/null
+++ b/Assets/UniGLTF/MeshUtility/Documentation/images/interface_4.jpg.meta
@@ -0,0 +1,88 @@
+fileFormatVersion: 2
+guid: 669e2a7e945cb8f468940a05224a8efb
+TextureImporter:
+ fileIDToRecycleName: {}
+ externalObjects: {}
+ serializedVersion: 9
+ 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: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ platformSettings:
+ - serializedVersion: 2
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/UniGLTF/MeshUtility/Documentation/notes/MeshSeparator.md b/Assets/UniGLTF/MeshUtility/Documentation/notes/MeshSeparator.md
index d1ad8907b..5b68ab9f5 100644
--- a/Assets/UniGLTF/MeshUtility/Documentation/notes/MeshSeparator.md
+++ b/Assets/UniGLTF/MeshUtility/Documentation/notes/MeshSeparator.md
@@ -4,7 +4,7 @@ MeshSeparator provides a functionality of separating meshes contained BlendShape
## How to use
-Select a GameObject contained skinned mesh and BlendShape:
+Select a GameObject contained skinned mesh and BlendShape (or drag and drop a GameObject to TargetObject field shown below):
@@ -12,10 +12,14 @@ From menu go to `UniGLTF` -> `Mesh Utility` -> `MeshProcessing Wizard`, select `
-The separate meshes are saved in the Assets folder. GameObjects with separate meshes are also available in the Hierarchy Window:
+The separate meshes are saved in the Assets folder.
+In the Hierarchy Window, click the generated GameObject and export.
+
+
+
In this example, the model's mesh are split into two parts: face and body:
Face: with BlendShape | Body: without BlendShape
diff --git a/Assets/UniGLTF/MeshUtility/Editor/MeshProcessDialog.cs b/Assets/UniGLTF/MeshUtility/Editor/MeshProcessDialog.cs
index 7ce167d11..6cecdc4e4 100644
--- a/Assets/UniGLTF/MeshUtility/Editor/MeshProcessDialog.cs
+++ b/Assets/UniGLTF/MeshUtility/Editor/MeshProcessDialog.cs
@@ -1,10 +1,8 @@
+using System;
+using System.Reflection;
using UnityEngine;
using UnityEditor;
-using System.Reflection;
-using MeshUtility;
-using System.IO;
-using System;
-using System.Linq;
+using MeshUtility.M17N;
namespace MeshUtility
{
@@ -34,25 +32,67 @@ namespace MeshUtility
GUIStyle _tabButtonStyle => "LargeButton";
GUI.ToolbarButtonSize _tabButtonSize => GUI.ToolbarButtonSize.Fixed;
+ private enum MeshProcessingMessages
+ {
+ [LangMsg(Languages.ja, "ターゲットオブジェクト")]
+ [LangMsg(Languages.en, "TargetObject")]
+ TARGET_OBJECT,
+
+ [LangMsg(Languages.ja, "BlendShapeを含むメッシュは分割されます")]
+ [LangMsg(Languages.en, "Meshes containing BlendShape will be split")]
+ MESH_SEPARATOR,
+
+ [LangMsg(Languages.ja, "メッシュを統合する。BlendShapeを含むメッシュは独立して統合されます")]
+ [LangMsg(Languages.en, "Generate a single mesh. Meshes w/ BlendShape will be grouped into another one")]
+ MESH_INTEGRATOR,
+
+ [LangMsg(Languages.ja, "静的メッシュを一つに統合する")]
+ [LangMsg(Languages.en, "Integrate static meshes into one")]
+ STATIC_MESH_INTEGRATOR,
+
+ [LangMsg(Languages.ja, "GameObjectを選んでください")]
+ [LangMsg(Languages.en, "Select a GameObject first")]
+ NO_GAMEOBJECT_SELECTED,
+
+ [LangMsg(Languages.ja, "GameObjectにスキンメッシュが含まれていません")]
+ [LangMsg(Languages.en, "No skinned mesh is contained")]
+ NO_SKINNED_MESH,
+
+ [LangMsg(Languages.ja, "GameObjectに静的メッシュが含まれていません")]
+ [LangMsg(Languages.en, "No static mesh is contained")]
+ NO_STATIC_MESH,
+
+ [LangMsg(Languages.ja, "GameObjectにスキンメッシュ・静的メッシュが含まれていません")]
+ [LangMsg(Languages.en, "Skinned/Static mesh is not contained")]
+ NO_MESH,
+
+ [LangMsg(Languages.ja, "ターゲットオブジェクトはVRMモデルです。`VRM0-> MeshIntegrator`を使ってください")]
+ [LangMsg(Languages.en, "Target object is VRM model, use `VRM0 -> MeshIntegrator` instead")]
+ VRM_DETECTED,
+ }
+
private void OnGUI()
{
EditorGUIUtility.labelWidth = 150;
+ // lang
+ Getter.OnGuiSelectLang();
+
_tab = TabBar.OnGUI(_tab, _tabButtonStyle, _tabButtonSize);
switch (_tab)
{
case Tabs.MeshSeparator:
- EditorGUILayout.TextField("Meshes containing BlendShape data will be split");
+ EditorGUILayout.TextField(MeshProcessingMessages.MESH_SEPARATOR.Msg());
break;
case Tabs.MeshIntegrator:
- EditorGUILayout.TextField("Generate a single mesh. Meshes w/ BlendShape will be grouped into another one");
+ EditorGUILayout.TextField(MeshProcessingMessages.MESH_INTEGRATOR.Msg());
break;
case Tabs.StaticMeshIntegrator:
- EditorGUILayout.TextField("Integrate static meshes into one");
+ EditorGUILayout.TextField(MeshProcessingMessages.STATIC_MESH_INTEGRATOR.Msg());
break;
}
- EditorGUILayout.LabelField("ExportTarget");
+ EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg());
_exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true);
if (_exportTarget == null && MeshUtility.IsGameObjectSelected())
{
@@ -111,7 +151,7 @@ namespace MeshUtility
private bool GameObjectNull()
{
- EditorUtility.DisplayDialog("Failed", "No GameObject Selected", "ok");
+ EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok");
return false;
}
@@ -127,7 +167,7 @@ namespace MeshUtility
}
else
{
- EditorUtility.DisplayDialog("Failed", "No skinned mesh contained", "ok");
+ EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok");
return false;
}
}
@@ -146,7 +186,7 @@ namespace MeshUtility
var sourceString = component.ToString();
if (sourceString.Contains(keyWord))
{
- EditorUtility.DisplayDialog("Failed", "Target object is VRM file, use `VRM0 -> MeshIntegrator` instead", "ok");
+ EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok");
return false;
}
}
@@ -158,7 +198,7 @@ namespace MeshUtility
}
else
{
- EditorUtility.DisplayDialog("Failed", "Neither skinned mesh nor static mesh contained", "ok");
+ EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok");
return false;
}
}
@@ -174,7 +214,7 @@ namespace MeshUtility
}
else
{
- EditorUtility.DisplayDialog("Failed", "No static mesh contained", "ok");
+ EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_STATIC_MESH.Msg(), "ok");
return false;
}
}
diff --git a/Assets/UniGLTF/MeshUtility/Editor/MeshUtility.cs b/Assets/UniGLTF/MeshUtility/Editor/MeshUtility.cs
index 400d752a9..a7eb133de 100644
--- a/Assets/UniGLTF/MeshUtility/Editor/MeshUtility.cs
+++ b/Assets/UniGLTF/MeshUtility/Editor/MeshUtility.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
@@ -9,14 +9,9 @@ namespace MeshUtility
public class MeshUtility
{
public const string MENU_PARENT = "UniGLTF/Mesh Utility/";
-
private const string ASSET_SUFFIX = ".mesh.asset";
- private const string MENU_NAME = MENU_PARENT + "MeshSeparator";
private static readonly Vector3 ZERO_MOVEMENT = Vector3.zero;
- private const string INTEGRATED_MESH_NAME = "MeshesIntegrated";
- private const string INTEGRATED_MESH_BLENDSHAPE_NAME = "MeshesBlendShapeIntegrated";
-
public static Object GetPrefab(GameObject instance)
{
#if UNITY_2018_2_OR_NEWER
@@ -32,15 +27,6 @@ namespace MeshUtility
WithoutBlendShape,
}
- [MenuItem(MENU_NAME, validate = true)]
- private static bool ShowLogValidation()
- {
- if (Selection.activeTransform == null)
- return false;
- else
- return true;
- }
-
[MenuItem(MENU_PARENT + "MeshUtility Docs", priority = 32)]
public static void LinkToMeshSeparatorDocs()
{
@@ -344,32 +330,35 @@ namespace MeshUtility
// destroy integrated meshes in the source
foreach (var skinnedMesh in go.GetComponentsInChildren())
{
- if (skinnedMesh.sharedMesh.name == INTEGRATED_MESH_NAME)
+ if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME ||
+ skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)
{
GameObject.DestroyImmediate(skinnedMesh.gameObject);
}
}
- // destroy original meshes in the copied GameObject
foreach (var skinnedMesh in skinnedMeshes)
{
- if (skinnedMesh.sharedMesh.name != INTEGRATED_MESH_NAME)
- {
- GameObject.DestroyImmediate(skinnedMesh);
- }
- // avoid repeated name
- else if (skinnedMesh.sharedMesh.blendShapeCount > 0)
- {
- skinnedMesh.sharedMesh.name = INTEGRATED_MESH_BLENDSHAPE_NAME;
- }
- // check if the integrated mesh is empty
- else if (skinnedMesh.sharedMesh.subMeshCount == 0)
- {
- GameObject.DestroyImmediate(skinnedMesh.gameObject);
- }
+ // destroy original meshes in the copied GameObject
+ if (!(skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME ||
+ skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME))
+ {
+ GameObject.DestroyImmediate(skinnedMesh);
+ }
+ // check if the integrated mesh is empty
+ else if (skinnedMesh.sharedMesh.subMeshCount == 0)
+ {
+ GameObject.DestroyImmediate(skinnedMesh.gameObject);
+ }
+ // save mesh data
+ else if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME ||
+ skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)
+ {
+ // SaveMeshData(skinnedMesh.sharedMesh);
+ }
}
foreach (var normalMesh in normalMeshes)
{
- if (normalMesh.sharedMesh.name != INTEGRATED_MESH_NAME)
+ if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME)
{
if (normalMesh.gameObject.GetComponent())
{
@@ -379,5 +368,22 @@ namespace MeshUtility
}
}
}
+
+ private static void SaveMeshData(Mesh mesh)
+ {
+ var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX);
+ Debug.Log(assetPath);
+ if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh))))
+ {
+ var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/");
+ assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX);
+ }
+ else
+ {
+ assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX);
+ }
+ Debug.LogFormat("CreateAsset: {0}", assetPath);
+ AssetDatabase.CreateAsset(mesh, assetPath);
+ }
}
}
\ No newline at end of file
diff --git a/Assets/UniGLTF/MeshUtility/Runtime/MeshIntegratorUtility.cs b/Assets/UniGLTF/MeshUtility/Runtime/MeshIntegratorUtility.cs
index 2f5b343ef..8285af6e6 100644
--- a/Assets/UniGLTF/MeshUtility/Runtime/MeshIntegratorUtility.cs
+++ b/Assets/UniGLTF/MeshUtility/Runtime/MeshIntegratorUtility.cs
@@ -6,6 +6,8 @@ namespace MeshUtility
{
public static class MeshIntegratorUtility
{
+ public const string INTEGRATED_MESH_NAME = "MeshesIntegrated";
+ public const string INTEGRATED_MESH_BLENDSHAPE_NAME = "MeshesBlendShapeIntegrated";
///
/// go を root としたヒエラルキーから Renderer を集めて、統合された Mesh 作成する
///
@@ -54,7 +56,6 @@ namespace MeshUtility
}
var mesh = new Mesh();
- mesh.name = "MeshesIntegrated";
if (integrator.Positions.Count > ushort.MaxValue)
{
@@ -77,6 +78,11 @@ namespace MeshUtility
if (onlyBlendShapeRenderers)
{
integrator.AddBlendShapesToMesh(mesh);
+ mesh.name = INTEGRATED_MESH_BLENDSHAPE_NAME;
+ }
+ else
+ {
+ mesh.name = INTEGRATED_MESH_NAME;
}
var integrated = meshNode.AddComponent();
diff --git a/Assets/UniGLTF/MeshUtility/Runtime/StaticMeshIntegrator.cs b/Assets/UniGLTF/MeshUtility/Runtime/StaticMeshIntegrator.cs
index 219b0d04f..e865b5a17 100644
--- a/Assets/UniGLTF/MeshUtility/Runtime/StaticMeshIntegrator.cs
+++ b/Assets/UniGLTF/MeshUtility/Runtime/StaticMeshIntegrator.cs
@@ -66,7 +66,7 @@ namespace MeshUtility
public Mesh ToMesh()
{
var mesh = new Mesh();
- mesh.name = "MeshesIntegrated";
+ mesh.name = MeshIntegratorUtility.INTEGRATED_MESH_NAME;
mesh.vertices = m_positions.ToArray();
if (m_normals.Count > 0)