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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ZoneCodeGenerator.Domain.Evaluation;
|
using ZoneCodeGenerator.Domain.Evaluation;
|
||||||
|
using ZoneCodeGenerator.Domain.FastFileStructure;
|
||||||
using ZoneCodeGenerator.Generating.Computations;
|
using ZoneCodeGenerator.Generating.Computations;
|
||||||
|
|
||||||
namespace ZoneCodeGenerator.Domain.Information
|
namespace ZoneCodeGenerator.Domain.Information
|
||||||
{
|
{
|
||||||
class MemberInformation
|
class MemberInformation
|
||||||
{
|
{
|
||||||
|
public StructureInformation Parent { get; }
|
||||||
public StructureInformation StructureType { get; }
|
public StructureInformation StructureType { get; }
|
||||||
public Variable Member { get; set; }
|
public Variable Member { get; set; }
|
||||||
public bool IsString { get; set; }
|
public bool IsString { get; set; }
|
||||||
public bool IsScriptString { get; set; }
|
public bool IsScriptString { get; set; }
|
||||||
public bool IsReusable { get; set; }
|
public bool IsReusable { get; set; }
|
||||||
|
public bool IsLeaf { get; set; }
|
||||||
public IEvaluation Condition { get; set; }
|
public IEvaluation Condition { get; set; }
|
||||||
public FastFileBlock Block { get; set; }
|
public FastFileBlock Block { get; set; }
|
||||||
|
|
||||||
public MemberComputations Computations => new MemberComputations(this);
|
public MemberComputations Computations => new MemberComputations(this);
|
||||||
|
|
||||||
public MemberInformation(Variable member, StructureInformation structureType)
|
public MemberInformation(StructureInformation parent, Variable member, StructureInformation structureType)
|
||||||
{
|
{
|
||||||
|
Parent = parent;
|
||||||
Member = member;
|
Member = member;
|
||||||
StructureType = structureType;
|
StructureType = structureType;
|
||||||
IsString = false;
|
IsString = false;
|
||||||
IsScriptString = false;
|
IsScriptString = false;
|
||||||
IsReusable = false;
|
IsReusable = false;
|
||||||
|
IsLeaf = false;
|
||||||
Condition = null;
|
Condition = null;
|
||||||
Block = null;
|
Block = null;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,12 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
public bool IsNotDefaultNormalBlock =>
|
public bool IsNotDefaultNormalBlock =>
|
||||||
information.Block != null && !(information.Block.IsNormal && information.Block.IsDefault);
|
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 MemberReferenceComputations References => new MemberReferenceComputations(information);
|
||||||
|
|
||||||
public MemberComputations(MemberInformation information)
|
public MemberComputations(MemberInformation information)
|
||||||
|
@ -79,35 +79,86 @@ Loading member $member.Member.Name$
|
|||||||
|
|
||||||
LoadMemberReference(context, structure, member, reference) ::= <%
|
LoadMemberReference(context, structure, member, reference) ::= <%
|
||||||
$if(reference.IsSinglePointer)$
|
$if(reference.IsSinglePointer)$
|
||||||
$\n$$\n$
|
|
||||||
$LoadSinglePointer(context, structure, member, reference)$
|
$LoadSinglePointer(context, structure, member, reference)$
|
||||||
$elseif(reference.IsArrayPointer)$
|
$elseif(reference.IsArrayPointer)$
|
||||||
$\n$$\n$
|
|
||||||
$LoadArrayPointer(context, structure, member, reference)$
|
$LoadArrayPointer(context, structure, member, reference)$
|
||||||
$elseif(reference.IsPointerArray)$
|
$elseif(reference.IsPointerArray)$
|
||||||
$\n$$\n$
|
|
||||||
$LoadPointerArray(context, structure, member, reference)$
|
$LoadPointerArray(context, structure, member, reference)$
|
||||||
$elseif(reference.IsArray && !reference.NextReference)$
|
$elseif(reference.IsArray && !reference.NextReference)$
|
||||||
$\n$$\n$
|
|
||||||
$LoadEmbeddedArray(context, structure, member, reference)$
|
$LoadEmbeddedArray(context, structure, member, reference)$
|
||||||
$elseif(!reference.Reference)$
|
$elseif(!reference.Reference)$
|
||||||
$\n$$\n$
|
|
||||||
$LoadEmbedded(context, structure, member, reference)$
|
$LoadEmbedded(context, structure, member, reference)$
|
||||||
$else$
|
$else$
|
||||||
$\n$$\n$
|
|
||||||
// $member.Member.Name$
|
// $member.Member.Name$
|
||||||
$endif$
|
$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) ::= <%
|
LoadMemberIfNeedsTreatment(context, structure, member) ::= <%
|
||||||
$if(!member.Computations.ShouldIgnore)$
|
$if(!member.Computations.ShouldIgnore)$
|
||||||
|
|
||||||
$if(member.IsString || member.IsScriptString)$
|
$if(member.IsString || member.IsScriptString)$
|
||||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
$LoadMemberCondition(context, structure, member)$
|
||||||
$elseif(member.Computations.ContainsNonEmbeddedReference)$
|
$elseif(member.Computations.ContainsNonEmbeddedReference)$
|
||||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
$LoadMemberCondition(context, structure, member)$
|
||||||
$elseif(member.StructureType && !member.StructureType.IsLeaf)$
|
$elseif(member.StructureType && !member.StructureType.IsLeaf)$
|
||||||
$LoadMemberReference(context, structure, member, member.Computations.References)$
|
$LoadMemberCondition(context, structure, member)$
|
||||||
$endif$
|
$endif$
|
||||||
|
|
||||||
$endif$
|
$endif$
|
||||||
|
@ -14,7 +14,9 @@ namespace ZoneCodeGenerator.Parsing.CommandFile
|
|||||||
private static readonly IDataPostProcessor[] postProcessors =
|
private static readonly IDataPostProcessor[] postProcessors =
|
||||||
{
|
{
|
||||||
new PostProcessorUsages(),
|
new PostProcessorUsages(),
|
||||||
new PostProcessorLeafs()
|
new PostProcessorLeafs(),
|
||||||
|
new PostProcessorMemberLeafs(),
|
||||||
|
new PostProcessorUnions(),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static bool ReadFile(string path, CUISession session, bool verbose = false)
|
public static bool ReadFile(string path, CUISession session, bool verbose = false)
|
||||||
|
@ -7,7 +7,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
|||||||
{
|
{
|
||||||
class PostProcessorLeafs : IDataPostProcessor
|
class PostProcessorLeafs : IDataPostProcessor
|
||||||
{
|
{
|
||||||
private static bool IsLeaf(StructureInformation structureInformation)
|
public static bool IsLeaf(StructureInformation structureInformation)
|
||||||
{
|
{
|
||||||
foreach (var member in structureInformation.OrderedMembers)
|
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);
|
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
|
union FxElemExtendedDefPtr
|
||||||
{
|
{
|
||||||
FxTrailDef *localTrailDef;
|
|
||||||
FxTrailDef *trailDef;
|
FxTrailDef *trailDef;
|
||||||
FxSpotLightDef *localSpotLightDef;
|
|
||||||
FxSpotLightDef *spotLightDef;
|
FxSpotLightDef *spotLightDef;
|
||||||
void *unknownDef;
|
char *unknownDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FxBillboardTrim
|
struct FxBillboardTrim
|
||||||
@ -4643,6 +4641,26 @@ struct FxElemSpawnSound
|
|||||||
const char *spawnSound;
|
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
|
const struct FxElemDef
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
@ -4664,7 +4682,7 @@ const struct FxElemDef
|
|||||||
FxFloatRange reflectionFactor;
|
FxFloatRange reflectionFactor;
|
||||||
FxElemAtlas atlas;
|
FxElemAtlas atlas;
|
||||||
float windInfluence;
|
float windInfluence;
|
||||||
char elemType;
|
FxElemType elemType;
|
||||||
char visualCount;
|
char visualCount;
|
||||||
char velIntervalCount;
|
char velIntervalCount;
|
||||||
char visStateIntervalCount;
|
char visStateIntervalCount;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user