public void Blend(Godot.Animation animation, float influence = 1f) { Ensure.Any.IsNotNull(animation, nameof(animation)); var slot = Enumerable .Range(1, _overridableSlots) .FirstOrDefault(i => !_overrides.ContainsKey(i)); if (slot == default(int)) { throw new InvalidOperationException( $"No overridable slots left: total = {_overridableSlots}."); } var blendNode = OverrideBlendNodePrefix + slot; _overrides[slot] = animation.GetName(); TreePlayer.AnimationNodeSetAnimation(OverrideNodePrefix + slot, animation); TreePlayer.Blend2NodeSetAmount(blendNode, influence); var reset = Player.GetAnimation(ResetAnimation); if (reset == null) { return; } var filtered = new HashSet <string>(FindTransformTracks(animation).Select(p => p.ToString())); FindTransformTracks(reset) .ToList() .ForEach(p => TreePlayer.Blend2NodeSetFilterPath(blendNode, p, !filtered.Contains(p.ToString()))); }
protected virtual void PlayAnimation( IEquipmentHolder holder, Equipment equipment, Option <Node> dropTo, Godot.Animation animation, IAnimationManager animationManager, InteractionContext context) { animationManager.OnAnimationEvent .OfType <TriggerEvent>() .Where(e => e.Name == "Action" && e.Argument.Contains(Key)) .Take(1) .TakeUntil(Disposed.Where(identity)) .Subscribe(_ => Unequip(holder, equipment, dropTo, context), this); if (animationManager is IAnimationStateManager stateManager && AnimatorPath.IsSome && StatesPath.IsSome) { ( from animator in AnimatorPath.Bind(stateManager.FindAnimator) from states in StatesPath.Bind(stateManager.FindStates) from state in ActionState select(animator, states, state)).Iter(t => { t.animator.Animation = animation; t.states.Playback.Travel(t.state); }); }
protected static IEnumerable <NodePath> FindTransformTracks(Godot.Animation animation) { Ensure.That(animation, nameof(animation)).IsNotNull(); return(Enumerable .Range(0, animation.GetTrackCount()) .Select(i => (path: animation.TrackGetPath(i), type: animation.TrackGetType(i))) .Where(t => t.type == Godot.Animation.TrackType.Transform) .Select(t => t.path)); }
private static IEnumerable <NodePath> FindTransformTracks(Godot.Animation animation) { var tracks = animation.GetTrackCount(); return(Enumerable .Range(0, tracks) .Select(i => (animation.TrackGetPath(i), animation.TrackGetType(i))) .Where(t => t.Item2 == Godot.Animation.TrackType.Transform) .Select(t => t.Item1)); }
public override void Play(Godot.Animation animation, System.Action onFinish = null) { _oneShotAnimationCallback?.Dispose(); TreePlayer.AnimationNodeSetAnimation(OneShotNode, animation); TreePlayer.OneshotNodeStart(OneShotTriggerNode); if (onFinish != null) { _oneShotAnimationCallback = _scheduler?.Schedule( TimeSpan.FromSeconds(animation.Length), onFinish); } }
private void AddTrack(Godot.Animation animation) { var args = new Dictionary <object, object> { { "method", "Reset" }, { "args", new string[0] } }; var track = animation.AddTrack(Godot.Animation.TrackType.Method); animation.TrackSetPath(track, GetPath()); animation.TrackInsertKey(track, 0, args); animation.TrackInsertKey(track, animation.Length, args); }
public static string AddAnimation(this AnimationPlayer player, Godot.Animation animation) { Ensure.That(player, nameof(player)).IsNotNull(); Ensure.That(animation, nameof(animation)).IsNotNull(); var name = animation.GetKey(); Debug.Assert(name != null, "name != null"); if (!player.HasAnimation(name)) { player.AddAnimation(name, animation).ThrowOnError(); } return(name); }
internal void CreateAnimation( string animationName, IEnumerable <MWAnimationKeyframe> keyframes, IEnumerable <MWAnimationEvent> events, MWAnimationWrapMode wrapMode, MWSetAnimationStateOptions initialState, bool isInternal, bool managed, Action onCreatedCallback) { var continuation = new MWContinuation(AttachedActor, null, (result) => { var animationPlayer = GetOrCreateGodotAnimationPlayer(animationName); var animation = new GodotAnimation(); animation.Loop = wrapMode.IsInterpolationLoopWrap(); var curves = new Dictionary <string, int>(); int GetOrCreateCurve(Type type, string propertyName) { if (!curves.TryGetValue(propertyName, out int trackIndex)) { trackIndex = animation.AddTrack(GodotAnimation.TrackType.Bezier); curves.Add(propertyName, trackIndex); } return(trackIndex); } void AddFloatPatch(Type type, string propertyName, float time, float?value) { if (value.HasValue) { var trackIndex = GetOrCreateCurve(type, propertyName); animation.TrackSetPath(trackIndex, propertyName); animation.BezierTrackInsertKey(trackIndex, time, value.Value); } } void AddVector3Patch(Type type, string propertyName, float time, Vector3Patch value) { AddFloatPatch(type, String.Format("{0}:x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}:y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}:z", propertyName), time, value?.Z); } void AddQuaternionPatch(Type type, string propertyName, float time, QuaternionPatch value) { AddFloatPatch(type, String.Format("{0}:x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}:y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}:z", propertyName), time, value?.Z); AddFloatPatch(type, String.Format("{0}:w", propertyName), time, value?.W); } void AddTransformPatch(float time, ScaledTransformPatch value) { // Work around a Unity bug/feature where all position components must be specified // in the keyframe or the missing fields get set to zero. Vector3Patch position = value?.Position; if (position != null && position.IsPatched()) { if (!position.X.HasValue) { position.X = Transform.origin.x; } if (!position.Y.HasValue) { position.Y = Transform.origin.y; } if (!position.Z.HasValue) { position.Z = Transform.origin.z; } } // Work around a Unity bug/feature where all scale components must be specified // in the keyframe or the missing fields get set to one. Vector3Patch scale = value?.Scale; if (scale != null && scale.IsPatched()) { if (!scale.X.HasValue) { scale.X = Scale.x; } if (!scale.Y.HasValue) { scale.Y = Scale.y; } if (!scale.Z.HasValue) { scale.Z = Scale.z; } } AddVector3Patch(typeof(Transform), "..:translation", time, value?.Position); var ratation = value?.Rotation; var quat = new Quat(ratation.X.Value, ratation.Y.Value, ratation.Z.Value, ratation.W.Value); var vector3 = quat.GetEuler(); AddVector3Patch(typeof(Transform), "..:rotation_degrees", time, new Vector3Patch(vector3)); AddVector3Patch(typeof(Transform), "..:scale", time, value?.Scale); } void AddActorPatch(float time, ActorPatch value) { AddTransformPatch(time, value?.Transform.Local); } void AddKeyframe(MWAnimationKeyframe keyframe) { AddActorPatch(keyframe.Time, keyframe.Value); if (animation.Length < keyframe.Time) { animation.Length = keyframe.Time; } } foreach (var keyframe in keyframes) { AddKeyframe(keyframe); } _animationData[animationName] = new AnimationData() { IsInternal = isInternal, Managed = managed }; float initialTime = 0f; float initialSpeed = 1f; bool initialEnabled = false; if (initialState != null) { initialTime = initialState.Time ?? initialTime; initialSpeed = initialState.Speed ?? initialSpeed; initialEnabled = initialState.Enabled ?? initialEnabled; } animationPlayer.AddAnimation(animationName, animation); animationPlayer.AssignedAnimation = animationName; SetAnimationState(animationName, initialTime, initialSpeed, initialEnabled); onCreatedCallback?.Invoke(); }); continuation.Start(); }
public MeleeToolConfiguration( string key, string slot, Set <string> additionalSlots, Set <string> tags, Option <IInputBindings> armInput, Option <IInputBindings> swingInput, Godot.Animation swingAnimation, string statesPath, string seekerPath, string idleState, string swingState, Range <float> animationRange, IPlayerControl playerControl, bool active, ILoggerFactory loggerFactory) : base(key, slot, additionalSlots, tags, active, loggerFactory) { Ensure.That(swingAnimation, nameof(swingAnimation)).IsNotNull(); Ensure.That(statesPath, nameof(statesPath)).IsNotNullOrEmpty(); Ensure.That(seekerPath, nameof(seekerPath)).IsNotNullOrEmpty(); Ensure.That(idleState, nameof(idleState)).IsNotNullOrEmpty(); Ensure.That(swingState, nameof(swingState)).IsNotNullOrEmpty(); Ensure.That(playerControl, nameof(playerControl)).IsNotNull(); SwingAnimation = swingAnimation; StatesPath = statesPath; SeekerPath = seekerPath; IdleState = idleState; SwingState = swingState; AnimationRange = animationRange; PlayerControl = playerControl; OnPlayerChange = OnHolderChange .CombineLatest(PlayerControl.OnCharacterChange, (h, p) => h.Filter(v => p.Contains(v))) .Select(p => p.ToObservable()) .Switch(); SwingInput = swingInput .Bind(i => i.AsVector2Input()) .MatchObservable(identity, Empty <Vector2>) .Where(_ => Valid) .Select(v => v * 2f); ArmInput = armInput.Bind(i => i.FindTrigger().HeadOrNone()) .MatchObservable(identity, Empty <bool>) .Where(_ => Valid); var manager = OnPlayerChange .Select(p => p.AnimationManager) .OfType <IAnimationStateManager>(); var states = manager .Select(m => m.FindStates(StatesPath).ToObservable()) .Switch(); var seeker = manager .Select(m => m.FindSeekableAnimator(SeekerPath).ToObservable()) .Switch(); var blender = manager .Select(m => AnimationBlend.Bind(m.FindBlender).ToObservable()) .Switch(); OnArm = OnPlayerChange .Select(_ => ArmInput.Where(identity)) .Switch() .AsUnitObservable() .WithLatestFrom(states, (a, s) => s.State == IdleState ? Return(a) : Empty <Unit>()) .Switch(); OnDisarm = Merge( ArmInput.Where(v => !v).AsUnitObservable(), OnHolderChange.Where(v => v.IsNone).AsUnitObservable(), Disposed.Where(identity).AsUnitObservable()) .WithLatestFrom(states, (a, s) => s.State == SwingState ? Return(a) : Empty <Unit>()) .Switch(); OnSwing = OnArm .Select(_ => SwingInput.TakeUntil(OnDisarm).Select(v => v.y).DistinctUntilChanged()) .Switch() .Scan(0f, (s, v) => Mathf.Clamp(s + v, 0f, 600f)) .Select(v => v / 600f); bool Conflicts(IInput input) => swingInput.Bind(i => i.Inputs.Values).Exists(input.ConflictsWith); ConflictingInputs = playerControl.Inputs.Filter(i => i.Active).Filter(Conflicts); }