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(); }
public AtomAnimationClip AddTransitionAnimation() { var next = _animation.GetClip(_clip.animationLayer, _clip.nextAnimationName); if (next == null) { SuperController.LogError("There is no animation to transition to"); return(null); } var clip = _animation.CreateClip(_clip); clip.animationName = $"{_clip.animationName} > {next.animationName}"; clip.loop = false; clip.autoTransitionPrevious = _animation.index.ByLayer(_clip.animationLayer).Any(c => c.animationLayer == _clip.animationLayer); clip.autoTransitionNext = _clip.nextAnimationName != null; clip.nextAnimationName = _clip.nextAnimationName; clip.blendInDuration = AtomAnimationClip.DefaultBlendDuration; clip.nextAnimationTime = clip.animationLength - clip.blendInDuration; clip.ensureQuaternionContinuity = _clip.ensureQuaternionContinuity; foreach (var origTarget in _clip.targetControllers) { var newTarget = CopyTarget(clip, origTarget); newTarget.SetCurveSnapshot(0f, origTarget.GetCurveSnapshot(_clip.animationLength)); newTarget.SetCurveSnapshot(clip.animationLength, next.targetControllers.First(t => t.TargetsSameAs(origTarget)).GetCurveSnapshot(0f)); } foreach (var origTarget in _clip.targetFloatParams) { if (!origTarget.EnsureAvailable(false)) { continue; } var newTarget = clip.Add(origTarget.storable, origTarget.floatParam); newTarget.SetCurveSnapshot(0f, origTarget.GetCurveSnapshot(_clip.animationLength)); newTarget.SetCurveSnapshot(clip.animationLength, next.targetFloatParams.First(t => t.TargetsSameAs(origTarget)).GetCurveSnapshot(0f)); } _animation.clips.Remove(clip); _animation.clips.Insert(_animation.clips.IndexOf(_clip) + 1, clip); _clip.nextAnimationName = clip.animationName; return(clip); }
public List <AtomAnimationClip> ImportClip(AtomAnimationClip clip) { var clips = new List <AtomAnimationClip>(); var matchingLayer = _animation.clips.FirstOrDefault(c => { // We only need to match float params and controllers, triggers can be in any layers if (!clip.targetFloatParams.All(t => c.targetFloatParams.Any(t.TargetsSameAs))) { return(false); } if (!clip.targetControllers.All(t => c.targetControllers.Any(t.TargetsSameAs))) { return(false); } return(true); }); if (matchingLayer != null) { clip.animationLayer = matchingLayer.animationLayer; // Add missing targets foreach (var target in matchingLayer.targetFloatParams) { if (!clip.targetFloatParams.Any(t => target.TargetsSameAs(t))) { var missing = new FloatParamAnimationTarget(target); missing.AddEdgeFramesIfMissing(clip.animationLength); clip.Add(missing); } } foreach (var target in matchingLayer.targetControllers) { if (!clip.targetControllers.Any(t => target.TargetsSameAs(t))) { var missing = new FreeControllerAnimationTarget(target.controller); missing.AddEdgeFramesIfMissing(clip.animationLength); clip.Add(missing); } } } else if (_animation.index.ByLayer(clip.animationLayer).Any()) { clip.animationLayer = new LayersOperations(_animation, clip).GetNewLayerName(); } foreach (var controller in clip.targetControllers.Select(t => t.controller)) { if (_animation.clips.Where(c => c.animationLayer != clip.animationLayer).Any(c => c.targetControllers.Any(t => t.controller == controller))) { if (!_silent) { SuperController.LogError($"Timeline: Imported animation contains controller {controller.name} in layer {clip.animationLayer}, but that controller is already used elsewhere in your animation. To import, a layer is needed with targets: {string.Join(", ", clip.GetAllCurveTargets().Select(c => c.GetShortName()).ToArray())}"); } return(clips); } } foreach (var floatParam in clip.targetFloatParams.Select(t => t.name)) { if (_animation.clips.Where(c => c.animationLayer != clip.animationLayer).Any(c => c.targetFloatParams.Any(t => t.name == floatParam))) { if (!_silent) { SuperController.LogError($"Timeline: Imported animation contains storable float {floatParam} in layer {clip.animationLayer}, but that storable is already used elsewhere in your animation. To import, a layer is needed with targets: {string.Join(", ", clip.GetAllCurveTargets().Select(c => c.GetShortName()).ToArray())}"); } return(clips); } } var existingClip = _animation.GetClip(clip.animationLayer, clip.animationName); if (existingClip != null) { if (existingClip.IsEmpty()) { _animation.clips.Remove(existingClip); existingClip.Dispose(); } else { var newAnimationName = GenerateUniqueAnimationName(clip.animationLayer, clip.animationName); if (!_silent) { SuperController.LogError($"Timeline: Imported clip '{clip.animationNameQualified}' already exists and will be imported with the name {newAnimationName}"); } clip.animationName = newAnimationName; } } clips.Add(clip); return(clips); }
private AtomAnimationClip GetClip(object[] e) { return(animation.GetClip((string)e[1])); }