public static CubismFadeMotionData CreateInstance( CubismFadeMotionData fadeMotion, CubismMotion3Json motion3Json, string motionName, float motionLength, bool shouldImportAsOriginalWorkflow = false, bool isCallFormModelJson = false) { fadeMotion.MotionName = motionName; fadeMotion.MotionLength = motionLength; fadeMotion.FadeInTime = (motion3Json.Meta.FadeInTime < 0.0f) ? 1.0f : motion3Json.Meta.FadeInTime; fadeMotion.FadeOutTime = (motion3Json.Meta.FadeOutTime < 0.0f) ? 1.0f : motion3Json.Meta.FadeOutTime; for (var i = 0; i < motion3Json.Curves.Length; ++i) { var curve = motion3Json.Curves[i]; // In original workflow mode, skip add part opacity curve when call not from model3.json. if (curve.Target == "PartOpacity" && shouldImportAsOriginalWorkflow && !isCallFormModelJson) { continue; } fadeMotion.ParameterIds[i] = curve.Id; fadeMotion.ParameterFadeInTimes[i] = (curve.FadeInTime < 0.0f) ? -1.0f : curve.FadeInTime; fadeMotion.ParameterFadeOutTimes[i] = (curve.FadeOutTime < 0.0f) ? -1.0f : curve.FadeOutTime; fadeMotion.ParameterCurves[i] = new AnimationCurve(CubismMotion3Json.ConvertCurveSegmentsToKeyframes(curve.Segments)); } return(fadeMotion); }
/// <summary> /// Handles file drops. /// </summary> /// <param name="sender">Event source.</param> /// <param name="absolutePath">Absolute path of dropped file.</param> private void HandleFileDrop(CubismViewer sender, string absolutePath) { // Skip non-motion files. if (!absolutePath.EndsWith("motion3.json")) { return; } var model = sender.Model; // Make sure animation component is attached to model. var animator = model.GetComponent <Animation>(); if (animator == null) { animator = model.gameObject.AddComponent <Animation>(); } // Deserialize animation. var model3Json = CubismMotion3Json.LoadFrom(CubismViewerIo.LoadAsset <string>(absolutePath)); var clipName = CubismViewerIo.GetFileName(absolutePath); var clip = model3Json.ToAnimationClip(); clip.wrapMode = WrapMode.Loop; clip.legacy = true; // Play animation. animator.AddClip(clip, clipName); animator.Play(clipName); }
public void Awake(ModelType type, string name) { try { Type = type; Name = name; URL = Live2dPathHelper.GetModelConfigPath(type, name); TextAsset config = ResourcesHelper.GetAsset <TextAsset>(URL); ModelConfig = JsonMapper.ToObject <Live2dModelConfig>(config.text); ModelConfig.AssetPath = Live2dPathHelper.GetAssetPath(type, name); string modelPath = ModelConfig.GetModelPath(); var model3Json = CubismModel3Json.LoadAtPath(modelPath, BuiltinLoadAssetAtPath); Model = model3Json.ToModel(); EntityRef.GameObject = Model.gameObject; EntityRef.Transform = Model.gameObject.transform; EntityRef.GameObject.layer = LayerHelper.LayerNameToLayer("Unit"); GameObjectHelper.Traversal(EntityRef.Transform, (arg) => { arg.gameObject.layer = LayerHelper.LayerNameToLayer("Unit"); }, true); Animations = new Dictionary <string, AnimationClip>(); fadeController = EntityRef.GameObject.AddComponent <CubismFadeController>(); fadeController.CubismFadeMotionList = ScriptableObject.CreateInstance <CubismFadeMotionList>(); fadeController.CubismFadeMotionList.MotionInstanceIds = new int[ModelConfig.Motions.Length]; fadeController.CubismFadeMotionList.CubismFadeMotionObjects = new CubismFadeMotionData[ModelConfig.Motions.Length]; for (int i = 0; i < ModelConfig.Motions.Length; ++i) { string motion = ModelConfig.Motions[i]; string motionPath = ModelConfig.GetMotionPath(motion); var motion3Json = CubismMotion3Json.LoadFrom(ResourcesHelper.GetAsset <TextAsset>(motionPath)); var clip = ResourcesHelper.GetAsset <AnimationClip>(ModelConfig.GetAnimationClipPath(motion)); clip.name = motion; int instanceId = clip.GetInstanceID(); var events = clip.events; for (var j = 0; j < events.Length; ++j) { if (events[j].functionName != "InstanceId") { continue; } instanceId = events[j].intParameter; } fadeController.CubismFadeMotionList.MotionInstanceIds[i] = instanceId; fadeController.CubismFadeMotionList.CubismFadeMotionObjects[i] = CubismFadeMotionData.CreateInstance(motion3Json, clip.name, clip.length); Animations.Add(motion, clip); } motionController = EntityRef.GameObject.AddComponent <CubismMotionController>(); } catch (Exception e) { Log.Error(e); } }
private void ParseMotion3Json(string root, string path) { bool ShouldClearAnimationCurves = false; bool ShouldImportAsOriginalWorkflow = false; string clipName = path.Replace(".motion3.json", ""); string srcPath = $"Assets{DefaultModelDir}\\{root}\\motions\\{path}".Substring(Application.dataPath.Length); string desPath = $"Assets{DefaultExportDir}\\{root}\\motions\\{clipName}.anim".Substring(Application.dataPath.Length); var Motion3Json = CubismMotion3Json.LoadFrom(AssetDatabase.LoadAssetAtPath <TextAsset>(srcPath).text); var clip = (ShouldImportAsOriginalWorkflow) ? AssetDatabase.LoadAssetAtPath <AnimationClip>(srcPath.Replace(".motion3.json", ".anim")) : null; // Convert motion. var animationClip = (clip == null) ? Motion3Json.ToAnimationClip(ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves) : Motion3Json.ToAnimationClip(clip, ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves); AssetDatabase.CreateAsset(animationClip, desPath); var index = -1; var sourceAnimationEvents = AnimationUtility.GetAnimationEvents(animationClip); for (var i = 0; i < sourceAnimationEvents.Length; ++i) { if (sourceAnimationEvents[i].functionName != "InstanceId") { continue; } index = i; break; } if (index == -1) { index = sourceAnimationEvents.Length; Array.Resize(ref sourceAnimationEvents, sourceAnimationEvents.Length + 1); sourceAnimationEvents[sourceAnimationEvents.Length - 1] = new AnimationEvent(); } int instanceId = animationClip.GetInstanceID(); sourceAnimationEvents[index].time = 0; sourceAnimationEvents[index].functionName = "InstanceId"; sourceAnimationEvents[index].intParameter = instanceId; sourceAnimationEvents[index].messageOptions = SendMessageOptions.DontRequireReceiver; AnimationUtility.SetAnimationEvents(animationClip, sourceAnimationEvents); var assetImporter = AssetImporter.GetAtPath(srcPath); assetImporter.userData = JsonUtility.ToJson(this); assetImporter.SaveAndReimport(); }
/// <summary> /// プリセットモデルの設定を読み出す。 /// リソースからの相対パスを指定 /// </summary> /// <param name="pathResources"></param> public static AnimationClip Load(string pathResources) { //モデルの設定データをロードする。 TextAsset textasset = Resources.Load(pathResources) as TextAsset; //キュービズムJosnデシリアライズ CubismMotion3Json model3Json = JsonConvert.DeserializeObject <CubismMotion3Json>(textasset.text); //アニメーションクリップを生成し、返す return(model3Json.ToAnimationClip()); }
public static CubismFadeMotionData CreateInstance( CubismMotion3Json motion3Json, string motionName, float motionLength, bool shouldImportAsOriginalWorkflow = false, bool isCallFormModelJson = false) { var fadeMotion = CreateInstance <CubismFadeMotionData>(); var curveCount = motion3Json.Curves.Length; fadeMotion.ParameterIds = new string[curveCount];; fadeMotion.ParameterFadeInTimes = new float[curveCount]; fadeMotion.ParameterFadeOutTimes = new float[curveCount]; fadeMotion.ParameterCurves = new AnimationCurve[curveCount]; return(CreateInstance(fadeMotion, motion3Json, motionName, motionLength, shouldImportAsOriginalWorkflow, isCallFormModelJson)); }
/// <summary> /// テーブルに表情データを追加する。 /// </summary> /// <param name="ModelPath"></param> /// <param name="expression"></param> public void Add(string ModelPath, LiplisMotion expression) { //モーションパス取得 var path = ModelPath + ModelPathDefine.EXPRESSIONS + "/" + expression.FileName; //対象エモーションにファイルを追加する。 TableExpression[(int)MotionMap.GetMotion(expression.Emotion, expression.Emotion)].Add(expression.FileName); //ModelJsonオブジェクト取得 var model3Json = CubismMotion3Json.LoadFrom(AssetLoader.LoadAsset <string>(path)); //アニメーションクリップテーブルに追加 TabelAnimationClip.Add(expression.FileName, model3Json.ToAnimationClip()); }
/// <summary> /// モーションのロード /// TODO Exceptionの実装 /// </summary> /// <param name="model"></param> /// <param name="modelPath"></param> private void LoadMotion(CubismModel model, string modelPath) { //モーションテーブルの初期化 this.TableMotion = new Dictionary <int, List <string> >(); //モーションリストを回して登録 foreach (LiplisMotion motion in modelData.MotionList) { //モーションパス取得 var path = modelPath + ModelPathDefine.MOTIONS + "/" + motion.FileName; //ModelJsonオブジェクト取得 CubismMotion3Json model3Json = CubismMotion3Json.LoadFrom(AssetLoader.LoadAsset <string>(path)); //モーションロード AnimationClip clip = model3Json.ToAnimationClip(); //レガシーに設定 clip.legacy = true; //ワラップモード設定 //アイドルモーションはループ、それ以外はワンスを設定 if (motion.FileName.StartsWith(MOTION_IDLE_HEAD)) { //アイドルモーションに登録 clip.wrapMode = WrapMode.Loop; } else { //通常モーションに登録 clip.wrapMode = WrapMode.Once; } //アニメーターに登録 this.Animator.AddClip(clip, motion.FileName); //モーションテーブル キー追加 if (!TableMotion.ContainsKey(motion.Emotion)) { TableMotion.Add(motion.Emotion, new List <string>()); } //モーションテーブル 値追加 TableMotion[motion.Emotion].Add(motion.FileName); } }
public static CubismPose LoadCubismPoseFromAssetPath(string assetpath) { if ((assetpath == string.Empty) || (assetpath == null)) { return(null); } CubismPose cubismPose = null; string loadedJson = null; #if UNITY_EDITOR loadedJson = File.ReadAllText(assetpath); #else loadedJson = Resources.Load(assetpath, typeof(TextAsset)) as TextAsset; #endif if (loadedJson == null) { Debug.Log("CubismPose: input path is no good."); return(null); } CubismMotion3Json json = CubismMotion3Json.LoadFrom(loadedJson); if (json == null) { Debug.Log("CubismPose: i feel input json is not json."); return(null); } cubismPose = new CubismPose(); foreach (var curbe in json.Curves) { if ((curbe.Target == "Parameter") && (curbe.Segments.Length > 2)) { cubismPose.setting.Add(curbe.Id, curbe.Segments[1]); } } return(cubismPose); }
/// <summary> /// Called when animation is selected in dropdown. /// </summary> private void DropdownSelected() { var model = viewer.Model; // Make sure animation component is attached to model. var animator = model.GetComponent <Animation>(); if (animator == null) { animator = model.gameObject.AddComponent <Animation>(); } // Check if "no animation" entry is selected. if (animDropdown.value == 0) { animator.Stop(); animator.clip = null; return; } string absolutePath = files[animDropdown.value - 1]; // Deserialize animation. var model3Json = CubismMotion3Json.LoadFrom(CubismViewerIo.LoadAsset <string>(absolutePath)); var clipName = CubismViewerIo.GetFileName(absolutePath); var clip = model3Json.ToAnimationClip(); clip.wrapMode = WrapMode.Loop; clip.legacy = true; // Set clip info in animator (needed for recording with CubismRecorder). clip.name = clipName; animator.clip = clip; // Play animation. animator.AddClip(clip, clipName); animator.Play(clipName); }
public CubismModel GetModelFromName(string name, GameObject parent) { try { string ModelPath = Application.streamingAssetsPath + "../../../Data/live2d/" + name + ".model3.json"; //Debug.Log(ModelPath); if (System.IO.File.Exists(ModelPath)) { var ModelFullName = ModelPath; var model3Json = CubismModel3Json.LoadAtPath(ModelFullName, BuiltinLoadAssetAtPath); var motions = model3Json.FileReferences.Motions.Motions; var model = model3Json.ToModel(true); var Scale = 40f; model.gameObject.transform.localScale += new Vector3(Scale, Scale); CubismRenderController cubisumRenderController = model.GetComponent <CubismRenderController>(); cubisumRenderController.SortingMode = CubismSortingMode.BackToFrontOrder; //处理动画(Motion) Animation animation = model.gameObject.AddComponent <Animation>(); var animationClips = new ArrayList(); var modelD = Path.GetDirectoryName(ModelPath); if (motions != null) { for (var i = 0; i < motions.Length; ++i) { for (var j = 0; j < motions[i].Length; ++j) { string MotionPath = modelD + "/" + motions[i][j].File; CubismMotion3Json cubismMotion3Json = CubismMotion3Json.LoadFrom(File.ReadAllText(MotionPath)); AnimationClip animationClip = cubismMotion3Json.ToAnimationClip(new AnimationClip { legacy = true }, false, false, false, null); var motionName = motions[i][j].File.Substring(0, motions[i][j].File.Length - 13); animationClip.name = motionName; animation.AddClip(animationClip, animationClip.name); animationClips.Add(animationClip.name); //animation.Blend(animationClip.name); } } } //处理姿势 var pose3Json = model3Json.Pose3Json; if (pose3Json != null) { var groups = pose3Json.Groups; var parts = model.Parts; for (var groupIndex = 0; groupIndex < groups.Length; ++groupIndex) { var group = groups[groupIndex]; if (group == null) { continue; } for (var partIndex = 0; partIndex < group.Length; ++partIndex) { var part = parts.FindById(group[partIndex].Id); if (part == null) { continue; } var posePart = part.gameObject.GetComponent <CubismPosePart>(); if (posePart == null) { posePart = part.gameObject.AddComponent <CubismPosePart>(); } posePart.GroupIndex = groupIndex; posePart.PartIndex = partIndex; posePart.Link = group[partIndex].Link; } } model.GetComponent <CubismPoseController>().Refresh(); } //+1 model.name = model.name + "(" + Globle.ModelNum.ToString() + ")"; Globle.ModelNum++; Globle.ModelList.Add(model.gameObject); var modelController = model.gameObject.AddComponent <Live2DModelController>(); modelController.DisplayName = model.name; modelController.ModelPath = modelD; modelController.Animation = animation; modelController.animationClips = animationClips; model.transform.SetParent(parent.transform); model.gameObject.transform.localPosition = new Vector3(0, 0, 0); return(model); } else { throw new Exception(Globle.LangController.GetLang("LOG.FileUnisset")); } } catch (Exception err) { Globle.AddDataLog("Main", Globle.LangController.GetLang("LOG.ModelAddationException", err.Message)); } return(null); }
/// <summary> /// Create pose motions. /// </summary> /// <param name="sender">Event source.</param> /// <param name="model">Imported model.</param> private static void OnModelImport(CubismModel3JsonImporter sender, CubismModel model) { var shouldImportAsOriginalWorkflow = CubismUnityEditorMenu.ShouldImportAsOriginalWorkflow; var pose3Json = sender.Model3Json.Pose3Json; // Fail silently... if (!shouldImportAsOriginalWorkflow || pose3Json == null) { return; } var assetsDirectoryPath = Application.dataPath.Replace("Assets", ""); var assetPath = sender.AssetPath.Replace(assetsDirectoryPath, ""); var fileReferences = sender.Model3Json.FileReferences; // Create pose animation clip var motions = new List <CubismModel3Json.SerializableMotion>(); if (fileReferences.Motions.GroupNames != null) { for (var i = 0; i < fileReferences.Motions.GroupNames.Length; i++) { motions.AddRange(fileReferences.Motions.Motions[i]); } } for (var i = 0; i < motions.Count; ++i) { var motionPath = Path.GetDirectoryName(assetPath) + "/" + motions[i].File; var jsonString = string.IsNullOrEmpty(motionPath) ? null : File.ReadAllText(motionPath); if (jsonString == null) { continue; } var directoryPath = Path.GetDirectoryName(assetPath) + "/"; var motion3Json = CubismMotion3Json.LoadFrom(jsonString); var animationClipPath = directoryPath + motions[i].File.Replace(".motion3.json", ".anim"); var newAnimationClip = motion3Json.ToAnimationClip(shouldImportAsOriginalWorkflow, false, true, pose3Json); var oldAnimationClip = AssetDatabase.LoadAssetAtPath <AnimationClip>(animationClipPath); // Create animation clip. if (oldAnimationClip == null) { AssetDatabase.CreateAsset(newAnimationClip, animationClipPath); oldAnimationClip = newAnimationClip; } // Update animation clip. else { EditorUtility.CopySerialized(newAnimationClip, oldAnimationClip); EditorUtility.SetDirty(oldAnimationClip); newAnimationClip = oldAnimationClip; } // Add animation event { var instanceId = newAnimationClip.GetInstanceID(); var sourceAnimationEvents = AnimationUtility.GetAnimationEvents(newAnimationClip); var index = -1; for (var j = 0; j < sourceAnimationEvents.Length; ++j) { if (sourceAnimationEvents[j].functionName != "InstanceId") { continue; } index = j; break; } if (index == -1) { index = sourceAnimationEvents.Length; Array.Resize(ref sourceAnimationEvents, sourceAnimationEvents.Length + 1); sourceAnimationEvents[sourceAnimationEvents.Length - 1] = new AnimationEvent(); } sourceAnimationEvents[index].time = 0; sourceAnimationEvents[index].functionName = "InstanceId"; sourceAnimationEvents[index].intParameter = instanceId; sourceAnimationEvents[index].messageOptions = SendMessageOptions.DontRequireReceiver; AnimationUtility.SetAnimationEvents(newAnimationClip, sourceAnimationEvents); } // update fade motion data. var fadeMotionPath = directoryPath + motions[i].File.Replace(".motion3.json", ".fade.asset"); var fadeMotion = AssetDatabase.LoadAssetAtPath <CubismFadeMotionData>(fadeMotionPath); if (fadeMotion == null) { fadeMotion = CubismFadeMotionData.CreateInstance(motion3Json, fadeMotionPath.Replace(directoryPath, ""), newAnimationClip.length, shouldImportAsOriginalWorkflow, true); AssetDatabase.CreateAsset(fadeMotion, fadeMotionPath); EditorUtility.SetDirty(fadeMotion); // Fade用モーションの参照をリストに追加 var directoryName = Path.GetDirectoryName(fadeMotionPath).ToString(); var modelDir = Path.GetDirectoryName(directoryName).ToString(); var modelName = Path.GetFileName(modelDir).ToString(); var fadeMotionListPath = Path.GetDirectoryName(directoryName).ToString() + "/" + modelName + ".fadeMotionList.asset"; var fadeMotions = AssetDatabase.LoadAssetAtPath <CubismFadeMotionList>(fadeMotionListPath); // 参照リスト作成 if (fadeMotions == null) { fadeMotions = ScriptableObject.CreateInstance <CubismFadeMotionList>(); fadeMotions.MotionInstanceIds = new int[0]; fadeMotions.CubismFadeMotionObjects = new CubismFadeMotionData[0]; AssetDatabase.CreateAsset(fadeMotions, fadeMotionListPath); } var instanceId = oldAnimationClip.GetInstanceID(); var motionIndex = Array.IndexOf(fadeMotions.MotionInstanceIds, instanceId); if (motionIndex != -1) { fadeMotions.CubismFadeMotionObjects[motionIndex] = fadeMotion; } else { motionIndex = fadeMotions.MotionInstanceIds.Length; Array.Resize(ref fadeMotions.MotionInstanceIds, motionIndex + 1); fadeMotions.MotionInstanceIds[motionIndex] = instanceId; Array.Resize(ref fadeMotions.CubismFadeMotionObjects, motionIndex + 1); fadeMotions.CubismFadeMotionObjects[motionIndex] = fadeMotion; } EditorUtility.SetDirty(fadeMotions); } for (var curveIndex = 0; curveIndex < motion3Json.Curves.Length; ++curveIndex) { var curve = motion3Json.Curves[curveIndex]; if (curve.Target == "PartOpacity") { if (pose3Json.FadeInTime == 0.0f) { fadeMotion.ParameterIds[curveIndex] = curve.Id; fadeMotion.ParameterFadeInTimes[curveIndex] = pose3Json.FadeInTime; fadeMotion.ParameterFadeOutTimes[curveIndex] = (curve.FadeOutTime < 0.0f) ? -1.0f : curve.FadeOutTime; fadeMotion.ParameterCurves[curveIndex] = new AnimationCurve(CubismMotion3Json.ConvertCurveSegmentsToKeyframes(curve.Segments)); } else { fadeMotion.ParameterIds[curveIndex] = curve.Id; fadeMotion.ParameterFadeInTimes[curveIndex] = pose3Json.FadeInTime; fadeMotion.ParameterFadeOutTimes[curveIndex] = (curve.FadeOutTime < 0.0f) ? -1.0f : curve.FadeOutTime; fadeMotion.ParameterCurves[curveIndex] = CubismMotion3Json.ConvertSteppedCurveToLinerCurver(curve, pose3Json.FadeInTime); } } } EditorUtility.SetDirty(fadeMotion); } InitializePosePart(model.Parts, pose3Json.Groups); }