Skip to content

Commit

Permalink
Lots of work on the new Top Down animation system.
Browse files Browse the repository at this point in the history
  • Loading branch information
vchelaru committed Feb 23, 2024
1 parent 530ae61 commit 0037022
Show file tree
Hide file tree
Showing 25 changed files with 1,291 additions and 744 deletions.
2 changes: 1 addition & 1 deletion Engines/FlatRedBallXNA/FlatRedBall/FlatRedBallServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public class SyntaxVersionAttribute : Attribute
public int Version;
}

[SyntaxVersion(Version=53)]
[SyntaxVersion(Version=54)]
public static partial class FlatRedBallServices
{
internal static SingleThreadSynchronizationContext singleThreadSynchronizationContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public override void StartUp()
base.RegisterCodeGenerator(new TopDownPlugin.CodeGenerators.EntityCodeGenerator());
base.RegisterCodeGenerator(new FlatRedBall.PlatformerPlugin.Generators.EntityCodeGenerator());
base.RegisterCodeGenerator(new PlatformerPluginCore.CodeGenerators.EntityPlatformerAnimationCodeGenerator());
base.RegisterCodeGenerator(new TopDownPlugin.CodeGenerators.EntityTopDownAnimationCodeGenerator());
base.RegisterCodeGenerator(new CodeGenerators.EntityCodeGenerator());
AssignEvents();
}
Expand Down Expand Up @@ -142,13 +143,15 @@ private static async Task<bool> UpdateTopDownCodePresenceInProject()
TopDownPlugin.CodeGenerators.InterfacesFileGenerator.Self.GenerateAndSave();
TopDownPlugin.CodeGenerators.AiCodeGenerator.Self.GenerateAndSave();
TopDownPluginCore.CodeGenerators.AiTargetLogicCodeGenerator.Self.GenerateAndSave();
TopDownPlugin.CodeGenerators.AnimationCodeGenerator.Self.GenerateAndSave();

var topDownController = TopDownPlugin.Controllers.MainController.Self;

// This guarantees a instance exists in the controller and returns it...
var viewModel =
TopDownPlugin.Controllers.MainController.Self.GetViewModel();



// ...updating to the argument entity will update the view model that was returned in the last call.
TopDownPlugin.Controllers.MainController.Self.UpdateTo(firstTopDownEntity);

Expand Down Expand Up @@ -217,6 +220,7 @@ private void CreateMainView()
var topDownViewModel = TopDownPlugin.Controllers.MainController.Self.GetViewModel();
mainViewModel.TopDownViewModel = topDownViewModel;
mainView.TopDownView.DataContext = topDownViewModel;
TopDownPlugin.Controllers.AnimationController.TopDownViewModel = topDownViewModel;
#endregion

#region Platformer
Expand Down
7 changes: 5 additions & 2 deletions FRBDK/Glue/Glue/SaveClasses/GlueProjectSave.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,18 @@ public enum GluxVersions
DamageDealingToggles = 52,

VariantsInsteadOfTypes = 53,


// February 23, 2023
ITopDownEntity = 54,
// Stop! If adding an entry here, modify SyntaxVersionAttribute on FlatRedBallServices
// and LatestVersion down below
}

#endregion

#region Versions

public const int LatestVersion = (int)GluxVersions.VariantsInsteadOfTypes;
public const int LatestVersion = (int)GluxVersions.ITopDownEntity;

