mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
ZoneCodeGenerator: Make unions work with conditions and only load one union member at a time consistently
This commit is contained in:
parent
f4a2639e30
commit
9253ac14fa
@ -1,29 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain.Evaluation;
|
||||
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||
using ZoneCodeGenerator.Generating.Computations;
|
||||
|
||||
namespace ZoneCodeGenerator.Domain.Information
|
||||
{
|
||||
class MemberInformation
|
||||
{
|
||||
public StructureInformation Parent { get; }
|
||||
public StructureInformation StructureType { get; }
|
||||
public Variable Member { get; set; }
|
||||
public bool IsString { get; set; }
|
||||
public bool IsScriptString { get; set; }
|
||||
public bool IsReusable { get; set; }
|
||||
public bool IsLeaf { get; set; }
|
||||
public IEvaluation Condition { get; set; }
|
||||
public FastFileBlock Block { get; set; }
|
||||
|
||||
public MemberComputations Computations => new MemberComputations(this);
|
||||
|
||||
public MemberInformation(Variable member, StructureInformation structureType)
|
||||
public MemberInformation(StructureInformation parent, Variable member, StructureInformation structureType)
|
||||
{
|
||||
Parent = parent;
|
||||
Member = member;
|
||||
StructureType = structureType;
|
||||
IsString = false;
|
||||
IsScriptString = false;
|
||||
IsReusable = false;
|
||||
IsLeaf = false;
|
||||
Condition = null;
|
||||
Block = null;
|
||||
}
|
||||
|
@ -73,6 +73,12 @@ namespace ZoneCodeGenerator.Generating.Computations
|
||||
public bool IsNotDefaultNormalBlock =>
|
||||
information.Block != null && !(information.Block.IsNormal && information.Block.IsDefault);
|
||||
|
||||
public bool IsFirstMember =>
|
||||
information.Parent.OrderedMembers.FirstOrDefault(member => !member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
||||
|
||||
public bool IsLastMember =>
|
||||
information.Parent.OrderedMembers.LastOrDefault(member => !member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
||||
|
||||
public MemberReferenceComputations References => new MemberReferenceComputations(information);
|
||||
|
||||
public MemberComputations(MemberInformation information)
|
||||
|
@ -79,35 +79,86 @@ Loading member $member.Member.Name$
|
||||
|
||||
LoadMemberReference(context, structure, member, reference) ::= <%
|
||||
$if(reference.IsSinglePointer)$
|
||||
$\n$$\n$
|
||||
$LoadSinglePointer(context, structure, member, reference)$
|
||||
$elseif(reference.IsArrayPointer)$
|
||||
$\n$$\n$
|
||||
$LoadArrayPointer(context, structure, member, reference)$
|
||||
$elseif(reference.IsPointerArray)$
|
||||
$\n$$\n$
|
||||
$LoadPointerArray(context, structure, member, reference)$
|
||||
$elseif(reference.IsArray && !reference.NextReference)$
|
||||
$\n$$\n$
|
||||
$LoadEmbeddedArray(context, structure, member, reference)$
|
||||
$elseif(!reference.Reference)$
|
||||
$\n$$\n$
|
||||
$LoadEmbedded(context, structure, member, reference)$
|
||||
$else$
|
||||
$\n$$\n$
|
||||
// $member.Member.Name$
|
||||
$endif$
|
||||
%>
|
||||
|
||||
LoadMemberCondition_Struct(context, structure, member) ::= <<
|
||||
|
||||
|
||||
$if(member.Condition)$
|
||||
if($PrintEvaluation(member.Condition)$)
|
||||
{
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
}$\\$
|
||||
$else$
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$$\\$
|
||||
$endif$
|
||||
>>
|
||||
|
||||
LoadMemberCondition_Union(context, structure, member) ::= <<
|
||||
$if(member.Computations.IsFirstMember)$$\\$
|
||||
$if(member.Condition)$
|
||||
|
||||
if($PrintEvaluation(member.Condition)$)
|
||||
{
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
}$\\$
|
||||
$else$
|
||||
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$$\\$
|
||||
$endif$$\\$
|
||||
$elseif(member.Computations.IsLastMember)$$\\$
|
||||
$if(member.Condition)$
|
||||
else if($PrintEvaluation(member.Condition)$)
|
||||
{
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
}$\\$
|
||||
$else$
|
||||
else
|
||||
{
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
}$\\$
|
||||
$endif$$\\$
|
||||
$else$$\\$
|
||||
$if(member.Condition)$
|
||||
else if($PrintEvaluation(member.Condition)$)
|
||||
{
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
}$\\$
|
||||
$else$$\\$
|
||||
#error Middle member of union must have condition ($member.Member.Name$)
|
||||
$endif$$\\$
|
||||
$endif$
|
||||
>>
|
||||
|
||||
LoadMemberCondition(context, structure, member) ::= <%
|
||||
$if(structure.IsUnion)$
|
||||
$LoadMemberCondition_Union(context, structure, member)$
|
||||
$else$
|
||||
$LoadMemberCondition_Struct(context, structure, member)$
|
||||
$endif$
|
||||
%>
|
||||
|
||||
LoadMemberIfNeedsTreatment(context, structure, member) ::= <%
|
||||
$if(!member.Computations.ShouldIgnore)$
|
||||
|
||||
$if(member.IsString || member.IsScriptString)$
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
$LoadMemberCondition(context, structure, member)$
|
||||
$elseif(member.Computations.ContainsNonEmbeddedReference)$
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
$LoadMemberCondition(context, structure, member)$
|
||||
$elseif(member.StructureType && !member.StructureType.IsLeaf)$
|
||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
||||
$LoadMemberCondition(context, structure, member)$
|
||||
$endif$
|
||||
|
||||
$endif$
|
||||
|
@ -14,7 +14,9 @@ namespace ZoneCodeGenerator.Parsing.CommandFile
|
||||
private static readonly IDataPostProcessor[] postProcessors =
|
||||
{
|
||||
new PostProcessorUsages(),
|
||||
new PostProcessorLeafs()
|
||||
new PostProcessorLeafs(),
|
||||
new PostProcessorMemberLeafs(),
|
||||
new PostProcessorUnions(),
|
||||
};
|
||||
|
||||
public static bool ReadFile(string path, CUISession session, bool verbose = false)
|
||||
|
@ -7,7 +7,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
||||
{
|
||||
class PostProcessorLeafs : IDataPostProcessor
|
||||
{
|
||||
private static bool IsLeaf(StructureInformation structureInformation)
|
||||
public static bool IsLeaf(StructureInformation structureInformation)
|
||||
{
|
||||
foreach (var member in structureInformation.OrderedMembers)
|
||||
{
|
||||
|
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.Information;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
||||
{
|
||||
class PostProcessorMemberLeafs : IDataPostProcessor
|
||||
{
|
||||
private static bool MemberIsLeaf(MemberInformation member)
|
||||
{
|
||||
if (member.IsString || member.IsScriptString)
|
||||
return false;
|
||||
|
||||
if (member.StructureType != null && !member.StructureType.IsLeaf)
|
||||
return false;
|
||||
|
||||
// If there are any Pointer members that are not always count 0 it needs to be processed.
|
||||
var hasNoPointerMembers = member.Member.VariableType.References.OfType<ReferenceTypePointer>().All(pointer =>
|
||||
{
|
||||
if (!pointer.Count.IsStatic)
|
||||
return false;
|
||||
|
||||
return pointer.Count.EvaluateNumeric() == 0;
|
||||
});
|
||||
|
||||
if (!hasNoPointerMembers)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ProcessStructureInformation(StructureInformation structure)
|
||||
{
|
||||
foreach (var member in structure.OrderedMembers)
|
||||
{
|
||||
member.IsLeaf = MemberIsLeaf(member);
|
||||
}
|
||||
}
|
||||
|
||||
public bool PostProcess(IDataRepository repository)
|
||||
{
|
||||
foreach (var structure in repository.GetAllStructs()
|
||||
.Cast<DataTypeWithMembers>()
|
||||
.Concat(repository.GetAllUnions())
|
||||
.Select(repository.GetInformationFor))
|
||||
{
|
||||
ProcessStructureInformation(structure);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ZoneCodeGenerator.Domain;
|
||||
using ZoneCodeGenerator.Domain.Information;
|
||||
using ZoneCodeGenerator.Persistence;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
||||
{
|
||||
class PostProcessorUnions : IDataPostProcessor
|
||||
{
|
||||
private static bool ProcessUnion(StructureInformation unionInformation)
|
||||
{
|
||||
var entriesWithoutConditionCount =
|
||||
unionInformation.OrderedMembers.Count(member => member.Condition == null && !member.IsLeaf);
|
||||
|
||||
if (entriesWithoutConditionCount > 1 && unionInformation.Usages.Any() && !unionInformation.IsLeaf)
|
||||
{
|
||||
Console.WriteLine($"Union '{unionInformation.Type.FullName}' has more than one entry without a condition!");
|
||||
return false;
|
||||
}
|
||||
else if (entriesWithoutConditionCount == 1)
|
||||
{
|
||||
// If there is only one entry without condition make it the last of the ordered members
|
||||
var entryWithoutCondition = unionInformation.OrderedMembers.First(information => information.Condition == null);
|
||||
|
||||
unionInformation.OrderedMembers.Remove(entryWithoutCondition);
|
||||
unionInformation.OrderedMembers.Insert(unionInformation.OrderedMembers.Count, entryWithoutCondition);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PostProcess(IDataRepository repository)
|
||||
{
|
||||
return repository.GetAllUnions()
|
||||
.Select(repository.GetInformationFor)
|
||||
.All(ProcessUnion);
|
||||
}
|
||||
}
|
||||
}
|
@ -124,7 +124,7 @@ namespace ZoneCodeGenerator.Persistence
|
||||
memberStructureInformation = GetInformationFor(memberType);
|
||||
}
|
||||
|
||||
information.OrderedMembers.Add(new MemberInformation(member, memberStructureInformation));
|
||||
information.OrderedMembers.Add(new MemberInformation(information, member, memberStructureInformation));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4619,11 +4619,9 @@ union FxElemDefVisuals
|
||||
|
||||
union FxElemExtendedDefPtr
|
||||
{
|
||||
FxTrailDef *localTrailDef;
|
||||
FxTrailDef *trailDef;
|
||||
FxSpotLightDef *localSpotLightDef;
|
||||
FxSpotLightDef *spotLightDef;
|
||||
void *unknownDef;
|
||||
char *unknownDef;
|
||||
};
|
||||
|
||||
struct FxBillboardTrim
|
||||
@ -4643,6 +4641,26 @@ struct FxElemSpawnSound
|
||||
const char *spawnSound;
|
||||
};
|
||||
|
||||
enum FxElemType : char
|
||||
{
|
||||
FX_ELEM_TYPE_SPRITE_BILLBOARD = 0x0,
|
||||
FX_ELEM_TYPE_SPRITE_ORIENTED = 0x1,
|
||||
FX_ELEM_TYPE_SPRITE_ROTATED = 0x2,
|
||||
FX_ELEM_TYPE_TAIL = 0x3,
|
||||
FX_ELEM_TYPE_LINE = 0x4,
|
||||
FX_ELEM_TYPE_TRAIL = 0x5,
|
||||
FX_ELEM_TYPE_CLOUD = 0x6,
|
||||
FX_ELEM_TYPE_MODEL = 0x7,
|
||||
FX_ELEM_TYPE_OMNI_LIGHT = 0x8,
|
||||
FX_ELEM_TYPE_SPOT_LIGHT = 0x9,
|
||||
FX_ELEM_TYPE_SOUND = 0xA,
|
||||
FX_ELEM_TYPE_DECAL = 0xB,
|
||||
FX_ELEM_TYPE_RUNNER = 0xC,
|
||||
FX_ELEM_TYPE_COUNT = 0xD,
|
||||
FX_ELEM_TYPE_LAST_SPRITE = 0x5,
|
||||
FX_ELEM_TYPE_LAST_DRAWN = 0x9,
|
||||
};
|
||||
|
||||
const struct FxElemDef
|
||||
{
|
||||
int flags;
|
||||
@ -4664,7 +4682,7 @@ const struct FxElemDef
|
||||
FxFloatRange reflectionFactor;
|
||||
FxElemAtlas atlas;
|
||||
float windInfluence;
|
||||
char elemType;
|
||||
FxElemType elemType;
|
||||
char visualCount;
|
||||
char velIntervalCount;
|
||||
char visStateIntervalCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user