Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Instantiates a <see cref="CubismMoc">model source</see> and a <see cref="CubismModel">model</see>.
        /// </summary>
        /// <param name="pickMaterial">The material mapper to use.</param>
        /// <param name="pickTexture">The texture mapper to use.</param>
        /// <param name="shouldImportAsOriginalWorkflow">Should import as original workflow.</param>
        /// <returns>The instantiated <see cref="CubismModel">model</see> on success; <see langword="null"/> otherwise.</returns>
        public CubismModel ToModel(MaterialPicker pickMaterial, TexturePicker pickTexture, bool shouldImportAsOriginalWorkflow = false)
        {
            // Initialize model source and instantiate it.
            var mocAsBytes = Moc3;


            if (mocAsBytes == null)
            {
                return(null);
            }


            var moc = CubismMoc.CreateFrom(mocAsBytes);


            var model = CubismModel.InstantiateFrom(moc);


            model.name = Path.GetFileNameWithoutExtension(FileReferences.Moc);


#if UNITY_EDITOR
            // Add parameters and parts inspectors.
            model.gameObject.AddComponent <CubismParametersInspector>();
            model.gameObject.AddComponent <CubismPartsInspector>();
#endif


            // Create renderers.
            var rendererController = model.gameObject.AddComponent <CubismRenderController>();
            var renderers          = rendererController.Renderers;

            var drawables = model.Drawables;


            // Initialize materials.
            for (var i = 0; i < renderers.Length; ++i)
            {
                renderers[i].Material = pickMaterial(this, drawables[i]);
            }


            // Initialize textures.
            for (var i = 0; i < renderers.Length; ++i)
            {
                renderers[i].MainTexture = pickTexture(this, drawables[i]);
            }


            // Initialize groups.
            var parameters = model.Parameters;


            for (var i = 0; i < parameters.Length; ++i)
            {
                if (IsParameterInGroup(parameters[i], "EyeBlink"))
                {
                    if (model.gameObject.GetComponent <CubismEyeBlinkController>() == null)
                    {
                        model.gameObject.AddComponent <CubismEyeBlinkController>();
                    }


                    parameters[i].gameObject.AddComponent <CubismEyeBlinkParameter>();
                }


                // Set up mouth parameters.
                if (IsParameterInGroup(parameters[i], "LipSync"))
                {
                    if (model.gameObject.GetComponent <CubismMouthController>() == null)
                    {
                        model.gameObject.AddComponent <CubismMouthController>();
                    }


                    parameters[i].gameObject.AddComponent <CubismMouthParameter>();
                }
            }


            // Add mask controller if required.
            for (var i = 0; i < drawables.Length; ++i)
            {
                if (!drawables[i].IsMasked)
                {
                    continue;
                }


                // Add controller exactly once...
                model.gameObject.AddComponent <CubismMaskController>();


                break;
            }

            // Add original workflow component if is original workflow.
            if (shouldImportAsOriginalWorkflow)
            {
                // Add cubism update manager.
                var updateaManager = model.gameObject.GetComponent <CubismUpdateController>();

                if (updateaManager == null)
                {
                    model.gameObject.AddComponent <CubismUpdateController>();
                }

                // Add parameter store.
                var parameterStore = model.gameObject.GetComponent <CubismParameterStore>();

                if (parameterStore == null)
                {
                    parameterStore = model.gameObject.AddComponent <CubismParameterStore>();
                }

                // Add pose controller.
                var poseController = model.gameObject.GetComponent <CubismPoseController>();

                if (poseController == null)
                {
                    poseController = model.gameObject.AddComponent <CubismPoseController>();
                }

                poseController.PoseData.Initialize(Pose3Json);

#if UNITY_EDITOR
                // Create pose animation clip
                var motions = new List <SerializableMotion>();

                if (FileReferences.Motions.Idle != null)
                {
                    motions.AddRange(FileReferences.Motions.Idle);
                }

                if (FileReferences.Motions.TapBody != null)
                {
                    motions.AddRange(FileReferences.Motions.TapBody);
                }

                for (var i = 0; i < motions.Count; ++i)
                {
                    var jsonString = string.IsNullOrEmpty(motions[i].File)
                                        ? null
                                        : LoadReferencedAsset <string>(motions[i].File);

                    if (jsonString == null)
                    {
                        continue;
                    }

                    var assetsDirectoryPath = Application.dataPath.Replace("Assets", "");
                    var assetPath           = AssetPath.Replace(assetsDirectoryPath, "");
                    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);
                    }

                    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
                            {
                                var poseFadeInTIme = (Pose3Json.FadeInTime < 0.0f) ? 0.5f : Pose3Json.FadeInTime;
                                fadeMotion.ParameterIds[curveIndex]          = curve.Id;
                                fadeMotion.ParameterFadeInTimes[curveIndex]  = poseFadeInTIme;
                                fadeMotion.ParameterFadeOutTimes[curveIndex] = (curve.FadeOutTime < 0.0f) ? -1.0f : curve.FadeOutTime;

                                var segments      = curve.Segments;
                                var segmentsCount = 2;
                                for (var index = 2; index < curve.Segments.Length; index += 3)
                                {
                                    // if current segment type is stepped and
                                    // next segment type is stepped or next segment is last segment
                                    // then convert segment type to liner.
                                    var currentSegmentTypeIsStepped = (curve.Segments[index] == 2);
                                    var currentSegmentIsLast        = (index == (curve.Segments.Length - 3));
                                    var nextSegmentTypeIsStepped    = (currentSegmentIsLast) ? false : (curve.Segments[index + 3] == 2);
                                    var nextSegmentIsLast           = (currentSegmentIsLast) ? false : ((index + 3) == (curve.Segments.Length - 3));
                                    if (currentSegmentTypeIsStepped && (nextSegmentTypeIsStepped || nextSegmentIsLast))
                                    {
                                        Array.Resize(ref segments, segments.Length + 3);
                                        segments[segmentsCount + 0] = 0;
                                        segments[segmentsCount + 1] = curve.Segments[index + 1];
                                        segments[segmentsCount + 2] = curve.Segments[index - 1];
                                        segments[segmentsCount + 3] = 0;
                                        segments[segmentsCount + 4] = curve.Segments[index + 1] + poseFadeInTIme;
                                        segments[segmentsCount + 5] = curve.Segments[index + 2];
                                        segmentsCount += 6;
                                    }
                                    else if (curve.Segments[index] == 1)
                                    {
                                        segments[segmentsCount + 0] = curve.Segments[index + 0];
                                        segments[segmentsCount + 1] = curve.Segments[index + 1];
                                        segments[segmentsCount + 2] = curve.Segments[index + 2];
                                        segments[segmentsCount + 3] = curve.Segments[index + 3];
                                        segments[segmentsCount + 4] = curve.Segments[index + 4];
                                        segments[segmentsCount + 5] = curve.Segments[index + 5];
                                        segments[segmentsCount + 6] = curve.Segments[index + 6];
                                        index         += 4;
                                        segmentsCount += 7;
                                    }
                                    else
                                    {
                                        segments[segmentsCount + 0] = curve.Segments[index + 0];
                                        segments[segmentsCount + 1] = curve.Segments[index + 1];
                                        segments[segmentsCount + 2] = curve.Segments[index + 2];
                                        segmentsCount += 3;
                                    }
                                }
                                fadeMotion.ParameterCurves[curveIndex] = new AnimationCurve(CubismMotion3Json.ConvertCurveSegmentsToKeyframes(segments));
                            }
                        }
                    }

                    EditorUtility.SetDirty(fadeMotion);
                }
