• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MeltyPlayer / MeltyTool / 23082208225

14 Mar 2026 06:19AM UTC coverage: 41.449%. Remained the same
23082208225

push

github

MeltyPlayer
Update ScbModelImporter.cs

7010 of 18991 branches covered (36.91%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 1 file covered. (0.0%)

29943 of 70162 relevant lines covered (42.68%)

62225.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/FinModelUtility/Games/TheLabyrinthPlusEdition/TheLabyrinthPlusEdition/src/api/ScbModelImporter.cs
1
using System.Numerics;
2

3
using fin.data.dictionaries;
4
using fin.io;
5
using fin.model;
6
using fin.model.impl;
7
using fin.model.io;
8
using fin.model.io.importers;
9
using fin.model.util;
10
using fin.util.sets;
11
using fin.util.strings;
12

13
using schema.text.reader;
14

15
using tlpe.scb;
16

17
namespace tlpe.api;
18

19
public sealed record ScbModelFileBundle(
×
20
    IReadOnlyTreeFile ScbFile,
×
21
    IReadOnlyTreeFile BallsFile,
×
22
    IReadOnlyTreeDirectory TexturesDir)
×
23
    : IModelFileBundle {
24
  public IReadOnlyTreeFile MainFile => this.ScbFile;
×
25
}
26

27
public sealed class ScbModelImporter : IModelImporter<ScbModelFileBundle> {
28
  public IModel Import(ScbModelFileBundle fileBundle) {
×
29
    var scb = fileBundle.ScbFile.ReadNew<Scb>();
×
30

31
    var files = fileBundle.ScbFile.AsFileSet();
×
32
    var finModel = new ModelImpl {
×
33
        FileBundle = fileBundle,
×
34
        Files = files
×
35
    };
×
36

37
    var allBallAttributes = ReadAllBallAttributes_(fileBundle.BallsFile);
×
38
    var ballAttributesByGeometry
×
39
        = allBallAttributes
×
40
          .Where(a => a.Geometry != null)
×
41
          .ToListDictionary(a => a.Geometry!.ToLower());
×
42

43
    var textureFiles = new List<IReadOnlyTreeFile>();
×
44
    if (ballAttributesByGeometry.TryGetList(
×
45
            fileBundle.ScbFile.Name.ToString().ToLower(),
×
46
            out var matchingBallAttributes)) {
×
47
      foreach (var ballAttributes in matchingBallAttributes) {
×
48
        if (ballAttributes.Texture != null) {
×
49
          var textureFile = fileBundle.TexturesDir.AssertGetExistingFile(
×
50
              ballAttributes.Texture);
×
51
          textureFiles.Add(textureFile);
×
52
        }
×
53
      }
×
54
    }
×
55

56
    foreach (var scbSection in scb.Sections) {
×
57
      if (scbSection is Section6 section6) {
×
58
        var textureName = section6.Names.Name1;
×
59
        if (textureName.Length > 0) {
×
60
          var textureFile = fileBundle.ScbFile.AssertGetParent()
×
61
                                      .AssertGetExistingFile(textureName);
×
62
          textureFiles.Add(textureFile);
×
63
        }
×
64
      }
×
65
    }
×
66

67
    IMaterial[] textureMaterials
×
68
        = textureFiles
×
69
          .Select(textureFile => {
×
70
            (var finMaterial, _)
×
71
                = finModel.MaterialManager.AddSimpleTextureMaterialFromFile(
×
72
                    textureFile);
×
73
            return finMaterial;
×
74
          })
×
75
          .ToArray();
×
76

77
    var finMaterial = textureMaterials.Length > 0
×
78
        ? textureMaterials[0]
×
79
        : finModel.MaterialManager.AddNullMaterial();
×
80

81
    var finSkin = finModel.Skin;
×
82

83
    foreach (var scbSection in scb.Sections) {
×
84
      switch (scbSection) {
×
85
        case MeshSection meshSection: {
×
86
          var finMesh = finSkin.AddMesh();
×
87

88
          var scbVertices = meshSection.Vertices;
×
89
          var finVertices = new IReadOnlyVertex[scbVertices.Length];
×
90
          for (var i = 0; i < scbVertices.Length; ++i) {
×
91
            var scbVertex = scbVertices[i];
×
92

93
            var finVertex = finSkin.AddVertex(AdjustVector3_(scbVertex.Position));
×
94
            finVertex.SetLocalNormal(AdjustVector3_(scbVertex.Normal));
×
NEW
95
            finVertex.SetUv(0, AdjustVector2_(scbVertex.Uv0));
×
NEW
96
            finVertex.SetUv(1, AdjustVector2_(scbVertex.Uv1));
×
97

98
            finVertices[scbVertices.Length - 1 - i] = finVertex;
×
99
          }
×
100

101
          var triangles
×
102
              = meshSection
×
103
                .Faces.Select(f => {
×
104
                  var v0 = finVertices[f.Vertex0];
×
105
                  var v1 = finVertices[f.Vertex1];
×
106
                  var v2 = finVertices[f.Vertex2];
×
107

×
108
                  return (v0, v1, v2);
×
109
                })
×
110
                .ToArray();
×
111

112
          var finPrimitive = finMesh.AddTriangles(triangles);
×
113
          finPrimitive.SetMaterial(finMaterial);
×
114

115
          break;
×
116
        }
117
      }
118
    }
×
119

120
    return finModel;
×
121
  }
×
122

123
  private class BallAttributes {
124
    public string Id { get; set; }
×
125
    public string? Geometry { get; set; }
×
126
    public string? Texture { get; set; }
×
127
    public bool MapFromFile { get; set; }
×
128
    public bool NoEnvMap { get; set; }
×
129
  }
130

131
  private static Vector2 AdjustVector2_(Vector2 input)
NEW
132
    => input with { Y = 1 - input.Y };
×
133

134
  private static Vector3 AdjustVector3_(Vector3 input)
135
    => new(input.X, input.Z, input.Y);
×
136

137
  private static IList<BallAttributes> ReadAllBallAttributes_(
138
      IReadOnlyTreeFile file) {
×
139
    using var tr = new SchemaTextReader(file.OpenRead());
×
140

141
    var allAttributes = new List<BallAttributes>();
×
142

143
    BallAttributes currentAttributes = default!;
×
144
    while (!tr.Eof) {
×
145
      var line = tr.ReadLine().Trim();
×
146

147
      if (line.StartsWith('[')) {
×
148
        var id = line[1..].SubstringUpTo(']');
×
149
        currentAttributes = new BallAttributes { Id = id };
×
150
        allAttributes.Add(currentAttributes);
×
151
      } else {
×
152
        var equalsParts = line.Split('=');
×
153
        if (equalsParts.Length > 1) {
×
154
          var before = equalsParts[0].Trim();
×
155
          var after = equalsParts[1].Trim();
×
156

157
          switch (before) {
×
158
            case "Geometry": {
×
159
              currentAttributes.Geometry = after;
×
160
              break;
×
161
            }
162
            case "MapFromFile": {
×
163
              currentAttributes.MapFromFile = after == "1";
×
164
              break;
×
165
            }
166
            case "NoEnvMap": {
×
167
              currentAttributes.NoEnvMap = after == "1";
×
168
              break;
×
169
            }
170
            case "Texture": {
×
171
              currentAttributes.Texture = after;
×
172
              break;
×
173
            }
174
          }
175
        }
×
176
      }
×
177
    }
×
178

179
    return allAttributes;
×
180
  }
×
181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc