LanguageManager 추가
This commit is contained in:
8
Assets/@Eden_Tools.meta
Normal file
8
Assets/@Eden_Tools.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcaa6555c32099948b000b2924ed7e2f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4826438966086d644a3997c5803cf5aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/LanguageManager.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/LanguageManager.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 839d259bdc2a4ec45b739da7ecbf4e70
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3c01fc12e499944da78f3441a00f36a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,213 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "Auto Fitting Mode"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "Manual Fitting Mode"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "Profile Mode"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Failed to find Body Mesh."
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[EN] Could not find key: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "Manual Setting Mode\n1. Assign the Objects and Meshes for the Source / Target Avatars.\n2. Adjust the target clothes object (Target Clothes Object) to match the target avatar.\n3. Press [Run Fitting] to start the fitting.\n4. Press [Run Weighting] to start weight assignment."
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "Auto Setting Mode\n1. Assign the Source avatar body and clothing objects to the Source Avatar.\n2. Assign the target avatar body to the Target Avatar.\n3. Press [Run Fitting] to begin fitting.\n4. Press [Run Weighting] to start weight assignment."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "If the clothes stick too closely to the body, increase the MinMargin value. (Default: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Check this option to disable foot-based shape corrections during the fitting stage."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "Automatically Assign Body Mesh"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "If the body mesh cannot be detected automatically, \nplease manually assign the mesh corresponding to the body (excluding the head) to Body Meshes."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "Increasing this value makes a wider area of the clothing deform smoothly together. (Default: 0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "Increasing this value applies the Smooth effect more strongly, making the deformation smoother. (Default: 1)\n - Higher values will increase computation time."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "If you want more deformation for the clothes, increase the number of fitting iterations."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Moves and places accessory bones into the target avatar’s armature during weighting."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "The following items must all be assigned:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "The Source Clothes Object must be a child of the Source Avatar Object.\n→ Please place the clothes under the Source Avatar object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "The Target Clothes Object must be a child of the Target Avatar Object.\n→ Please place the clothes under the Target Avatar object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - The Bone Armature referenced by the SkinnedMeshRenderer is not correctly included in the Clothes Object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "The Source Avatar Object does not have a Humanoid Avatar assigned.\n→ Please check the Animator component and Avatar settings."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "The Target Avatar Object does not have a Humanoid Avatar assigned.\n→ Please check the Animator component and Avatar settings."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "The number of SkinnedMeshRenderers in the Source / Target Clothes does not match."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "The vertex count of the corresponding SkinnedMeshRenderer meshes does not match."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "Unable to run\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null Error"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Failed to assign the Body Proxy.\nPlease make sure the Source Avatar is correctly assigned and the bones are properly set in the Animator."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh Not Found"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Could not find the Source Body Mesh."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh Not Found"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Could not find the Target Body Mesh."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "BodyMesh Search Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "The BodyMesh of [{0}] could not be found."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null Error"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers contains one or more null elements."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance Allocation Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "No ClothInstance could be allocated.\nPlease check if the clothes have a SkinnedMeshRenderer."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting Is Not Ready"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "Fitting has not finished before calling WeightingEnumerator, or the Target Avatar has been changed.\nPlease run Run Fitting again."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH Creation Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "Failed to build BVH for {0}.\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "This section is for generating Profile data.\nPlease set the avatar Scale to 1,1,1.\nAdjust ShapeKeys so that the avatar BodyMesh is not occluded."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "Name of the Profile to be saved"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Avatar root Transform with Humanoid Rig and Animator configured"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "List of body SkinnedMeshRenderers used for Profile generation"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name is empty."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar is not assigned."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar does not have an Animator."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes is empty."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes contains NULL."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes must be children of the Source Avatar."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "No Base file exists in the BaseData folder."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0aa9f12300a0596408771775b2d5148e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "自動セットアップモード"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "手動セットアップモード"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "プロファイルモード"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Body Mesh を見つけられませんでした。"
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[JP] キーが見つかりません: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "手動セットアップモード\n1. Source / Target Avatar に対応するオブジェクトとメッシュを割り当ててください。\n2. 対応する衣装(Target Clothes Object)をターゲットアバターに合わせて調整してください。\n3. [Run Fitting] を押してフィッティングを開始してください。\n4. [Run Weighting] を押してウェイト割り当てを開始してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "自動セットアップモード\n1. Source Avatar にソースアバターのボディと衣装オブジェクトを割り当ててください。\n2. Target Avatar にターゲットアバターのボディを割り当ててください。\n3. [Run Fitting] を押してフィッティングを開始してください。\n4. [Run Weighting] を押してウェイト割り当てを開始してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "衣装が体に密着しすぎる場合は、MinMarginの値を大きくしてください。(初期値: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Fitting工程において、足(foot)を基準とした形状補正を適用しない場合はチェックしてください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "ボディメッシュを自動で割り当てる"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "ボディメッシュを自動で検出できない場合は、\n(頭部を除く)ボディに該当するメッシュを Body Meshes に手動で割り当ててください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "値を上げるほど、衣装のより広い範囲が一緒に滑らかに変形します。(初期値:0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "値を上げるほど、Smooth効果がより強く適用され、変形がより滑らかになります。(初期値:1)\n - 値を上げると処理時間が長くなります。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "衣装をさらに変形させたい場合は、Fittingの反復回数を増やしてください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Weighting 時にアクセサリーボーンを Target アバターのアーマチュアへ移動して配置します。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "次の項目がすべて割り当てられている必要があります:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "Source Clothes Object は必ず Source Avatar Object の子オブジェクトである必要があります。\n→ Source Avatar オブジェクトの下に衣装を配置してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "Target Clothes Object は必ず Target Avatar Object の子オブジェクトである必要があります。\n→ Target Avatar オブジェクトの下に衣装を配置してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - Clothes オブジェクトに、SkinnedMeshRenderer が参照するボーンアーマチュアが正しく含まれていません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "Source Avatar Object に Humanoid Avatar が設定されていません。\n→ Animator コンポーネントと Avatar 設定を確認してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "Target Avatar Object に Humanoid Avatar が設定されていません。\n→ Animator コンポーネントと Avatar 設定を確認してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "Source / Target Clothes の SkinnedMeshRenderer の数が一致していません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "対応する SkinnedMeshRenderer の Mesh vertex 数が一致していません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "を実行できません\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null エラー"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Body Proxy を割り当てることができませんでした。\nSource Avatar が正しく割り当てられているか、Animator にボーンが正しく設定されているか確認してください。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh を見つけることができませんでした。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh を見つけることができませんでした。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "BodyMesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "[{0}] の BodyMesh を見つけることができません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null エラー"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers に null が含まれています。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance の割り当てに失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "割り当て可能な ClothInstance がありません。\n衣装に SkinnedMeshRenderer が含まれているか確認してください。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting の準備ができていません"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "WeightingEnumerator を呼び出す前に Fitting が完了していないか、Target Avatar が変更されています。\nRun Fitting を再実行してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH の生成に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "{0} の BVH の生成に失敗しました。\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "Profileデータ生成のための設定です。\nアバターのScaleは 1,1,1 に設定してください。\nアバターのBodyMeshが隠れないようにShapeKeyを調整してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "保存されるProfileの名前"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Humanoid Rig と Animator が設定された Avatar の Root Transform"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "Profile生成に使用される Body SkinnedMeshRenderer の一覧"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name が空です。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar が指定されていません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar に Animator が存在しません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes が空です。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes に NULL が含まれています。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes は必ず Source Avatar の子オブジェクトである必要があります。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "BaseData フォルダに Base ファイルが存在しません。"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07befa424eefac04e8670c57d4c2a2ec
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "자동 셋팅 모드"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "직접 셋팅 모드"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "프로필 모드"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Body Mesh를 찾지 못했습니다."
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[KO] 해당 키를 찾을 수 없습니다: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "직접 셋팅 모드\n1. Source / Target Avatar에 해당하는 Object와 Mesh들을 할당해 주세요.\n2. 대응할 의상(Target Clothes Object)을 대응할 아바타에 맞춰 조정해주세요.\n3. [Run Fitting]을 눌러서 대응을 시작하세요.\n4. [Run Weighting]을 눌러서 Weight 할당을 시작하세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "자동 셋팅 모드\n1. Source Avatar에 Source 아바타 바디와 의상 Object를 할당해주세요.\n2. Target Avatar에 Target 아바타 바디를 할당해주세요.\n3. [Run Fitting]을 눌러 대응을 시작하세요.\n4. [Run Weighting]을 눌러서 Weight 할당을 시작하세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "의상이 몸에 너무 달라 붙는다면, MinMargin 값을 늘려주세요. (초기값: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Fitting 단계에서 발(foot) 기준의 형태 보정을 적용하지 않으려면 체크해주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "Body Mesh 자동으로 할당하기."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "Body Mesh를 자동으로 찾지 못 할 경우, \n(Head 제외) 바디에 해당하는 Mesh를 Body Meshes에 할당해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "값을 높일수록 의상의 더 넓은 부분이 함께 부드럽게 변형됩니다. (초기값: 0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "값을 높일수록 Smooth 효과가 더 많이 적용되어 변형이 더욱 부드러워집니다. (초기값: 1)\n - 값이 높아질수록 연산 시간이 증가합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "의상을 더 많이 변형시키고 싶다면, Fitting 반복 횟수를 늘려주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Weighting시 악세서리 본을 Target Avatar에 Armature로 옮겨 배치합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "다음 항목이 모두 할당되어야 합니다:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "Source Clothes Object 는 반드시 Source Avatar Object 의 자식이어야 합니다.\n→ Source Avatar 오브젝트 하위에 의상을 넣어 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "Target Clothes Object 는 반드시 Target Avatar Object 의 자식이어야 합니다.\n→ Target Avatar 오브젝트 하위에 의상을 넣어 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - 의상에 SkinnedMeshRenderer가 참조하는 Bone Armature가 올바르게 포함되어 있지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "Source Avatar Object 에 Humanoid Avatar 가 설정되어 있지 않습니다.\n→ Animator 컴포넌트 및 Avatar 설정을 확인해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "Target Avatar Object 에 Humanoid Avatar 가 설정되어 있지 않습니다.\n→ Animator 컴포넌트 및 Avatar 설정을 확인해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "Source / Target Clothes 의 SkinnedMeshRenderer 개수가 일치하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "대응되는 SkinnedMeshRenderer 의 Mesh vertex 수가 일치하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "실행 불가\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null 에러"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Body Proxy를 할당할 수 없습니다.\nSource Avatar가 제대로 할당되어 있으며, Animator에 본이 제대로 셋팅되어 있는지 확인해주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "[{0}]의 Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null 에러"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers 에 null 이 포함되어 있습니다."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance 할당 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "할당할 수 있는 ClothInstance가 없습니다.\n의상에 SkinnedMeshRenderer가 있는지 확인해주세요."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting이 준비되지 않았습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "WeightingEnumerator 호출 전 Fitting이 완료되지 않았거나, Target Avatar가 변경되었습니다.\nRun Fitting을 다시 실행해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH 생성 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "{0} 의 BVH를 만드는데 실패하였습니다.\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "Profile 데이터 생성을 위한 설정 영역입니다.\n아바타의 Scale은 1,1,1로 맞춰주세요.\n아바타의 BodyMesh가 가려지지 않도록 ShapeKey를 조절해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "저장될 Profile 이름"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Humanoid Rig + Animator가 설정된 Avatar Root Transform"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "Profile 생성에 사용될 Body SkinnedMeshRenderer 목록"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name이 비어 있습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar가 지정되지 않았습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar에 Animator가 존재하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes가 비어 있습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes에 NULL이 존재합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes 는 반드시 Source Avatar 의 자식이어야 합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "BaseData 폴더에 Base 파일이 존재하지 않습니다."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06a08864e1cbb6740a46cbde54883c6a
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,285 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace Eden.AutoMorpher
|
||||
{
|
||||
public enum Language
|
||||
{
|
||||
Korean = 0,
|
||||
Japanese = 1,
|
||||
English = 2,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LocalizationEntry
|
||||
{
|
||||
public string key;
|
||||
public string value;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LocalizationFile
|
||||
{
|
||||
public LocalizationEntry[] entries;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
#endif
|
||||
public static class LanguageManager
|
||||
{
|
||||
private const string PREF_KEY_LANG = "EdenAutoMorpher_Language";
|
||||
|
||||
private const string PATH_KO = "Language/Language_ko";
|
||||
private const string PATH_JA = "Language/Language_ja";
|
||||
private const string PATH_EN = "Language/Language_en";
|
||||
|
||||
private static Language _currentLanguage = Language.Korean;
|
||||
|
||||
private static Dictionary<string, string> _koTable;
|
||||
private static Dictionary<string, string> _jaTable;
|
||||
private static Dictionary<string, string> _enTable;
|
||||
|
||||
public static Language CurrentLanguage
|
||||
{
|
||||
get => _currentLanguage;
|
||||
set
|
||||
{
|
||||
if (_currentLanguage == value) return;
|
||||
_currentLanguage = value;
|
||||
#if UNITY_EDITOR
|
||||
EditorPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
|
||||
#else
|
||||
PlayerPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
|
||||
PlayerPrefs.Save();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static LanguageManager()
|
||||
{
|
||||
// Editor 시작 시 언어 로드
|
||||
#if UNITY_EDITOR
|
||||
int saved = EditorPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
|
||||
#else
|
||||
int saved = PlayerPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
|
||||
#endif
|
||||
_currentLanguage = (Language)Mathf.Clamp(saved, 0, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 언어에서 문자열 가져오기.
|
||||
/// key 없으면 fallback → 다른 언어 → 최종적으로 key 자체 반환.
|
||||
/// </summary>
|
||||
public static string Get(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return string.Empty;
|
||||
|
||||
// 현재 언어 테이블에서 먼저 검색
|
||||
if (TryGetFromCurrentLanguage(key, out string value))
|
||||
return value;
|
||||
|
||||
return FormatKeyNotFound(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 언어별로 다른 키를 쓰고 싶을 때 (번호 기반 등)도 가능하도록
|
||||
/// 번호를 바로 key 문자열로 변환해서 사용하는 버전.
|
||||
/// </summary>
|
||||
public static string GetById(int id)
|
||||
{
|
||||
// 예: "ID.1001" 이런 식으로 통일하면 관리가 편함
|
||||
string key = $"ID.{id}";
|
||||
return Get(key);
|
||||
}
|
||||
|
||||
public static void SetLanguage(Language lang)
|
||||
{
|
||||
CurrentLanguage = lang;
|
||||
}
|
||||
|
||||
// ================== 내부 구현 ==================
|
||||
|
||||
private static bool TryGetFromCurrentLanguage(string key, out string value)
|
||||
{
|
||||
var table = GetTable(_currentLanguage);
|
||||
if (table != null && table.TryGetValue(key, out value))
|
||||
return true;
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGetFromOtherLanguages(string key, out string value)
|
||||
{
|
||||
// 현재 언어 제외한 나머지 순회
|
||||
foreach (Language lang in System.Enum.GetValues(typeof(Language)))
|
||||
{
|
||||
if (lang == _currentLanguage)
|
||||
continue;
|
||||
|
||||
var table = GetTable(lang);
|
||||
if (table != null && table.TryGetValue(key, out value))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> GetTable(Language lang)
|
||||
{
|
||||
switch (lang)
|
||||
{
|
||||
case Language.Korean:
|
||||
if (_koTable == null)
|
||||
_koTable = LoadTable(PATH_KO);
|
||||
return _koTable;
|
||||
|
||||
case Language.Japanese:
|
||||
if (_jaTable == null)
|
||||
_jaTable = LoadTable(PATH_JA);
|
||||
return _jaTable;
|
||||
|
||||
case Language.English:
|
||||
if (_enTable == null)
|
||||
_enTable = LoadTable(PATH_EN);
|
||||
return _enTable;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// fileName: "lang_ko", "lang_ja", "lang_en" 처럼 사용
|
||||
private static Dictionary<string, string> LoadTable(string fileName)
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// 스크립트 기준 Language 폴더 아래의 json 경로
|
||||
string assetPath = GetLanguageJsonAssetPath(fileName);
|
||||
// Assets/... 형식 경로를 실제 디스크 경로로 변환
|
||||
string fullPath = Path.GetFullPath(assetPath);
|
||||
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Debug.LogWarning($"[AutoMorpherLanguage] Localization file not found: {fullPath}");
|
||||
return dict;
|
||||
}
|
||||
|
||||
string jsonText;
|
||||
try
|
||||
{
|
||||
// ✅ 강제로 UTF-8 로 읽기 (BOM 유무 상관 없음)
|
||||
jsonText = File.ReadAllText(fullPath, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[AutoMorpherLanguage] Failed to read localization file: {fullPath}\n{ex}");
|
||||
return dict;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var file = JsonUtility.FromJson<LocalizationFile>(jsonText);
|
||||
if (file?.entries != null)
|
||||
{
|
||||
foreach (var entry in file.entries)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry.key))
|
||||
continue;
|
||||
|
||||
dict[entry.key] = entry.value ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[AutoMorpherLanguage] Failed to parse localization file: {fullPath}\n{ex}");
|
||||
}
|
||||
#else
|
||||
// 런타임 빌드에서 쓸 계획이 없으면 비워둬도 됨
|
||||
#endif
|
||||
return dict;
|
||||
}
|
||||
private static string FormatKeyNotFound(string key)
|
||||
{
|
||||
// 먼저 현재 언어의 "Error.KeyNotFound" 가져오기
|
||||
if (TryGetFromCurrentLanguage("Error.KeyNotFound", out string template))
|
||||
return template.Replace("{0}", key);
|
||||
|
||||
// JSON 자체가 없어서 템플릿도 없는 경우 (최후 fallback)
|
||||
switch (CurrentLanguage)
|
||||
{
|
||||
case Language.Korean:
|
||||
return $"[KO] 해당 키를 찾을 수 없습니다: {key}";
|
||||
case Language.Japanese:
|
||||
return $"[JP] キーが見つかりません: {key}";
|
||||
default:
|
||||
return $"[EN] Could not find key: {key}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string GetLanguageFolderPath()
|
||||
{
|
||||
string scriptDir = "Assets\\@Eden_Tools\\Eden_AutoMorpher\\LanguageManager\\Language";
|
||||
#if UNITY_EDITOR
|
||||
// AutoMorpherLanguage 스크립트의 GUID 찾기
|
||||
string[] guids = AssetDatabase.FindAssets("LanguageManager t:MonoScript");
|
||||
if (guids == null || guids.Length == 0)
|
||||
{
|
||||
Debug.LogError("[LanguageManager] Could not find LanguageManager.cs script.");
|
||||
return "Assets"; // 최소 fallback
|
||||
}
|
||||
|
||||
string scriptPath = AssetDatabase.GUIDToAssetPath(guids[0]); // 예: Assets/@Eden_Tools/.../AutoMorpherLanguage.cs
|
||||
scriptDir = Path.GetDirectoryName(scriptPath); // 그 폴더
|
||||
|
||||
|
||||
// 폴더가 없으면 에디터에서 자동 생성
|
||||
if (!Directory.Exists(scriptDir))
|
||||
{
|
||||
Directory.CreateDirectory(scriptDir);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
#endif
|
||||
// Unity Asset 경로 포맷으로 정리
|
||||
scriptDir = scriptDir.Replace("\\", "/");
|
||||
return scriptDir;
|
||||
}
|
||||
|
||||
public static string GetLanguageJsonAssetPath(string fileNameWithoutExt)
|
||||
{
|
||||
string folder = GetLanguageFolderPath();
|
||||
string path = Path.Combine(folder, fileNameWithoutExt + ".json");
|
||||
return path.Replace("\\", "/");
|
||||
}
|
||||
|
||||
public static string GetFormat(string key, params object[] args)
|
||||
{
|
||||
string raw = Get(key);
|
||||
if (string.IsNullOrEmpty(raw))
|
||||
return string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
return string.Format(raw, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LanguageManager] Format failed for key: {key}\n{ex}");
|
||||
return raw; // 최소한 원문이라도 보여주기
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4990eee90808bc488656e484f9ea0d8
|
||||
Reference in New Issue
Block a user