#endif

                // Add expression controller.
                var expressionController = model.gameObject.GetComponent <CubismExpressionController>();

                if (expressionController == null)
                {
                    expressionController = model.gameObject.AddComponent <CubismExpressionController>();
                }


                // Add fade controller.
                var motionFadeController = model.gameObject.GetComponent <CubismFadeController>();

                if (motionFadeController == null)
                {
                    motionFadeController = model.gameObject.AddComponent <CubismFadeController>();
                }
            }


            // Initialize physics if JSON exists.
            var physics3JsonAsString = Physics3Json;


            if (!string.IsNullOrEmpty(physics3JsonAsString))
            {
                var physics3Json      = CubismPhysics3Json.LoadFrom(physics3JsonAsString);
                var physicsController = model.gameObject.GetComponent <CubismPhysicsController>();

                if (physicsController == null)
                {
                    physicsController = model.gameObject.AddComponent <CubismPhysicsController>();
                }

                physicsController.Initialize(physics3Json.ToRig());
            }


            var userData3JsonAsString = UserData3Json;


            if (!string.IsNullOrEmpty(userData3JsonAsString))
            {
                var userData3Json = CubismUserData3Json.LoadFrom(userData3JsonAsString);


                var drawableBodies = userData3Json.ToBodyArray(CubismUserDataTargetType.ArtMesh);

                for (var i = 0; i < drawables.Length; ++i)
                {
                    var index = GetBodyIndexById(drawableBodies, drawables[i].Id);

                    if (index >= 0)
                    {
                        var tag = drawables[i].gameObject.GetComponent <CubismUserDataTag>();


                        if (tag == null)
                        {
                            tag = drawables[i].gameObject.AddComponent <CubismUserDataTag>();
                        }


                        tag.Initialize(drawableBodies[index]);
                    }
                }
            }

            if (model.gameObject.GetComponent <Animator>() == null)
            {
                model.gameObject.AddComponent <Animator>();
            }

            // Make sure model is 'fresh'
            model.ForceUpdateNow();


            return(model);
        }
Beispiel #3
0
        /// <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);
        }