Head Accessories AutoGen Configuration

This commit is contained in:
2026-04-25 07:40:17 +02:00
parent 831d3b47da
commit b6fff4bed4
6 changed files with 1010 additions and 10 deletions
+196
View File
@@ -5479,6 +5479,121 @@ with open(os.path.join(tlk, "sow_tlk.tlk"), "wb") as f:
}
}
func TestApplyAutogenConsumersAugmentsPartsFromLocalOverride(t *testing.T) {
root := testProjectRoot(t)
overrideRoot := filepath.Join(root, "autogen-assets")
mkdirAll(t, filepath.Join(overrideRoot, "part", "belt"))
writeFile(t, filepath.Join(overrideRoot, "part", "belt", "pfa0_belt018.mdl"), "mdl\n")
p := testProject(root)
p.Config.Autogen.Consumers = []project.AutogenConsumerConfig{
{
ID: "parts",
Producer: "parts",
Dataset: "parts",
Mode: "parts_rows",
Root: "part",
Include: []string{"**/*.mdl"},
Derive: project.AutogenDeriveConfig{Kind: "trailing_numeric_suffix", GroupFrom: "first_path_segment"},
Manifest: project.AutogenManifestConfig{ReleaseTag: "parts-manifest-current", AssetName: "sow-parts-manifest.json", CacheName: "sow-parts-manifest.json"},
LocalOverrideRoot: "autogen-assets",
},
}
collected := []nativeCollectedDataset{
{
Dataset: nativeDataset{Name: "parts/belt"},
Columns: []string{"COSTMODIFIER", "ACBONUS"},
Rows: []map[string]any{
{"id": 0, "COSTMODIFIER": "0", "ACBONUS": "0.00"},
},
},
}
got, err := applyAutogenConsumers(p, collected, nil)
if err != nil {
t.Fatalf("applyAutogenConsumers failed: %v", err)
}
if len(got) != 1 || len(got[0].Rows) != 2 {
t.Fatalf("expected autogenerated part row, got %#v", got)
}
row := got[0].Rows[1]
if row["id"] != 18 || row["COSTMODIFIER"] != "0" || row["ACBONUS"] != "0.00" {
t.Fatalf("unexpected autogenerated part row: %#v", row)
}
}
func TestApplyAutogenConsumersAugmentsHeadVisualeffectsFromLocalOverride(t *testing.T) {
root := testProjectRoot(t)
overrideRoot := filepath.Join(root, "autogen-assets")
mkdirAll(t, filepath.Join(overrideRoot, "vfxs", "head_accessories"))
mkdirAll(t, filepath.Join(overrideRoot, "vfxs", "head_features", "hair"))
writeFile(t, filepath.Join(overrideRoot, "vfxs", "head_accessories", "hfx_bandana.mdl"), "mdl\n")
writeFile(t, filepath.Join(overrideRoot, "vfxs", "head_features", "hair", "hfx_hair_bangs.mdl"), "mdl\n")
p := testProject(root)
p.Config.Autogen.Consumers = []project.AutogenConsumerConfig{
{
ID: "head_visualeffects",
Producer: "head_visualeffects",
Dataset: "visualeffects",
Mode: "head_visualeffects",
Root: "vfxs",
Include: []string{"head_accessories/**/*.mdl", "head_features/**/*.mdl"},
Derive: project.AutogenDeriveConfig{Kind: "model_stem", GroupFrom: "first_path_segment"},
Manifest: project.AutogenManifestConfig{ReleaseTag: "head-vfx-manifest-current", AssetName: "sow-head-vfx-manifest.json", CacheName: "sow-head-vfx-manifest.json"},
LocalOverrideRoot: "autogen-assets",
},
}
collected := []nativeCollectedDataset{
{
Dataset: nativeDataset{Name: "visualeffects", Kind: nativeDatasetBase},
Columns: []string{"Label", "Type_FD", "OrientWithGround", "Imp_HeadCon_Node", "OrientWithObject"},
Rows: nil,
LockData: map[string]int{
"visualeffects:existing": 17,
},
},
}
got, err := applyAutogenConsumers(p, collected, nil)
if err != nil {
t.Fatalf("applyAutogenConsumers failed: %v", err)
}
if len(got) != 1 || len(got[0].Rows) != 2 {
t.Fatalf("expected autogenerated visualeffects rows, got %#v", got)
}
rowByKey := map[string]map[string]any{}
for _, row := range got[0].Rows {
rowByKey[row["key"].(string)] = row
}
bandana := rowByKey["visualeffects:headaccessory_bandana"]
if bandana == nil {
t.Fatalf("expected head accessory row, got %#v", got[0].Rows)
}
if bandana["Label"] != "headaccessory_BANDANA" || bandana["Imp_HeadCon_Node"] != "hfx_bandana" || bandana["OrientWithObject"] != "1" {
t.Fatalf("unexpected head accessory defaults: %#v", bandana)
}
hair := rowByKey["visualeffects:headfeature_hair_bangs"]
if hair == nil {
t.Fatalf("expected head feature row, got %#v", got[0].Rows)
}
if hair["Label"] != "headfeature_HAIR_BANGS" || hair["Imp_HeadCon_Node"] != "hfx_hair_bangs" || hair["Type_FD"] != "D" {
t.Fatalf("unexpected head feature defaults: %#v", hair)
}
if _, ok := got[0].LockData["visualeffects:headaccessory_bandana"]; !ok {
t.Fatalf("expected head accessory lock id, got %#v", got[0].LockData)
}
if _, ok := got[0].LockData["visualeffects:headfeature_hair_bangs"]; !ok {
t.Fatalf("expected head feature lock id, got %#v", got[0].LockData)
}
}
func TestNormalizeProjectImportsLegacyLoadscreens(t *testing.T) {
root := testProjectRoot(t)
mkdirAll(t, filepath.Join(root, "topdata", "data"))
@@ -9028,6 +9143,27 @@ func TestBuildNativeWithReleasedPartsManifest(t *testing.T) {
Source: "topdata",
Build: "build/topdata",
},
Autogen: project.AutogenConfig{
Consumers: []project.AutogenConsumerConfig{
{
ID: "parts",
Producer: "parts",
Dataset: "parts",
Mode: "parts_rows",
Root: "part",
Include: []string{"**/*.mdl"},
Derive: project.AutogenDeriveConfig{
Kind: "trailing_numeric_suffix",
GroupFrom: "first_path_segment",
},
Manifest: project.AutogenManifestConfig{
ReleaseTag: "parts-manifest-current",
AssetName: "sow-parts-manifest.json",
CacheName: "sow-parts-manifest.json",
},
},
},
},
},
}
@@ -9105,6 +9241,27 @@ func TestBuildNativeFailsWhenReleasedPartsManifestUnavailable(t *testing.T) {
Source: "topdata",
Build: "build/topdata",
},
Autogen: project.AutogenConfig{
Consumers: []project.AutogenConsumerConfig{
{
ID: "parts",
Producer: "parts",
Dataset: "parts",
Mode: "parts_rows",
Root: "part",
Include: []string{"**/*.mdl"},
Derive: project.AutogenDeriveConfig{
Kind: "trailing_numeric_suffix",
GroupFrom: "first_path_segment",
},
Manifest: project.AutogenManifestConfig{
ReleaseTag: "parts-manifest-current",
AssetName: "sow-parts-manifest.json",
CacheName: "sow-parts-manifest.json",
},
},
},
},
},
}
@@ -9564,6 +9721,45 @@ func testProject(root string) *project.Project {
ReferenceBuilder: "reference",
Assets: ".",
},
Autogen: project.AutogenConfig{
Consumers: []project.AutogenConsumerConfig{
{
ID: "parts",
Producer: "parts",
Dataset: "parts",
Mode: "parts_rows",
Root: "part",
Include: []string{"**/*.mdl"},
Derive: project.AutogenDeriveConfig{
Kind: "trailing_numeric_suffix",
GroupFrom: "first_path_segment",
},
Manifest: project.AutogenManifestConfig{
ReleaseTag: "parts-manifest-current",
AssetName: "sow-parts-manifest.json",
CacheName: "sow-parts-manifest.json",
},
},
{
ID: "head_visualeffects",
Producer: "head_visualeffects",
Dataset: "visualeffects",
Mode: "head_visualeffects",
Optional: true,
Root: "vfxs",
Include: []string{"head_accessories/**/*.mdl", "head_features/**/*.mdl"},
Derive: project.AutogenDeriveConfig{
Kind: "model_stem",
GroupFrom: "first_path_segment",
},
Manifest: project.AutogenManifestConfig{
ReleaseTag: "head-vfx-manifest-current",
AssetName: "sow-head-vfx-manifest.json",
CacheName: "sow-head-vfx-manifest.json",
},
},
},
},
},
}
}