Esempio n. 1
0
        protected void finishRecording(ProgressBar progress)
        {
            string targetFolderPath = targetFolder.Path;

            if (targetFolderPath == null)
            {
                if (gameObject.scene.IsValid() && !string.IsNullOrEmpty(gameObject.scene.path))
                {
                    string sceneFolder = Path.GetDirectoryName(gameObject.scene.path);
                    targetFolderPath = Path.Combine(sceneFolder, "Recordings");
                }
                else
                {
                    targetFolderPath = Path.Combine("Assets", "Recordings");
                }
            }

            int    folderSuffix = 1;
            string finalSubFolder;

            do
            {
                finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0'));
                folderSuffix++;
            } while (Directory.Exists(finalSubFolder));

            string dataDirectory = Path.Combine(finalSubFolder, "_Data");

            Directory.CreateDirectory(dataDirectory);
            Directory.CreateDirectory(finalSubFolder);
            AssetDatabase.Refresh();

            progress.Begin(6, "Saving Recording", "", () => {
                if (!_isRecording)
                {
                    return;
                }
                _isRecording = false;

                //Turn on auto-pushing for all auto-proxy components
                foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>())
                {
                    autoProxy.autoPushingEnabled = true;
                }

                progress.Begin(3, "", "Reverting Scene State", () => {
                    //For all of our transform data, revert to the first piece recorded
                    progress.Begin(_transformData.Count, "", "", () => {
                        foreach (var pair in _transformData)
                        {
                            progress.Step();
                            var transform = pair.Key;
                            var data      = pair.Value;

                            if (transform == null || data.Count == 0)
                            {
                                continue;
                            }

                            data[0].ApplyTo(transform);
                        }
                    });

                    //For all recorded curves, revert to start of curve
                    progress.Begin(_curves.Count, "", "", () => {
                        AnimationClip tempClip = new AnimationClip();
                        foreach (var data in _curves)
                        {
                            progress.Step();
                            AnimationUtility.SetEditorCurve(tempClip, data.binding, data.curve);
                        }
                        tempClip.SampleAnimation(gameObject, 0);
                    });

                    //For all non-transform components, revert to original serialized values
                    progress.Begin(_initialComponentData.Count, "", "", () => {
                        foreach (var pair in _initialComponentData)
                        {
                            progress.Step();
                            var component = pair.Key;
                            var sobj      = pair.Value;

                            if (component == null || component is Transform)
                            {
                                continue;
                            }


                            //We don't want to revert method recordings!
                            if (component is MethodRecording ||
                                component is RecordedAudio)
                            {
                                continue;
                            }

                            var flags = sobj.FindProperty("m_ObjectHideFlags");
                            if (flags == null)
                            {
                                Debug.LogError("Could not find hide flags for " + component);
                                continue;
                            }

                            //We have to dirty the serialized object somehow
                            //apparently there is no api to do this
                            //all objects have hide flags so we just touch them and revert them
                            int originalFlags = flags.intValue;
                            flags.intValue    = ~originalFlags;
                            flags.intValue    = originalFlags;

                            try {
                                //Applies previous state of entire component
                                sobj.ApplyModifiedProperties();
                            } catch (Exception e) {
                                Debug.LogError("Exception when trying to apply properties to " + component);
                                Debug.LogException(e);
                            }
                        }
                    });
                });

                progress.Begin(1, "", "Patching Materials: ", () => {
                    GetComponentsInChildren(true, _recorders);
                    foreach (var recorder in _recorders)
                    {
                        DestroyImmediate(recorder);
                    }

                    //Patch up renderer references to materials
                    var allMaterials = Resources.FindObjectsOfTypeAll <Material>().
                                       Query().
                                       Where(AssetDatabase.IsMainAsset).
                                       ToList();

                    var renderers = GetComponentsInChildren <Renderer>(includeInactive: true);

                    progress.Begin(renderers.Length, "", "", () => {
                        foreach (var renderer in renderers)
                        {
                            progress.Step(renderer.name);

                            var materials = renderer.sharedMaterials;
                            for (int i = 0; i < materials.Length; i++)
                            {
                                var material = materials[i];
                                if (material == null)
                                {
                                    continue;
                                }

                                if (!AssetDatabase.IsMainAsset(material))
                                {
                                    var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) &&
                                                                                               material.shader == m.shader);

                                    if (matchingMaterial != null)
                                    {
                                        materials[i] = matchingMaterial;
                                    }
                                }
                            }
                            renderer.sharedMaterials = materials;
                        }
                    });
                });

                progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => {
                    foreach (var pair in _behaviourActivity)
                    {
                        var targetBehaviour = pair.Key;
                        var activityData    = pair.Value;

                        if (targetBehaviour == null)
                        {
                            continue;
                        }

                        progress.Step(targetBehaviour.name);

                        string path         = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform);
                        Type type           = targetBehaviour.GetType();
                        string propertyName = "m_Enabled";

                        AnimationCurve curve = new AnimationCurve();
                        foreach (var dataPoint in activityData)
                        {
                            int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0);
                            AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                            AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                        }

                        if (curve.IsConstant())
                        {
                            continue;
                        }

                        var binding = EditorCurveBinding.FloatCurve(path, type, propertyName);

                        if (_curves.Query().Any(c => c.binding == binding))
                        {
                            Debug.LogError("Binding already existed?");
                            Debug.LogError(binding.path + " : " + binding.propertyName);
                            continue;
                        }

                        _curves.Add(new CurveData()
                        {
                            binding = binding,
                            curve   = curve
                        });
                    }
                });

                progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => {
                    foreach (var pair in _transformData)
                    {
                        var targetTransform = pair.Key;
                        var targetData      = pair.Value;

                        progress.Step(targetTransform.name);

                        string path = AnimationUtility.CalculateTransformPath(targetTransform, transform);

                        bool isActivityConstant = true;
                        bool isPositionConstant = true;
                        bool isRotationConstant = true;
                        bool isScaleConstant    = true;

                        {
                            bool startEnabled        = targetData[0].enabled;
                            Vector3 startPosition    = targetData[0].localPosition;
                            Quaternion startRotation = targetData[0].localRotation;
                            Vector3 startScale       = targetData[0].localScale;
                            for (int i = 1; i < targetData.Count; i++)
                            {
                                isActivityConstant &= targetData[i].enabled == startEnabled;
                                isPositionConstant &= targetData[i].localPosition == startPosition;
                                isRotationConstant &= targetData[i].localRotation == startRotation;
                                isScaleConstant    &= targetData[i].localScale == startScale;
                            }
                        }

                        for (int i = 0; i < TransformData.CURVE_COUNT; i++)
                        {
                            string propertyName = TransformData.GetName(i);
                            Type type           = typeof(Transform);

                            AnimationCurve curve = new AnimationCurve();
                            var dataType         = TransformData.GetDataType(i);

                            switch (dataType)
                            {
                            case TransformDataType.Position:
                                if (isPositionConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Rotation:
                                if (isRotationConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Scale:
                                if (isScaleConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Activity:
                                if (isActivityConstant)
                                {
                                    continue;
                                }
                                type = typeof(GameObject);
                                break;
                            }

                            for (int j = 0; j < targetData.Count; j++)
                            {
                                int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i));
                                if (dataType == TransformDataType.Activity)
                                {
                                    AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                                    AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                                }
                            }

                            var binding = EditorCurveBinding.FloatCurve(path, type, propertyName);

                            if (_curves.Query().Any(c => c.binding == binding))
                            {
                                Debug.LogError("Duplicate object was created??");
                                Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName);
                            }
                            else
                            {
                                _curves.Add(new CurveData()
                                {
                                    binding = binding,
                                    curve   = curve
                                });
                            }
                        }
                    }
                });

                progress.Begin(_curves.Count, "", "Compressing Data: ", () => {
                    _curves.Sort((a, b) => a.binding.propertyName.CompareTo(b.binding.propertyName));
                    foreach (var data in _curves)
                    {
                        using (new ProfilerSample("A")) {
                            EditorCurveBinding binding = data.binding;
                            AnimationCurve curve       = data.curve;

                            progress.Step(binding.propertyName);

                            GameObject animationGameObject;
                            {
                                var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding);
                                if (animatedObj is GameObject)
                                {
                                    animationGameObject = animatedObj as GameObject;
                                }
                                else
                                {
                                    animationGameObject = (animatedObj as Component).gameObject;
                                }
                            }

                            bool isMatBinding = binding.propertyName.StartsWith("material.") &&
                                                binding.type.IsSubclassOf(typeof(Renderer));

                            //But if the curve is constant, just get rid of it!
                            //Except for material curves, which we always need to keep
                            if (curve.IsConstant() && !isMatBinding)
                            {
                                //Check to make sure there are no other matching curves that are
                                //non constant.  If X and Y are constant but Z is not, we need to
                                //keep them all :(
                                if (_curves.Query().Where(p => p.binding.path == binding.path &&
                                                          p.binding.type == binding.type &&
                                                          p.binding.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)).
                                    All(k => k.curve.IsConstant()))
                                {
                                    continue;
                                }
                            }

                            //First do a lossless compression
                            using (new ProfilerSample("B")) {
                                curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon, checkSteps: 3);
                            }

                            Transform targetTransform = null;
                            var targetObj             = AnimationUtility.GetAnimatedObject(gameObject, binding);
                            if (targetObj is GameObject)
                            {
                                targetTransform = (targetObj as GameObject).transform;
                            }
                            else if (targetObj is Component)
                            {
                                targetTransform = (targetObj as Component).transform;
                            }
                            else
                            {
                                Debug.LogError("Target obj was of type " + targetObj.GetType().Name);
                            }
                        }
                    }
                });
            });

            progress.Begin(4, "Finalizing Assets", "", () => {
                var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>();

                GameObject myGameObject = gameObject;

                DestroyImmediate(this);

                //Create all the files for the method recording
                progress.Step("Creating Method Recording Files...");
                var methodRecordings = myGameObject.GetComponentsInChildren <MethodRecording>();
                for (int i = 0; i < methodRecordings.Length; i++)
                {
                    var methodRecording = methodRecordings[i];
                    string fullPath     = Path.Combine(finalSubFolder, "MethodRecording_" + i + ".asset");
                    methodRecording.ExitRecordingMode(fullPath);
                }

                postProcessComponent.dataFolder = new AssetFolder(dataDirectory);

                //Create the asset that holds all of the curve data
                progress.Begin(_curves.Count, "", "", () => {
                    string curveFile = Path.Combine(dataDirectory, "Curves.data");
                    using (var writer = File.CreateText(curveFile)) {
                        foreach (var data in _curves)
                        {
                            progress.Step(data.binding.propertyName);

                            var bindingData = new EditorCurveBindingData()
                            {
                                path         = data.binding.path,
                                propertyName = data.binding.propertyName,
                                typeName     = data.binding.type.Name,
                                curve        = data.curve
                            };

                            writer.WriteLine(JsonUtility.ToJson(bindingData));
                        }
                    }
                });

                //Create the asset that holds all of the leap data
                if (_leapData.Count > 0)
                {
                    progress.Begin(_leapData.Count, "", "", () => {
                        string leapFile = Path.Combine(dataDirectory, "Frames.data");

                        using (var writer = File.CreateText(leapFile)) {
                            for (int i = 0; i < _leapData.Count; i++)
                            {
                                progress.Step("Frame " + i);
                                writer.WriteLine(JsonUtility.ToJson(_leapData[i]));
                            }
                        }
                    });
                }

                progress.Step("Creating Final Prefab...");
                //Init the post process component
                postProcessComponent.recordingName = recordingName;
                postProcessComponent.assetFolder   = new AssetFolder(finalSubFolder);

                string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab");
                PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject);

                AssetDatabase.Refresh();

                EditorApplication.isPlaying = false;
            });
        }
