Created
March 16, 2015 08:39
-
-
Save yamahigashi/5347b74a06d055e15384 to your computer and use it in GitHub Desktop.
Auto duplicate animation clips at PostprocessModelImport #unity3d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UnityEngine | |
import UnityEditor | |
import System | |
import System.IO | |
import System.Text.RegularExpressions | |
//--------------------------------------------------------------------------// | |
class Mot: | |
public name as string | |
public frame_in as single | |
public frame_out as single | |
public loop as bool | |
public def constructor( _name, _frame_in, _frame_out, _loop ): | |
self.name = _name | |
self.frame_in = _frame_in | |
self.frame_out = _frame_out | |
self.loop = _loop | |
public def ToString(): | |
return "Mot: name:${self.name}, in: ${self.frame_in}, out: ${self.frame_out}, loop: ${self.loop}" | |
/***************************************************************************** | |
* FBXファイルをインポートした際、自動で | |
* | |
* ・インポートオプションの設定 | |
* ・AnimationClip のファイルへの書き出し | |
* | |
* をおこないます | |
* **************************************************************************/ | |
class AnimationAssetProcessor( AssetPostprocessor ): | |
def OnPostprocessModel( g as GameObject ): | |
im as ModelImporter = assetImporter | |
ap as string = assetPath | |
try: | |
AssetDatabase.StartAssetEditing() | |
setImportOptions( im ) | |
setAnimations( im, g, ap ) | |
copyAnimClips( im, g, ap ) | |
AssetDatabase.WriteImportSettingsIfDirty( ap ) | |
EditorApplication.SaveAssets() | |
AssetDatabase.Refresh() | |
except e: | |
Debug.LogError( "make anim error: " + e + "\n" + e.StackTrace ) | |
# StartAssetEditing() をしたら必ずエラーを補足し StopAssetEditing() かけること | |
# さもないとエディタ無反応になる | |
AssetDatabase.StopAssetEditing() | |
def setImportOptions(im as ModelImporter): | |
im.generateAnimations = ModelImporterGenerateAnimations.GenerateAnimations #, UnityEditor.ModelImporterGenerateAnimations, GenerateAnimations | |
im.animationType = ModelImporterAnimationType.Generic #, UnityEditor.ModelImporterAnimationType, Generic | |
#im.bakeIK #, System.Boolean, false | |
#im.isBakeIKSupported #, System.Boolean, false | |
#im.isTangentImportSupported #, System.Boolean, true | |
#im.animationCompression #, UnityEditor.ModelImporterAnimationCompression, KeyframeRuduction | |
#im.animationRotationError #, System.Single, 0.5 | |
#im.animationPositionError #, System.Single, 0.5 | |
#im.animationScaleError #, System.Single, 0.5 | |
#im.animationWrapMode #, UnityEngine.WrapMode, Default | |
#x im.animationType #, UnityEditor.ModelImporterAnimationType, Generic | |
#im.clipAnimations #, UnityEditor.ModelImporterClipAnimation[], | |
def setAnimations( im as ModelImporter, g as GameObject, ap as string ): | |
fname as string = Path.GetFileNameWithoutExtension( ap ).ToLower() | |
// テスト用の設定 | |
mot1 = Mot( "mot1", 0.0, 14.0, false ) | |
mot2 = Mot( "mot2", 15.0, 20.0, true ) | |
mot3 = Mot( "mot3", 21.0, 30.0, false ) | |
motions = ( mot1, mot2, mot3 ) | |
//Debug.Log( "${ap}: アニメーションインポート 分割開始 --------" ) | |
mica as (ModelImporterClipAnimation) = array( ModelImporterClipAnimation, motions.Length ) | |
for i as int, m as Mot in enumerate( motions ): | |
clipName = fname + "${m.name}" | |
mica[i] = ModelImporterClipAnimation() | |
mica[i].takeName = clipName | |
mica[i].name = clipName | |
mica[i].firstFrame = m.frame_in | |
mica[i].lastFrame = m.frame_out | |
mica[i].loopTime = m.loop | |
im.clipAnimations = mica | |
//Debug.Log( "----- ${ap}: アニメーションインポート 分割終了" ) | |
def copyAnimClips( im as ModelImporter, g as GameObject, ap as string ): | |
// FBXに含まれるアニメーションクリップ(複数)を .anim ファイルに書き出す | |
// mecanim(Animator) / Animation 両対応 | |
// 必須コンポーネントの存否チェック | |
animator as Animator = g.GetComponent[of Animator]() | |
anim as Animation = g.GetComponent[of Animation]() | |
if anim == null and animator == null: | |
Debug.LogError( "Animation もしくは Animator Componentが見つからないです" ) | |
#raise NotFoundAnimationOrAnimatorComponent #TODO: later | |
if animator != null: | |
_copyAnimatorClips( im, g, ap ) | |
elif anim != null: | |
_copyAnimationClips( im, g, ap ) | |
// ------------------------------------------------------------------------ // | |
// // | |
// ------------------------------------------------------------------------ // | |
private def _copyAnimationClips( im as ModelImporter, g as GameObject, ap as string ): | |
// Animation コンポーネント のクリップを複製 | |
for x as AnimationClip in AnimationUtility.GetAnimationClips( g ): | |
animpath = _animpath( ap, x.name, "" ) | |
_createClip( x, animpath ) | |
private def _copyAnimatorClips( im as ModelImporter, g as GameObject, ap as string ): | |
// Animator コンポーネント のクリップを複製 | |
// あまり良い方法と思えない・・・ | |
// おそらく Import中メモリにのってる clip 拾いに行ってるんだと思う | |
all as (AnimationClip) = UnityEngine.Object.FindObjectsOfType( typeof(AnimationClip) ) | |
for a as AnimationClip in all: | |
if isIgnoreClip( a ): | |
continue | |
animpath = _animpath( ap, a.name, "" ) | |
_createClip( a, animpath ) | |
// ------------------------------------------------------------------------ // | |
private static def _createClip( clip as AnimationClip, path as string ): | |
# verifying already exsits Anim Clip | |
asset = AssetDatabase.LoadAssetAtPath( path, AnimationClip ) | |
if asset != null: | |
dst as AnimationClip = asset | |
else: | |
newPath as string = AssetDatabase.GenerateUniqueAssetPath( path ) | |
dst = AnimationClip() | |
AssetDatabase.CreateAsset( dst, newPath ) | |
EditorUtility.CopySerialized( clip, dst ) | |
dst.name = clip.name | |
return dst | |
/* CopySerialized 知らなかった時代の名残 | |
private static def _duplicateClip(src as AnimationClip, dst as AnimationClip): | |
for crv as AnimationClipCurveData in AnimationUtility.GetAllCurves(src, true): | |
ecb as EditorCurveBinding = EditorCurveBinding() | |
ecb.path = crv.path | |
ecb.type = crv.type | |
ecb.propertyName = crv.propertyName | |
AnimationUtility.SetEditorCurve( dst, ecb, crv.curve ) | |
return dst | |
*/ | |
// いい感じに anim ファイルの名前、パスを決定する | |
private static def _animpath(path as string, fname as string, postfix as string) as string: | |
folder as string = Path.GetDirectoryName(path) | |
if not postfix == "": | |
return Path.Combine(folder, "${fname}_${postfix}.anim") | |
else: | |
return Path.Combine(folder, "${fname}.anim") | |
// FBXをテキストとして読み、最終フレームを取得する | |
// バイナリfbx?そんなもの投げ捨てろ | |
private static def _getFBXFrameOut(path as string) as int: | |
st as StreamReader = StreamReader(path) | |
t as string = st.ReadToEnd() | |
st.Close() | |
re = Regex("KeyCount: ([0-9]+)", RegexOptions.Multiline) | |
m = re.Match(t) | |
if not m.Success: | |
return -1 | |
res = m.Groups[1].Value | |
return int.Parse(res) - 1 | |
private static def isIgnoreClip( c as AnimationClip ) as bool: | |
# インポート、複製する必要のあるクリップかどうか名前で判定 | |
# __preview__ 外し | |
return true if string.IsNullOrEmpty( c.name ) | |
return true if "__preview__" in c.name | |
return false | |
/* 全 ModelImporter のプロパティ列挙*/ | |
#im.generateMaterials #, UnityEditor.ModelImporterGenerateMaterials, PerTexture | |
#im.importMaterials #, System.Boolean, true | |
#im.materialName #, UnityEditor.ModelImporterMaterialName, BasedOnTextureName | |
#im.materialSearch #, UnityEditor.ModelImporterMaterialSearch, RecursiveUp | |
#im.globalScale #, System.Single, 0 | |
#im.isUseFileUnitsSupported #, System.Boolean, false | |
#im.useFileUnits #, System.Boolean, true | |
#im.addCollider #, System.Boolean, false | |
#im.normalSmoothingAngle #, System.Single, 60 | |
#im.splitTangentsAcrossSeams #, System.Boolean, true | |
#im.swapUVChannels #, System.Boolean, true | |
#im.generateSecondaryUV #, System.Boolean, false | |
#im.secondaryUVAngleDistortion #, System.Single, 8 | |
#im.secondaryUVAreaDistortion #, System.Single, 15 | |
#im.secondaryUVHardAngle #, System.Single, 88 | |
#im.secondaryUVPackMargin #, System.Single, 4 | |
#im.generateAnimations #, UnityEditor.ModelImporterGenerateAnimations, GenerateAnimations | |
#im.transformPaths #, System.String[] | |
#im.referencedClips #, System.String[] | |
#im.isReadable #, System.Boolean, true | |
#im.optimizeMesh #, System.Boolean, true | |
#im.normalImportMode #, UnityEditor.ModelImporterTangentSpaceMode, Import | |
#im.tangentImportMode #, UnityEditor.ModelImporterTangentSpaceMode, Calculate | |
#im.bakeIK #, System.Boolean, false | |
#im.isBakeIKSupported #, System.Boolean, false | |
#im.isTangentImportSupported #, System.Boolean, true | |
#im.meshCompression #, UnityEditor.ModelImporterMeshCompression, Off | |
#im.animationCompression #, UnityEditor.ModelImporterAnimationCompression, KeyframeRuduction | |
#im.animationRotationError #, System.Single, 0.5 | |
#im.animationPositionError #, System.Single, 0.5 | |
#im.animationScaleError #, System.Single, 0.5 | |
#im.animationWrapMode #, UnityEngine.WrapMode, Default | |
#im.animationType #, UnityEditor.ModelImporterAnimationType, Generic | |
#im.clipAnimations #, UnityEditor.ModelImporterClipAnimation[], | |
/* 以下は変更する必要ない | |
im.assetPath #, System.String, | |
im.assetTimeStamp #, System.UInt64, | |
im.userData #, System.String | |
im.name #, System.String | |
im.hideFlags #, UnityEngine.HideFlags, 0 | |
*/ | |
/* 以下はobsolute | |
#im.importedTakeInfos #, UnityEditor.TakeInfo[], | |
#im.reduceKeyframes #, System.Boolean | |
#im.splitAnimations #, System.Boolean | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment