From 530ae61c1ad74920aaf530384250f64d15292dd4 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 23 Feb 2024 09:58:29 -0700 Subject: [PATCH] Added new top-down animation controller generated code --- .../MainEntityInputMovementPlugin.cs | 10 + .../PlatformerAnimationControllerGenerator.cs | 75 +++--- .../TopDownAnimationControllerGenerator.cs | 240 ++++++++++++++++++ .../Controllers/MainController.cs | 5 +- .../GlueTestProjectDesktopGl.csproj | 1 + 5 files changed, 291 insertions(+), 40 deletions(-) create mode 100644 FRBDK/Glue/TopDownPlugin/CodeGenerators/TopDownAnimationControllerGenerator.cs diff --git a/FRBDK/Glue/EntityInputMovementPlugin/MainEntityInputMovementPlugin.cs b/FRBDK/Glue/EntityInputMovementPlugin/MainEntityInputMovementPlugin.cs index e90d79f94..c579173b8 100644 --- a/FRBDK/Glue/EntityInputMovementPlugin/MainEntityInputMovementPlugin.cs +++ b/FRBDK/Glue/EntityInputMovementPlugin/MainEntityInputMovementPlugin.cs @@ -155,6 +155,16 @@ private static async Task UpdateTopDownCodePresenceInProject() await topDownController.GenerateAndAddCsv( firstTopDownEntity, viewModel); + + TopDownPlugin.CodeGenerators.TopDownAnimationControllerGenerator.Self.GenerateAndSave(); + + } + else + { + // Platformer removes here. Should we also remove top-down? + + GlueCommands.Self.ProjectCommands.RemoveFromProjects(TopDownPlugin.CodeGenerators.TopDownAnimationControllerGenerator.Self.FileLocation); + } // remove requirement for the old top-down plugin otherwise projects will get a message forever about it: diff --git a/FRBDK/Glue/PlatformerPlugin/CodeGenerators/PlatformerAnimationControllerGenerator.cs b/FRBDK/Glue/PlatformerPlugin/CodeGenerators/PlatformerAnimationControllerGenerator.cs index 246084d2d..9a55c4c96 100644 --- a/FRBDK/Glue/PlatformerPlugin/CodeGenerators/PlatformerAnimationControllerGenerator.cs +++ b/FRBDK/Glue/PlatformerPlugin/CodeGenerators/PlatformerAnimationControllerGenerator.cs @@ -6,50 +6,50 @@ using System.Collections.Generic; using System.Text; -namespace FlatRedBall.PlatformerPlugin.Generators +namespace FlatRedBall.PlatformerPlugin.Generators; + +public class PlatformerAnimationControllerGenerator : Singleton { - public class PlatformerAnimationControllerGenerator : Singleton - { - string RelativeFileLocation => "Platformer/PlatformerAnimationController.Generated.cs"; - public FilePath FileLocation => GlueState.Self.CurrentGlueProjectDirectory + RelativeFileLocation; + string RelativeFileLocation => "Platformer/PlatformerAnimationController.Generated.cs"; + public FilePath FileLocation => GlueState.Self.CurrentGlueProjectDirectory + RelativeFileLocation; - public void GenerateAndSave() + public void GenerateAndSave() + { + + TaskManager.Self.Add(() => { + var contents = GenerateFileContents(); - TaskManager.Self.Add(() => - { - var contents = GenerateFileContents(); + var relativeDirectory = RelativeFileLocation; - var relativeDirectory = RelativeFileLocation; + GlueCommands.Self.ProjectCommands.CreateAndAddCodeFile(relativeDirectory); - GlueCommands.Self.ProjectCommands.CreateAndAddCodeFile(relativeDirectory); + var glueProjectDirectory = GlueState.Self.CurrentGlueProjectDirectory; - var glueProjectDirectory = GlueState.Self.CurrentGlueProjectDirectory; + if (!string.IsNullOrEmpty(glueProjectDirectory)) + { + var fullFile = GlueState.Self.CurrentGlueProjectDirectory + relativeDirectory; - if (!string.IsNullOrEmpty(glueProjectDirectory)) + try { - var fullFile = GlueState.Self.CurrentGlueProjectDirectory + relativeDirectory; - - try - { - GlueCommands.Self.TryMultipleTimes(() => - System.IO.File.WriteAllText(fullFile, contents)); - } - catch (Exception e) - { - GlueCommands.Self.PrintError(e.ToString()); - } + GlueCommands.Self.TryMultipleTimes(() => + System.IO.File.WriteAllText(fullFile, contents)); } + catch (Exception e) + { + GlueCommands.Self.PrintError(e.ToString()); + } + } - }, "Adding PlatformerAnimationConfiguration.Generated.cs to the project"); + }, "Adding PlatformerAnimationConfiguration.Generated.cs to the project"); - } + } - private string GenerateFileContents() - { - var toReturn = + private string GenerateFileContents() + { + var toReturn = @" using System.Linq; @@ -127,17 +127,17 @@ public void AddLayer(PlatformerAnimationConfiguration configuration) "; - if(GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.AnimationLayerHasName) - { - toReturn += - @" + if(GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.AnimationLayerHasName) + { + toReturn += + @" layer.Name = configuration.AnimationName; "; - } + } - toReturn += - @" + toReturn += + @" layer.EveryFrameAction = () => { if(!IsActive) @@ -264,7 +264,6 @@ public void AddLayer(PlatformerAnimationConfiguration configuration) } "; - return toReturn; - } + return toReturn; } } diff --git a/FRBDK/Glue/TopDownPlugin/CodeGenerators/TopDownAnimationControllerGenerator.cs b/FRBDK/Glue/TopDownPlugin/CodeGenerators/TopDownAnimationControllerGenerator.cs new file mode 100644 index 000000000..552bf89ae --- /dev/null +++ b/FRBDK/Glue/TopDownPlugin/CodeGenerators/TopDownAnimationControllerGenerator.cs @@ -0,0 +1,240 @@ +using FlatRedBall.Glue.Managers; +using FlatRedBall.Glue.Plugins.ExportedImplementations; +using FlatRedBall.Glue.SaveClasses; +using FlatRedBall.IO; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TopDownPlugin.CodeGenerators; + +public class TopDownAnimationControllerGenerator : Singleton +{ + string RelativeFileLocation = "TopDown/TopDownAnimationControllerGenerator.Generated.cs"; + public FilePath FileLocation => GlueState.Self.CurrentGlueProjectDirectory + RelativeFileLocation; + + public void GenerateAndSave() + { + + TaskManager.Self.Add(() => + { + var contents = GenerateFileContents(); + + var relativeDirectory = RelativeFileLocation; + + GlueCommands.Self.ProjectCommands.CreateAndAddCodeFile(relativeDirectory); + + var glueProjectDirectory = GlueState.Self.CurrentGlueProjectDirectory; + + if (!string.IsNullOrEmpty(glueProjectDirectory)) + { + var fullFile = GlueState.Self.CurrentGlueProjectDirectory + relativeDirectory; + + try + { + GlueCommands.Self.TryMultipleTimes(() => + System.IO.File.WriteAllText(fullFile, contents)); + } + catch (Exception e) + { + GlueCommands.Self.PrintError(e.ToString()); + } + } + + }, "Adding TopDownAnimationControllerGenerator.Generated.cs to the project"); + + } + + private string GenerateFileContents() + { + var toReturn = +@" +using System.Linq; + +namespace " + GlueState.Self.ProjectNamespace + @".TopDown +{ + public enum AnimationSpeedAssignment + { + ForceTo1, + NoAssignment, + BasedOnVelocityMultiplier, + BasedOnMaxSpeedRatioMultiplier, + BasedOnInputMultiplier + } + + public class TopDownAnimationConfiguration + { + public string AnimationName { get; set; } + public bool IsDirectionFacingAppended { get; set; } = true; + + + public float? MinVelocityAbsolute { get; set; } + public float? MaxVelocityAbsolute { get; set; } + + public float? AbsoluteVelocityAnimationSpeedMultiplier { get; set; } + + public float? MinMovementInputAbsolute { get; set; } + public float? MaxMovementInputAbsolute { get; set; } + + public float? MaxSpeedRatioMultiplier { get; set; } + + public string MovementName { get; set; } + + public AnimationSpeedAssignment AnimationSpeedAssignment { get; set; } + + public System.Func AdditionalPredicate; + + public override string ToString() + { + return AnimationName; + } + } + + public class TopDownAnimationController : FlatRedBall.Graphics.Animation.AnimationController + { + ITopDownEntity TopDownEntity; + + public bool IsActive { get; set; } = true; + + System.Collections.Generic.List topDownAnimationConfigurations; + public System.Collections.ObjectModel.ReadOnlyCollection Configurations { get; private set; } + + public TopDownAnimationController(ITopDownEntity topDownEntity) + { + TopDownEntity = topDownEntity; + topDownAnimationConfigurations = + new System.Collections.Generic.List(); + Configurations = new System.Collections.ObjectModel.ReadOnlyCollection(topDownAnimationConfigurations); + } + + public TopDownAnimationConfiguration GetConfiguration(string animationName) => + topDownAnimationConfigurations.First(item => item.AnimationName == animationName); + + public void AddLayer(TopDownAnimationConfiguration configuration) + { + var layer = new FlatRedBall.Graphics.Animation.AnimationLayer(); + this.Layers.Add(layer); + topDownAnimationConfigurations.Add(configuration); +"; + + if (GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.AnimationLayerHasName) + { + toReturn += + @" + layer.Name = configuration.AnimationName; +"; + + } + + toReturn += + @" + + layer.EveryFrameAction = () => + { + if (!IsActive) + { + return null; + } + + bool shouldSet = true; + + var absoluteVelocity = (float)System.Math.Sqrt(TopDownEntity.XVelocity * TopDownEntity.XVelocity + TopDownEntity.YVelocity * TopDownEntity.YVelocity); + var absoluteInput = TopDownEntity.MovementInput?.Magnitude ?? 0; + + if(shouldSet && !string.IsNullOrEmpty(configuration.MovementName)) + { + shouldSet = configuration.MovementName == TopDownEntity.CurrentMovement?.Name; + } + + shouldSet = shouldSet && (absoluteVelocity < configuration.MinVelocityAbsolute) == false; + shouldSet = shouldSet && (absoluteVelocity > configuration.MaxVelocityAbsolute) == false; + + shouldSet = shouldSet && (absoluteInput < configuration.MinMovementInputAbsolute) == false; + shouldSet = shouldSet && (absoluteInput > configuration.MaxMovementInputAbsolute) == false; + + if (shouldSet && configuration.AdditionalPredicate != null) + { + shouldSet = configuration.AdditionalPredicate(); + } + + + if (shouldSet) + { + switch (configuration.AnimationSpeedAssignment) + { + case AnimationSpeedAssignment.ForceTo1: + { + var asSprite = this.AnimatedObject as FlatRedBall.Sprite; + + if (asSprite != null) + { + asSprite.AnimationSpeed = 1; + } + } + break; + case AnimationSpeedAssignment.NoAssignment: + break; + case AnimationSpeedAssignment.BasedOnVelocityMultiplier: + { + var asSprite = this.AnimatedObject as FlatRedBall.Sprite; + + if (configuration.AbsoluteVelocityAnimationSpeedMultiplier != null) + { + asSprite.AnimationSpeed = configuration.AbsoluteVelocityAnimationSpeedMultiplier.Value * + absoluteVelocity; + } + } + break; + case AnimationSpeedAssignment.BasedOnMaxSpeedRatioMultiplier: + { + var asSprite = this.AnimatedObject as FlatRedBall.Sprite; + if (asSprite != null) + { + if (configuration.MaxSpeedRatioMultiplier != null) + { + if (TopDownEntity.MaxSpeed == 0) + { + asSprite.AnimationSpeed = 1; + } + else + { + asSprite.AnimationSpeed = configuration.MaxSpeedRatioMultiplier.Value * absoluteVelocity / TopDownEntity.MaxSpeed; + } + } + } + } + break; + case AnimationSpeedAssignment.BasedOnInputMultiplier: + { + var asSprite = this.AnimatedObject as FlatRedBall.Sprite; + if (asSprite != null) + { + asSprite.AnimationSpeed = TopDownEntity.MovementInput.Magnitude; + } + } + break; + } + + + var toReturn = configuration.AnimationName; + if (configuration.IsDirectionFacingAppended) + { + toReturn += TopDownEntity.DirectionFacing.ToString(); + } + return toReturn; + } + + return null; + }; + } + } +} + + +"; + return toReturn; + } + +} diff --git a/FRBDK/Glue/TopDownPlugin/Controllers/MainController.cs b/FRBDK/Glue/TopDownPlugin/Controllers/MainController.cs index 4eb3f5d4f..f1ef688a2 100644 --- a/FRBDK/Glue/TopDownPlugin/Controllers/MainController.cs +++ b/FRBDK/Glue/TopDownPlugin/Controllers/MainController.cs @@ -52,7 +52,7 @@ public TopDownEntityViewModel GetViewModel() if (viewModel == null) { viewModel = new TopDownEntityViewModel(); - viewModel.PropertyChanged += HandleViewModelPropertyChange; + viewModel.PropertyChanged += HandleViewModelPropertyChanged; } return viewModel; @@ -76,7 +76,7 @@ private void AddTopDownGlueVariables(EntitySave entity) // property. But we'll just codegen that for now. } - private async void HandleViewModelPropertyChange(object sender, PropertyChangedEventArgs e) + private async void HandleViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { /////////// early out /////////// if (ignoresPropertyChanges) @@ -158,6 +158,7 @@ await TaskManager.Self.AddAsync( AiTargetLogicCodeGenerator.Self.GenerateAndSave(); AnimationCodeGenerator.Self.GenerateAndSave(); } + TopDownAnimationControllerGenerator.Self.GenerateAndSave(); }, "Generating all top-down code"); } diff --git a/Tests/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl.csproj b/Tests/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl.csproj index 605da0962..49543853d 100644 --- a/Tests/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl.csproj +++ b/Tests/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl/GlueTestProjectDesktopGl.csproj @@ -1397,6 +1397,7 @@ +