Пример #1
0
        public void Prepare(bool resize)
        {
            if (SuperController.singleton.motionAnimationMaster == null || _containingAtom?.motionAnimationControls == null)
            {
                throw new Exception("Timeline: Missing motion animation controls");
            }

            var length = _containingAtom.motionAnimationControls.Select(m => m?.clip?.clipLength ?? 0).Max().Snap(0.01f);

            if (length < 0.01f)
            {
                throw new Exception("Timeline: No motion animation to import.");
            }

            var requiresRebuild = false;

            if (clip.loop)
            {
                clip.loop       = SuperController.singleton.motionAnimationMaster.loop;
                requiresRebuild = true;
            }
            if (resize && length != clip.animationLength)
            {
                new ResizeAnimationOperations(clip).CropOrExtendEnd(length);
                requiresRebuild = true;
            }
            if (requiresRebuild)
            {
                _animation.RebuildAnimationNow();
            }
        }
Пример #2
0
        public void ImportClips(IEnumerable <AtomAnimationClip> clips)
        {
            var importedClips = new List <AtomAnimationClip>();

            _animation.index.StartBulkUpdates();
            try
            {
                foreach (var clip in clips.SelectMany(ImportClip))
                {
                    clip.Validate();
                    _animation.AddClip(clip);
                    importedClips.Add(clip);
                }
            }
            finally
            {
                _animation.index.EndBulkUpdates();
            }

            foreach (var clip in importedClips)
            {
                if (clip.autoPlay && _animation.index.ByLayer(clip.animationLayer).Any(c => c.autoPlay))
                {
                    clip.autoPlay = false;
                }
            }

            _animation.RebuildAnimationNow();
        }
        public void DeserializeAnimation(AtomAnimation animation, JSONClass animationJSON)
        {
            if (animation == null)
            {
                throw new ArgumentNullException(nameof(animation));
            }

            animation.speed = DeserializeFloat(animationJSON["Speed"], 1f);

            JSONArray clipsJSON = animationJSON["Clips"].AsArray;

            if (clipsJSON == null || clipsJSON.Count == 0)
            {
                throw new NullReferenceException("Saved state does not have clips");
            }
            foreach (JSONClass clipJSON in clipsJSON)
            {
                var animationName  = clipJSON["AnimationName"].Value;
                var animationLayer = DeserializeString(clipJSON["AnimationLayer"], AtomAnimationClip.DefaultAnimationLayer);
                var existingClip   = animation.GetClip(animationName);
                if (existingClip != null)
                {
                    if (existingClip.IsEmpty())
                    {
                        var clipToRemove = animation.GetClip(animationName);
                        animation.clips.Remove(clipToRemove);
                        clipToRemove.Dispose();
                    }
                    else
                    {
                        var newAnimationName = GenerateUniqueAnimationName(animation, animationName);
                        SuperController.LogError($"VamTimeline: Imported clip '{animationName}' already exists and will be imported with the name {newAnimationName}");
                        animationName = newAnimationName;
                    }
                }
                var clip = new AtomAnimationClip(animationName, animationLayer)
                {
                    blendDuration = DeserializeFloat(clipJSON["BlendDuration"], AtomAnimationClip.DefaultBlendDuration),
                    loop          = DeserializeBool(clipJSON["Loop"], true),
                    transition    = DeserializeBool(clipJSON["Transition"], false),
                    ensureQuaternionContinuity = DeserializeBool(clipJSON["EnsureQuaternionContinuity"], true),
                    nextAnimationName          = clipJSON["NextAnimationName"]?.Value,
                    nextAnimationTime          = DeserializeFloat(clipJSON["NextAnimationTime"], 0),
                    autoPlay = DeserializeBool(clipJSON["AutoPlay"], false),
                    speed    = DeserializeFloat(clipJSON["Speed"], 1),
                    weight   = DeserializeFloat(clipJSON["Weight"], 1),
                };
                clip.animationLength = DeserializeFloat(clipJSON["AnimationLength"]).Snap();
                DeserializeClip(clip, clipJSON);
                animation.AddClip(clip);
            }
            animation.Initialize();
            animation.RebuildAnimationNow();
        }
Пример #4
0
        public IEnumerator StartRecording(List <FreeControllerAnimationTarget> controllers, List <FloatParamAnimationTarget> floatParams)
        {
            // TODO: Handle stopping in the middle of it
            // TODO: Handle starting while it's already recording
            // TODO: Counter should use in-game rather than helptext

            _animation.StopAll();
            _animation.ResetAll();

            var keyframesOps = new KeyframesOperations(_clip);

            for (var i = 5; i > 0; i--)
            {
                SuperController.singleton.helpText = $"Start recording in {i}...";
                var next = Time.realtimeSinceStartup + 1f;
                while (Time.realtimeSinceStartup < next)
                {
                    yield return(0);

                    if (Input.GetKeyDown(KeyCode.Escape))
                    {
                        yield break;
                    }
                }
            }

            SuperController.singleton.helpText = "Recording...";

            foreach (var target in controllers)
            {
                keyframesOps.RemoveAll(target);
            }
            foreach (var target in floatParams)
            {
                keyframesOps.RemoveAll(target);
            }

            _clip.DirtyAll();
            _animation.RebuildAnimationNow();

            yield return(0);

            foreach (var target in controllers)
            {
                target.recording = true;
                target.StartBulkUpdates();
            }
            foreach (var target in floatParams)
            {
                target.recording = true;
                target.StartBulkUpdates();
            }

            _animation.PlayClip(_clip, false);

            while (_animation.playTime <= _clip.animationLength && _animation.isPlaying)
            {
                if (Input.GetKeyDown(KeyCode.Escape))
                {
                    break;
                }
                yield return(0);
            }

            _animation.StopAll();
            _animation.ResetAll();
            SuperController.singleton.helpText = "";

            // TODO: This needs to be guaranteed. We could register the enumerator inside a disposable class, dispose being called in different cancel situations
            foreach (var target in controllers)
            {
                target.recording = false;
                target.EndBulkUpdates();
            }
            foreach (var target in floatParams)
            {
                target.recording = false;
                target.EndBulkUpdates();
            }

            _clip.DirtyAll();
        }