public int FileVersion { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,133 +11,132 @@
using System.Linq;
using System.Text;

namespace PlatformerPluginCore.CodeGenerators
namespace PlatformerPluginCore.CodeGenerators;

public class EntityPlatformerAnimationCodeGenerator : ElementComponentCodeGenerator
{
public class EntityPlatformerAnimationCodeGenerator : ElementComponentCodeGenerator
// July 17, 2022
// Vic says - Unlike other data which is embedded in the glue files, this sits in its
// own file. This means that we don't have a cached place for it. We could...but that would
// be more coding overhead and possible bugs. This should be really fast, since most games will
// not have very many of these, and these deserialize fast.
// We'll review performance if in the future some game uses a ton of these files and codegen slows
// down too much, but I think that's unlikely.
SaveClasses.AllPlatformerAnimationValues GetAnimationValuesFor(GlueElement element)
{
// July 17, 2022
// Vic says - Unlike other data which is embedded in teh glue files, this sits in its
// own file. This means that we don't have a cached place for it. We could...but that would
// be more coding overhead and possible bugs. This should be really fast, since most games will
// not have very many of these, and these deserialize fast.
// We'll review performance if in the future some game uses a ton of these files and codegen slows
// down too much, but I think that's unlikely.
SaveClasses.AllPlatformerAnimationValues GetAnimationValuesFor(IElement element)
var asEntitySave = element as EntitySave;
var shouldGenerate = asEntitySave != null &&
FlatRedBall.PlatformerPlugin.Controllers.MainController.IsPlatformer(asEntitySave) &&
GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.IPlatformer;

FilePath platformerAnimationJson = null;

if(shouldGenerate)
{
EntitySave asEntitySave = element as EntitySave;
var shouldGenerate = asEntitySave != null &&
FlatRedBall.PlatformerPlugin.Controllers.MainController.IsPlatformer(asEntitySave) &&
GlueState.Self.CurrentGlueProject.FileVersion >= (int)GlueProjectSave.GluxVersions.IPlatformer;
platformerAnimationJson = Controllers.AnimationController.PlatformerAnimationsFileLocationFor(asEntitySave);

FilePath platformerAnimationJson = null;
shouldGenerate = platformerAnimationJson.Exists();
}

if(shouldGenerate)
{
platformerAnimationJson = Controllers.AnimationController.PlatformerAnimationsFileLocationFor(asEntitySave);
if(shouldGenerate)
{
var fileContents = System.IO.File.ReadAllText(platformerAnimationJson.FullPath);
var deserialized = JsonConvert.DeserializeObject<SaveClasses.AllPlatformerAnimationValues>(fileContents);

shouldGenerate = platformerAnimationJson.Exists();
}
return deserialized;
}
return null;
}

if(shouldGenerate)
{
var fileContents = System.IO.File.ReadAllText(platformerAnimationJson.FullPath);
var deserialized = JsonConvert.DeserializeObject<SaveClasses.AllPlatformerAnimationValues>(fileContents);
string PlatformerAnimationControllerClassName =>
$"{GlueState.Self.ProjectNamespace}.Entities.PlatformerAnimationController";

return deserialized;
}
return null;
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, IElement element)
{
var animationValues = GetAnimationValuesFor(element as GlueElement);

if(animationValues != null)
{
codeBlock.Line($"{PlatformerAnimationControllerClassName} PlatformerAnimationController;");
}
return codeBlock;
}


public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, IElement element)
{

string PlatformerAnimationControllerClassName =>
$"{GlueState.Self.ProjectNamespace}.Entities.PlatformerAnimationController";
var animationValues = GetAnimationValuesFor(element as GlueElement);

public override ICodeBlock GenerateFields(ICodeBlock codeBlock, IElement element)
if(animationValues != null)
{
var animationValues = GetAnimationValuesFor(element);
codeBlock.Line($"PlatformerAnimationController = new {PlatformerAnimationControllerClassName}(this);");

// This currently assumes not recursive, so it relies on SetByDerived exposing the sprite
var firstSprite = element.AllNamedObjects.FirstOrDefault(item => item.GetAssetTypeInfo() == AvailableAssetTypes.CommonAtis.Sprite);

if(animationValues != null)
if(firstSprite != null)
{
codeBlock.Line($"{PlatformerAnimationControllerClassName} PlatformerAnimationController;");
codeBlock.Line($"PlatformerAnimationController.AnimatedObject = {firstSprite.FieldName};");
}
return codeBlock;
}


public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, IElement element)
{
foreach (var entry in animationValues.Values)
{
codeBlock = codeBlock.Block();
{
string animationSpeedAssignment = $"global::{GlueState.Self.ProjectNamespace}.Entities.AnimationSpeedAssignment.{entry.AnimationSpeedAssignment}";


codeBlock.Line("var configuration = new PlatformerAnimationConfiguration");
codeBlock.Line("{");
var variableAssignmentBlock = codeBlock.CodeBlockIndented();
variableAssignmentBlock.Line($"AnimationName={CodeParser.ConvertValueToCodeString(entry.AnimationName)},");
variableAssignmentBlock.Line($"HasLeftAndRight={CodeParser.ConvertValueToCodeString(entry.HasLeftAndRight)},");
variableAssignmentBlock.Line($"MinXVelocityAbsolute={CodeParser.ConvertValueToCodeString(entry.MinXVelocityAbsolute)},");
variableAssignmentBlock.Line($"MaxXVelocityAbsolute={CodeParser.ConvertValueToCodeString(entry.MaxXVelocityAbsolute)} ,");
variableAssignmentBlock.Line($"MinYVelocity={CodeParser.ConvertValueToCodeString(entry.MinYVelocity)} ,");
variableAssignmentBlock.Line($"MaxYVelocity={CodeParser.ConvertValueToCodeString(entry.MaxYVelocity)} ,");
variableAssignmentBlock.Line($"MinHorizontalInputAbsolute={CodeParser.ConvertValueToCodeString(entry.MinHorizontalInputAbsolute)} ,");
variableAssignmentBlock.Line($"MaxHorizontalInputAbsolute={CodeParser.ConvertValueToCodeString(entry.MaxHorizontalInputAbsolute)} ,");
variableAssignmentBlock.Line($"AbsoluteXVelocityAnimationSpeedMultiplier={CodeParser.ConvertValueToCodeString(entry.AbsoluteXVelocityAnimationSpeedMultiplier)} ,");
variableAssignmentBlock.Line($"AbsoluteYVelocityAnimationSpeedMultiplier={CodeParser.ConvertValueToCodeString(entry.AbsoluteYVelocityAnimationSpeedMultiplier)} ,");
variableAssignmentBlock.Line($"MaxSpeedXRatioMultiplier={CodeParser.ConvertValueToCodeString(entry.MaxSpeedXRatioMultiplier)} ,");
variableAssignmentBlock.Line($"MaxSpeedYRatioMultiplier={CodeParser.ConvertValueToCodeString(entry.MaxSpeedYRatioMultiplier)} ,");
variableAssignmentBlock.Line($"OnGroundRequirement={CodeParser.ConvertValueToCodeString(entry.OnGroundRequirement)} ,");
if(entry.MovementName != "<NULL>")
{
// If it's "<NULL>" that's an option in the CSV parser. Let's keep using it, and just omit any line if it's null which will just use the default fallback of null for strings
variableAssignmentBlock.Line($"MovementName={CodeParser.ConvertValueToCodeString(entry.MovementName)} ,");
}

var animationValues = GetAnimationValuesFor(element);
variableAssignmentBlock.Line($"AnimationSpeedAssignment={animationSpeedAssignment}");

if(animationValues != null)
{
codeBlock.Line($"PlatformerAnimationController = new {PlatformerAnimationControllerClassName}(this);");

// This currently assumes not recursive, so it relies on SetByDerived exposing the sprite
var firstSprite = element.AllNamedObjects.FirstOrDefault(item => item.GetAssetTypeInfo() == AvailableAssetTypes.CommonAtis.Sprite);
codeBlock.Line("};");

if(firstSprite != null)
{
codeBlock.Line($"PlatformerAnimationController.AnimatedObject = {firstSprite.FieldName};");
}
codeBlock.Line("PlatformerAnimationController.AddLayer(configuration);");

foreach (var entry in animationValues.Values)
{
codeBlock = codeBlock.Block();
if(!string.IsNullOrWhiteSpace( entry.CustomCondition ))
{
string animationSpeedAssignment = $"global::{GlueState.Self.ProjectNamespace}.Entities.AnimationSpeedAssignment.{entry.AnimationSpeedAssignment}";


codeBlock.Line("var configuration = new PlatformerAnimationConfiguration");
codeBlock.Line("{");
var variableAssignmentBlock = codeBlock.CodeBlockIndented();
variableAssignmentBlock.Line($"AnimationName={CodeParser.ConvertValueToCodeString(entry.AnimationName)},");
variableAssignmentBlock.Line($"HasLeftAndRight={CodeParser.ConvertValueToCodeString(entry.HasLeftAndRight)},");
variableAssignmentBlock.Line($"MinXVelocityAbsolute={CodeParser.ConvertValueToCodeString(entry.MinXVelocityAbsolute)},");
variableAssignmentBlock.Line($"MaxXVelocityAbsolute={CodeParser.ConvertValueToCodeString(entry.MaxXVelocityAbsolute)} ,");
variableAssignmentBlock.Line($"MinYVelocity={CodeParser.ConvertValueToCodeString(entry.MinYVelocity)} ,");
variableAssignmentBlock.Line($"MaxYVelocity={CodeParser.ConvertValueToCodeString(entry.MaxYVelocity)} ,");
variableAssignmentBlock.Line($"MinHorizontalInputAbsolute={CodeParser.ConvertValueToCodeString(entry.MinHorizontalInputAbsolute)} ,");
variableAssignmentBlock.Line($"MaxHorizontalInputAbsolute={CodeParser.ConvertValueToCodeString(entry.MaxHorizontalInputAbsolute)} ,");
variableAssignmentBlock.Line($"AbsoluteXVelocityAnimationSpeedMultiplier={CodeParser.ConvertValueToCodeString(entry.AbsoluteXVelocityAnimationSpeedMultiplier)} ,");
variableAssignmentBlock.Line($"AbsoluteYVelocityAnimationSpeedMultiplier={CodeParser.ConvertValueToCodeString(entry.AbsoluteYVelocityAnimationSpeedMultiplier)} ,");
variableAssignmentBlock.Line($"MaxSpeedXRatioMultiplier={CodeParser.ConvertValueToCodeString(entry.MaxSpeedXRatioMultiplier)} ,");
variableAssignmentBlock.Line($"MaxSpeedYRatioMultiplier={CodeParser.ConvertValueToCodeString(entry.MaxSpeedYRatioMultiplier)} ,");
variableAssignmentBlock.Line($"OnGroundRequirement={CodeParser.ConvertValueToCodeString(entry.OnGroundRequirement)} ,");
if(entry.MovementName != "<NULL>")
{
// If it's "<NULL>" that's an option in the CSV parser. Let's keep using it, and just omit any line if it's null which will just use the default fallback of null for strings
variableAssignmentBlock.Line($"MovementName={CodeParser.ConvertValueToCodeString(entry.MovementName)} ,");
}

variableAssignmentBlock.Line($"AnimationSpeedAssignment={animationSpeedAssignment}");


codeBlock.Line("};");

codeBlock.Line("PlatformerAnimationController.AddLayer(configuration);");

if(!string.IsNullOrWhiteSpace( entry.CustomCondition ))
{
codeBlock.Line($"configuration.AdditionalPredicate += () => {entry.CustomCondition};");
}
codeBlock.Line($"configuration.AdditionalPredicate += () => {entry.CustomCondition};");
}
codeBlock = codeBlock.End();
}
codeBlock = codeBlock.End();
}

return codeBlock;
}

public override ICodeBlock GenerateActivity(ICodeBlock codeBlock, IElement element)
{
var animationValues = GetAnimationValuesFor(element);
return codeBlock;
}

if(animationValues != null)
{
codeBlock.Line("PlatformerAnimationController.Activity();");
}
public override ICodeBlock GenerateActivity(ICodeBlock codeBlock, IElement element)
{
var animationValues = GetAnimationValuesFor(element as GlueElement);

return codeBlock;
if(animationValues != null)
{
codeBlock.Line("PlatformerAnimationController.Activity();");
}

return codeBlock;
}
}
Loading

0 comments on commit 0037022

Please sign in to comment.