// ================================================================================ // import methods // -------------------------------------------------------------------------------- public void ImportAssets(DefaultAsset[] assets, ImportAnimatorController importAnimatorController = ImportAnimatorController.None) { List <AnimationImportJob> jobs = new List <AnimationImportJob>(); foreach (var asset in assets) { string assetPath = AssetDatabase.GetAssetPath(asset); if (!IsValidAsset(assetPath)) { continue; } AnimationImportJob job = CreateAnimationImportJob(assetPath); job.importAnimatorController = importAnimatorController; jobs.Add(job); } Import(jobs.ToArray()); }
/// <summary> /// can be used by custom import pipeline /// </summary> public ImportedAnimationSheet ImportSpritesAndAnimationSheet(string assetPath, string additionalCommandLineArguments = null) { if (!IsValidAsset(assetPath)) { return(null); } // making sure config is valid if (sharedData == null) { LoadOrCreateUserConfig(); } // create a job AnimationImportJob job = CreateAnimationImportJob(assetPath, additionalCommandLineArguments); job.createUnityAnimations = false; return(ImportJob(job)); }
// ================================================================================ // automatic ReImport // -------------------------------------------------------------------------------- /// <summary> /// will be called by the AssetPostProcessor /// </summary> public void AutomaticReImport(string[] assetPaths) { if (sharedData == null) { LoadOrCreateUserConfig(); } List <AnimationImportJob> jobs = new List <AnimationImportJob>(); foreach (var assetPath in assetPaths) { if (string.IsNullOrEmpty(assetPath)) { continue; } if (HandleCustomReImport != null && HandleCustomReImport(assetPath)) { continue; } AnimationImportJob job = CreateAnimationImportJob(assetPath); if (job != null) { if (HasExistingAnimatorController(assetPath)) { job.importAnimatorController = ImportAnimatorController.AnimatorController; } else if (HasExistingAnimatorOverrideController(assetPath)) { job.importAnimatorController = ImportAnimatorController.AnimatorOverrideController; job.useExistingAnimatorController = true; } jobs.Add(job); } } Import(jobs.ToArray()); }
private ImportedAnimationSheet ImportJob(AnimationImportJob job) { job.SetProgress(0); IAnimationImporterPlugin importer = _importerPlugins[GetExtension(job.fileName)]; ImportedAnimationSheet animationSheet = importer.Import(job, sharedData); job.SetProgress(0.3f); if (animationSheet != null) { animationSheet.assetDirectory = job.assetDirectory; animationSheet.name = job.name; animationSheet.ApplySpriteNamingScheme(sharedData.spriteNamingScheme); CreateSprites(animationSheet, job); job.SetProgress(0.6f); if (job.createUnityAnimations) { CreateAnimations(animationSheet, job); job.SetProgress(0.8f); if (job.importAnimatorController == ImportAnimatorController.AnimatorController) { CreateAnimatorController(animationSheet); } else if (job.importAnimatorController == ImportAnimatorController.AnimatorOverrideController) { CreateAnimatorOverrideController(animationSheet, job.useExistingAnimatorController); } } } return(animationSheet); }
// ================================================================================ // import methods // -------------------------------------------------------------------------------- public void ImportAssets(DefaultAsset[] assets, ImportAnimatorController importAnimatorController = ImportAnimatorController.None) { List <AnimationImportJob> jobs = new List <AnimationImportJob>(); foreach (var asset in assets) { string assetPath = AssetDatabase.GetAssetPath(asset); if (!IsValidAsset(assetPath)) { continue; } // DDobyns change to support adding to existing Animator Override Controller on manual import AnimationImportJob job = CreateAnimationImportJob(assetPath); if (job != null) { if (HasExistingAnimatorController(assetPath)) { job.importAnimatorController = ImportAnimatorController.AnimatorController; } else if (HasExistingAnimatorOverrideController(assetPath)) { job.importAnimatorController = ImportAnimatorController.AnimatorOverrideController; job.useExistingAnimatorController = true; } jobs.Add(job); } // AnimationImportJob job = CreateAnimationImportJob(assetPath); //job.importAnimatorController = importAnimatorController; // //job.useExistingAnimatorController = true; /// DDobyns test for adding to existing //jobs.Add(job); } Import(jobs.ToArray()); }
private void CreateAnimatorOverrideController(ImportedAnimationSheet animations, AnimationImportJob job) { AnimatorOverrideController overrideController; string directory = sharedData.animationControllersTargetLocation.GetAndEnsureTargetDirectory(job.assetPath); string pathForOverrideController; // check if override controller already exists; use this to not loose any references to this in other assets if (sharedData.namingScheme == NamingScheme.ItsName) { pathForOverrideController = $"{directory}/animatorController.overrideController"; } else { pathForOverrideController = $"{directory}/{animations.name}.overrideController"; } overrideController = AssetDatabase.LoadAssetAtPath <AnimatorOverrideController>(pathForOverrideController); RuntimeAnimatorController baseController = _baseController; if (job.useExistingAnimatorController && overrideController.runtimeAnimatorController != null) { baseController = overrideController.runtimeAnimatorController; } if (baseController != null) { if (overrideController == null) { overrideController = new AnimatorOverrideController(); AssetDatabase.CreateAsset(overrideController, pathForOverrideController); } overrideController.runtimeAnimatorController = baseController; // set override clips #if UNITY_5_6_OR_NEWER var clipPairs = new List <KeyValuePair <AnimationClip, AnimationClip> >(overrideController.overridesCount); overrideController.GetOverrides(clipPairs); foreach (var pair in clipPairs) { string animationName = pair.Key.name; AnimationClip clip = animations.GetClipOrSimilar(animationName); overrideController[animationName] = clip; } #else var clipPairs = overrideController.clips; for (int i = 0; i < clipPairs.Length; i++) { string animationName = clipPairs[i].originalClip.name; AnimationClip clip = animations.GetClipOrSimilar(animationName); clipPairs[i].overrideClip = clip; } overrideController.clips = clipPairs; #endif EditorUtility.SetDirty(overrideController); } else { Debug.LogWarning("No Animator Controller found as a base for the Override Controller"); } }
private void CreateSprites(ImportedAnimationSheet animationSheet, AnimationImportJob job) { if (animationSheet == null) { return; } var spriteInfos = new List <NamedSpriteInfo>(); animationSheet.CreateSpriteInfos( in sharedData.customPivotSettings, spriteInfos ); var siMap = new Dictionary <uint, NamedSpriteInfo>(); var nameMap = new Dictionary <string, string>(); var outputTexs = new Dictionary <Texture2D, SpriteMetaData[]>(); if (sharedData.doTrim) { var srcTex = animationSheet.srcTex; if (srcTex == null) { return; //? } var trimIndexList = new List <uint>(); for (int i = 0; i < spriteInfos.Count; ++i) { job.SetProgress(0.4f + i / (10.0f * spriteInfos.Count), "trimming sprite " + i.ToString()); var trimmed = spriteInfos[i].info.Trim(sharedData.trimColor, sharedData.trimMargin.x, sharedData.trimMargin.y); var trimmedCrc = trimmed.GetCrc32(); if (!siMap.ContainsKey(trimmedCrc)) { siMap[trimmedCrc] = new NamedSpriteInfo { name = spriteInfos[i].name, info = trimmed, }; trimIndexList.Add(trimmedCrc); } nameMap[spriteInfos[i].name] = siMap[trimmedCrc].name; } trimIndexList.Sort((lhsi, rhsi) => { var lhs = siMap[lhsi].info.frame; var rhs = siMap[rhsi].info.frame; if (lhs.width == rhs.width) { return(lhs.height - rhs.height); } return(rhs.width - lhs.width); // return (rhs.width + rhs.height) - (lhs.width + lhs.height); }); var boxs = new Luxko.Geometry.SkylinePacker.Box[trimIndexList.Count]; for (int i = 0; i < trimIndexList.Count; ++i) { var spriteInfo = siMap[trimIndexList[i]].info; boxs[i].w = spriteInfo.frame.width + sharedData.trimSpacing.x; boxs[i].h = spriteInfo.frame.height + sharedData.trimSpacing.y; } job.SetProgress(0.5f, "caculate packing info"); var packOutput = new Luxko.Geometry.SkylinePacker.Output[trimIndexList.Count]; var packBin = new Luxko.Geometry.SkylinePacker.Box { w = sharedData.trimTexSize.x, h = sharedData.trimTexSize.y }; var sky = new Luxko.Geometry.SkylinePacker.Sky(packBin, sharedData.PackSpreadFactor > 0 ? sharedData.PackSpreadFactor : (int)(packBin.h * 0.75f), boxs); for (int i = 0; i < boxs.Length; ++i) { sky.PackNext(out packOutput[i]); } var sheetBuf = new List <KeyValuePair <Texture2D, List <SpriteMetaData> > >(); for (int i = 0; i < packOutput.Length; ++i) { while (sheetBuf.Count <= packOutput[i].binIndex) { var newTex = new Texture2D(sharedData.trimTexSize.x, sharedData.trimTexSize.y, TextureFormat.RGBA32, false); // TODO: proper linear flag ClearTexture(newTex, Color.clear); sheetBuf.Add(new KeyValuePair <Texture2D, List <SpriteMetaData> >( newTex, new List <SpriteMetaData>() )); } var tSheet = sheetBuf[packOutput[i].binIndex]; var ti = new SpritePacker.SpriteInfo { tex = tSheet.Key, frame = new RectInt(packOutput[i].pos.x, packOutput[i].pos.y, 0, 0) }; var tis = siMap[trimIndexList[packOutput[i].boxIndex]]; job.SetProgress(0.55f + i / (20.0f * trimIndexList.Count), string.Format("packing {0} at {1} to {2}", tis.name, tis.info.frame, ti.frame.position)); tis.info.TryCopyTo(ref ti); tSheet.Value.Add(new SpriteMetaData { name = tis.name, rect = new Rect(ti.frame.x, ti.frame.y, ti.frame.width, ti.frame.height), alignment = (int)SpriteAlignment.Custom, pivot = ti.pivotN, }); } foreach (var kv in sheetBuf) { outputTexs.Add(kv.Key, kv.Value.ToArray()); } Texture2D.DestroyImmediate(srcTex, true); } else { var targetTex = animationSheet.srcTex; if (spriteInfos.Count > 0) { var smds = new SpriteMetaData[spriteInfos.Count]; for (int si = 0; si < spriteInfos.Count; ++si) { smds[si] = new SpriteMetaData { name = spriteInfos[si].name, rect = new Rect(spriteInfos[si].info.frame.x, spriteInfos[si].info.frame.y, spriteInfos[si].info.frame.width, spriteInfos[si].info.frame.height), alignment = (int)SpriteAlignment.Custom, pivot = spriteInfos[si].info.pivotN, }; } outputTexs.Add(targetTex, smds); spriteInfos.Clear(); } } int kvi = 0; var spriteDict = new Dictionary <string, Sprite>(); foreach (var kv in outputTexs) { job.SetProgress(0.6f + 0.1f * (kvi / (float)outputTexs.Count), "saving textures " + kvi); string imgPath; if (kvi <= 0) { imgPath = string.Format("{0}/{1}.png", job.directoryPathForSprites, job.name); } else { imgPath = string.Format("{0}/{1}_{2}.png", job.directoryPathForSprites, job.name, kvi); } kvi++; SaveAsPng(kv.Key, imgPath); AssetDatabase.Refresh(); AssetDatabase.ImportAsset(imgPath, ImportAssetOptions.ForceUpdate); var importer = AssetImporter.GetAtPath(imgPath) as TextureImporter; importer.textureType = TextureImporterType.Sprite; importer.spritePixelsPerUnit = sharedData.spritePixelsPerUnit; importer.mipmapEnabled = false; importer.filterMode = FilterMode.Point; importer.textureCompression = TextureImporterCompression.Uncompressed; // TODO: smart update: how to keep old references alive? importer.spritesheet = kv.Value; importer.spriteImportMode = SpriteImportMode.Multiple; importer.maxTextureSize = 2048; importer.textureCompression = TextureImporterCompression.CompressedHQ; EditorUtility.SetDirty(importer); importer.SaveAndReimport(); AssetDatabase.ImportAsset(imgPath, ImportAssetOptions.ForceUpdate); var assets = AssetDatabase.LoadAllAssetsAtPath(imgPath); foreach (var item in assets) { if (item is Sprite) { var sprite = (Sprite)item; spriteDict[sprite.name] = sprite; } } } if (nameMap.Count != 0) { var replaceMap = new Dictionary <string, Sprite>(); foreach (var kv in nameMap) { replaceMap[kv.Key] = spriteDict[kv.Value]; } spriteDict = replaceMap; } foreach (var kv in outputTexs) { Texture2D.DestroyImmediate(kv.Key); } outputTexs.Clear(); animationSheet.ApplyCreatedSprites(spriteDict); }