Esempio n. 2
0
        protected void finishRecording(ProgressBar progress)
        {
            progress.Begin(5, "Saving Recording", "", () => {
                if (!_isRecording)
                {
                    return;
                }
                _isRecording = false;

                //Turn on auto-pushing for all auto-proxy components
                foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>())
                {
                    autoProxy.autoPushingEnabled = true;
                }

                progress.Begin(1, "", "Reverting Scene State", () => {
                    foreach (var pair in _initialTransformData)
                    {
                        pair.Key.localPosition = pair.Value.localPosition;
                        pair.Key.localRotation = pair.Value.localRotation;
                        pair.Key.localScale    = pair.Value.localScale;
                        pair.Key.gameObject.SetActive(pair.Value.enabled);
                    }

                    foreach (var pair in _initialActivityData)
                    {
                        EditorUtility.SetObjectEnabled(pair.Key, pair.Value);
                    }
                });

                progress.Begin(1, "", "Patching Materials: ", () => {
                    GetComponentsInChildren(true, _recorders);
                    foreach (var recorder in _recorders)
                    {
                        DestroyImmediate(recorder);
                    }

                    //Patch up renderer references to materials
                    var allMaterials = Resources.FindObjectsOfTypeAll <Material>().
                                       Query().
                                       Where(AssetDatabase.IsMainAsset).
                                       ToList();

                    var renderers = GetComponentsInChildren <Renderer>(includeInactive: true);

                    progress.Begin(renderers.Length, "", "", () => {
                        foreach (var renderer in renderers)
                        {
                            progress.Step(renderer.name);

                            var materials = renderer.sharedMaterials;
                            for (int i = 0; i < materials.Length; i++)
                            {
                                var material = materials[i];
                                if (!AssetDatabase.IsMainAsset(material))
                                {
                                    var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) &&
                                                                                               material.shader == m.shader);

                                    if (matchingMaterial != null)
                                    {
                                        materials[i] = matchingMaterial;
                                    }
                                }
                            }
                            renderer.sharedMaterials = materials;
                        }
                    });
                });

                progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => {
                    foreach (var pair in _behaviourActivity)
                    {
                        var targetBehaviour = pair.Key;
                        var activityData    = pair.Value;

                        progress.Step(targetBehaviour.name);

                        string path         = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform);
                        Type type           = targetBehaviour.GetType();
                        string propertyName = "m_Enabled";

                        AnimationCurve curve = new AnimationCurve();
                        foreach (var dataPoint in activityData)
                        {
                            int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0);
                            AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                            AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                        }

                        if (curve.IsConstant())
                        {
                            continue;
                        }

                        var binding = EditorCurveBinding.FloatCurve(path, type, propertyName);

                        if (_curves.ContainsKey(binding))
                        {
                            Debug.LogError("Binding already existed?");
                            Debug.LogError(binding.path + " : " + binding.propertyName);
                            continue;
                        }
                        _curves.Add(binding, curve);
                    }
                });

                progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => {
                    foreach (var pair in _transformData)
                    {
                        var targetTransform = pair.Key;
                        var targetData      = pair.Value;

                        progress.Step(targetTransform.name);

                        string path = AnimationUtility.CalculateTransformPath(targetTransform, transform);

                        bool isActivityConstant = true;
                        bool isPositionConstant = true;
                        bool isRotationConstant = true;
                        bool isScaleConstant    = true;

                        {
                            bool startEnabled        = targetData[0].enabled;
                            Vector3 startPosition    = targetData[0].localPosition;
                            Quaternion startRotation = targetData[0].localRotation;
                            Vector3 startScale       = targetData[0].localScale;
                            for (int i = 1; i < targetData.Count; i++)
                            {
                                isActivityConstant &= targetData[i].enabled == startEnabled;
                                isPositionConstant &= targetData[i].localPosition == startPosition;
                                isRotationConstant &= targetData[i].localRotation == startRotation;
                                isScaleConstant    &= targetData[i].localScale == startScale;
                            }
                        }

                        for (int i = 0; i < TransformData.CURVE_COUNT; i++)
                        {
                            string propertyName = TransformData.GetName(i);
                            Type type           = typeof(Transform);

                            AnimationCurve curve = new AnimationCurve();
                            var dataType         = TransformData.GetDataType(i);

                            switch (dataType)
                            {
                            case TransformDataType.Position:
                                if (isPositionConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Rotation:
                                if (isRotationConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Scale:
                                if (isScaleConstant)
                                {
                                    continue;
                                }
                                break;

                            case TransformDataType.Activity:
                                if (isActivityConstant)
                                {
                                    continue;
                                }
                                type = typeof(GameObject);
                                break;
                            }

                            for (int j = 0; j < targetData.Count; j++)
                            {
                                int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i));
                                if (dataType == TransformDataType.Activity)
                                {
                                    AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                                    AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant);
                                }
                            }

                            var binding = EditorCurveBinding.FloatCurve(path, type, propertyName);

                            if (_curves.ContainsKey(binding))
                            {
                                Debug.LogError("Duplicate object was created??");
                                Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName);
                            }
                            else
                            {
                                _curves.Add(binding, curve);
                            }
                        }
                    }
                });

                progress.Begin(_curves.Count, "", "Compressing Data: ", () => {
                    foreach (var pair in _curves)
                    {
                        EditorCurveBinding binding = pair.Key;
                        AnimationCurve curve       = pair.Value;

                        progress.Step(binding.propertyName);

                        GameObject animationGameObject;
                        {
                            var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding);
                            if (animatedObj is GameObject)
                            {
                                animationGameObject = animatedObj as GameObject;
                            }
                            else
                            {
                                animationGameObject = (animatedObj as Component).gameObject;
                            }
                        }

                        //But if the curve is constant, just get rid of it!
                        if (curve.IsConstant())
                        {
                            //Check to make sure there are no other matching curves that are
                            //non constant.  If X and Y are constant but Z is not, we need to
                            //keep them all :(
                            if (_curves.Query().Where(p => p.Key.path == binding.path &&
                                                      p.Key.type == binding.type &&
                                                      p.Key.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)).
                                All(k => k.Value.IsConstant()))
                            {
                                continue;
                            }
                        }

                        //First do a lossless compression
                        curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon);

                        Transform targetTransform = null;
                        var targetObj             = AnimationUtility.GetAnimatedObject(gameObject, binding);
                        if (targetObj is GameObject)
                        {
                            targetTransform = (targetObj as GameObject).transform;
                        }
                        else if (targetObj is Component)
                        {
                            targetTransform = (targetObj as Component).transform;
                        }
                        else
                        {
                            Debug.LogError("Target obj was of type " + targetObj.GetType().Name);
                        }

                        var dataRecorder = targetTransform.GetComponent <RecordedData>();
                        if (dataRecorder == null)
                        {
                            dataRecorder = targetTransform.gameObject.AddComponent <RecordedData>();
                        }

                        dataRecorder.data.Add(new RecordedData.EditorCurveBindingData()
                        {
                            path         = binding.path,
                            propertyName = binding.propertyName,
                            typeName     = binding.type.Name,
                            curve        = curve
                        });
                    }
                });

                progress.Step("Finalizing Prefab...");

                var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>();

                GameObject myGameObject = gameObject;

                DestroyImmediate(this);

                string targetFolderPath = targetFolder.Path;
                if (targetFolderPath == null)
                {
                    if (myGameObject.scene.IsValid() && !string.IsNullOrEmpty(myGameObject.scene.path))
                    {
                        string sceneFolder = Path.GetDirectoryName(myGameObject.scene.path);
                        targetFolderPath   = Path.Combine(sceneFolder, "Recordings");
                    }
                    else
                    {
                        targetFolderPath = Path.Combine("Assets", "Recordings");
                    }
                }

                int folderSuffix = 1;
                string finalSubFolder;
                do
                {
                    finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0'));
                    folderSuffix++;
                } while (Directory.Exists(finalSubFolder));

                Directory.CreateDirectory(finalSubFolder);
                AssetDatabase.Refresh();

                postProcessComponent.recordingName    = recordingName;
                postProcessComponent.assetFolder.Path = finalSubFolder;
                postProcessComponent.leapData         = _leapData;

                string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab");
                PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject);
                AssetDatabase.Refresh();

                EditorApplication.isPlaying = false;
            });
        }