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

MeltyPlayer / MeltyTool / 22553354538

01 Mar 2026 09:41PM UTC coverage: 41.567% (-0.03%) from 41.595%
22553354538

push

github

MeltyPlayer
Set up loading the Mario Kart 3d kart.

6989 of 18916 branches covered (36.95%)

Branch coverage included in aggregate %.

4 of 63 new or added lines in 5 files covered. (6.35%)

1 existing line in 1 file now uncovered.

29928 of 69897 relevant lines covered (42.82%)

62441.98 hits per line

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

35.23
/FinModelUtility/Libraries/GameMaker/GameMaker/src/api/D3dModelImporter.cs
1
using System.Numerics;
2

3
using fin.animation.keyframes;
4
using fin.image;
5
using fin.io;
6
using fin.io.bundles;
7
using fin.math.transform;
8
using fin.model;
9
using fin.model.impl;
10
using fin.model.io;
11
using fin.model.io.importers;
12
using fin.model.util;
13
using fin.util.sets;
14

15
using gm.schema.d3d;
16

17

18
namespace gm.api;
19

20
public sealed class D3dModelFileBundle : IModelFileBundle {
21
  public required IReadOnlyTreeFile D3dFile { get; init; }
×
22

23
  public IReadOnlyTreeFile? TextureFile { get; init; }
×
24

25
  public (IReadOnlyTreeFile gifFile, float frameRate)? AnimatedTextureFile {
26
    get;
×
27
    init;
×
28
  }
29

30
  public IReadOnlyTreeFile MainFile => this.D3dFile;
×
31
  public bool FlipNormals { get; init; }
×
32
  public WrapMode TextureWrapMode { get; init; }
×
33
}
34

35
public sealed class D3dModelImporter : IModelImporter<D3dModelFileBundle> {
36
  public IModel Import(D3dModelFileBundle modelFileBundle) {
×
37
    var d3dFile = modelFileBundle.D3dFile;
×
NEW
38
    var fileSet = new HashSet<IReadOnlyGenericFile>();
×
39

40
    var (finModel, finRootBone)
×
NEW
41
        = CreateModel((modelFileBundle, fileSet));
×
42

NEW
43
    AddToModel(modelFileBundle, finModel, fileSet, finRootBone);
×
44

NEW
45
    if (modelFileBundle.FlipNormals) {
×
NEW
46
      finModel.FlipAllNormals();
×
NEW
47
    }
×
48

NEW
49
    return finModel;
×
NEW
50
  }
×
51

52
  public static void AddToModel(
53
      D3dModelFileBundle modelFileBundle,
54
      IModel<ISkin<Normal1Color1UvVertexImpl>> finModel,
55
      ISet<IReadOnlyGenericFile> fileSet,
56
      IBone finRootBone,
NEW
57
      bool flipNormals = false) {
×
NEW
58
    var d3dFile = modelFileBundle.D3dFile;
×
NEW
59
    var d3d = d3dFile.ReadNewFromText<D3d>();
×
NEW
60
    fileSet.Add(d3dFile);
×
61

62
    ITextureMaterial? material = null;
×
63
    if (modelFileBundle.TextureFile is { } textureFile) {
×
64
      (material, var texture) =
×
65
          finModel.MaterialManager.AddSimpleTextureMaterialFromFile(
×
66
              textureFile);
×
67
      texture.WrapModeU = texture.WrapModeV = modelFileBundle.TextureWrapMode;
×
68
    } else if (modelFileBundle.AnimatedTextureFile is { } gifFileAndFrameRate) {
×
69
      var (gifFile, frameRate) = gifFileAndFrameRate;
×
70

71
      var frameImages = FinImage.FromGifFile(gifFile);
×
72
      var name = gifFile.NameWithoutExtension.ToString();
×
73

74
      var finMaterialManager = finModel.MaterialManager;
×
75
      var frameTextures
×
76
          = frameImages
×
77
            .Select((frameImage, i) => {
×
78
              var frameTexture = finMaterialManager.CreateTexture(
×
79
                  frameImage.RemoveTopLeftBackgroundColor());
×
80
              frameTexture.Name =
×
81
                  frameImages.Length > 0 ? $"{name}_{i}" : name;
×
82
              frameTexture.WrapModeU = frameTexture.WrapModeV =
×
83
                  modelFileBundle.TextureWrapMode;
×
84
              return frameTexture;
×
85
            })
×
86
            .ToArray();
×
87

88
      var baseTexture = frameTextures[0];
×
89

90
      material = finMaterialManager.AddTextureMaterial(baseTexture);
×
91
      material.Name = "diffuse";
×
92

93
      var animation = finModel.AnimationManager.AddAnimation();
×
94
      animation.Name = name;
×
95
      animation.FrameCount = frameImages.Length;
×
96
      animation.FrameRate = frameRate;
×
97

98
      var textureTracks = animation.AddTextureTracks(baseTexture);
×
99
      var flipbookSwapKeyframes
×
100
          = textureTracks.UseFlipbookSwapKeyframes(frameTextures.Length);
×
101
      for (var f = 0; f < frameTextures.Length; ++f) {
×
102
        flipbookSwapKeyframes.Add(
×
103
            new Keyframe<IReadOnlyTexture?>(f, frameTextures[f]));
×
104
      }
×
105
    }
×
106

NEW
107
    AddToModel(d3d, finModel, finRootBone, out _, material, flipNormals);
×
UNCOV
108
  }
×
109

110
  public static (IModel<ISkin<Normal1Color1UvVertexImpl>>, IBone) CreateModel(
111
      (IFileBundle fileBundle, IReadOnlySet<IReadOnlyGenericFile> files)?
112
          modelMetadata = null) {
1✔
113
    var finModel =
1!
114
        new ModelImpl<Normal1Color1UvVertexImpl>((index, position)
1✔
115
                                                     => new
4,791✔
116
                                                         Normal1Color1UvVertexImpl(
4,791✔
117
                                                             index,
4,791✔
118
                                                             position)) {
4,791✔
119
            FileBundle = modelMetadata?.fileBundle!,
1✔
120
            Files = modelMetadata?.files!
1✔
121
        };
1✔
122
    var finRootBone = CreateAdjustedRootBone(finModel);
1✔
123
    return (finModel, finRootBone);
1✔
124
  }
1✔
125

126
  public static IBone CreateAdjustedRootBone(IModel finModel) {
1✔
127
    var finSkeleton = finModel.Skeleton;
1✔
128
    var bone = finSkeleton.Root.AddRoot(0, 0, 0);
1✔
129
    bone.Transform.SetRotationDegrees(-90, 180, 0);
1✔
130
    bone.Transform.SetScale(-1, 1, 1);
1✔
131
    return bone;
1✔
132
  }
1✔
133

134
  public static void AddToModel(
135
      D3d d3d,
136
      IModel<ISkin<Normal1Color1UvVertexImpl>> finModel,
137
      IReadOnlyBone bone,
138
      out IMesh finMesh,
139
      IMaterial? material = null,
140
      bool flipNormals = false) {
13✔
141
    var finSkin = finModel.Skin;
13✔
142
    finMesh = finSkin.AddMesh();
13✔
143

144
    var boneWeights = finSkin.GetOrCreateBoneWeights(
13✔
145
        VertexSpace.RELATIVE_TO_BONE,
13✔
146
        bone);
13✔
147

148
    D3dPrimitiveType d3dPrimitiveType = default;
13✔
149
    var finVertices = new LinkedList<IVertex>();
13✔
150
    foreach (var d3dCommand in d3d.Commands) {
14,508✔
151
      switch (d3dCommand.CommandType) {
4,823!
152
        case D3dCommandType.BEGIN: {
16✔
153
          d3dPrimitiveType = (D3dPrimitiveType) d3dCommand.Parameters[0];
16✔
154
          break;
16✔
155
        }
156
        case D3dCommandType.END: {
16✔
157
          switch (d3dPrimitiveType) {
16!
158
            case D3dPrimitiveType.TRIANGLE_FAN: {
×
159
              finMesh.AddTriangleFan(finVertices.ToArray())
×
160
                     .SetMaterial(material);
×
161
              break;
×
162
            }
163
            case D3dPrimitiveType.TRIANGLE_LIST: {
16✔
164
              finMesh.AddTriangles(finVertices.ToArray())
16✔
165
                     .SetMaterial(material);
16✔
166
              break;
16✔
167
            }
168
            case D3dPrimitiveType.TRIANGLE_STRIP: {
×
169
              finMesh.AddTriangleStrip(finVertices.ToArray())
×
170
                     .SetMaterial(material);
×
171
              break;
×
172
            }
173
            default: throw new NotImplementedException();
×
174
          }
175

176
          finVertices.Clear();
16✔
177
          break;
16✔
178
        }
179
        case D3dCommandType.VERTEX_NORMAL_TEXTURE: {
4,791✔
180
          var d3dParams = d3dCommand.Parameters.AsSpan();
4,791✔
181

182
          var finVertex = finSkin.AddVertex(new Vector3(d3dParams[..3]));
4,791✔
183

184
          var normal = -new Vector3(d3dParams.Slice(3, 3));
4,791✔
185
          if (flipNormals) {
4,791!
NEW
186
            normal *= -1;
×
NEW
187
          }
×
188

189
          finVertex.SetLocalNormal(normal);
4,791✔
190
          finVertex.SetUv(new Vector2(d3dParams.Slice(6, 2)));
4,791✔
191
          finVertex.SetBoneWeights(boneWeights);
4,791✔
192

193
          finVertices.AddLast(finVertex);
4,791✔
194
          break;
4,791✔
195
        }
196
        case D3dCommandType.VERTEX_TEXTURE: {
×
197
          var d3dParams = d3dCommand.Parameters.AsSpan();
×
198

199
          var finVertex = finSkin.AddVertex(new Vector3(d3dParams[..3]));
×
200
          finVertex.SetUv(new Vector2(d3dParams.Slice(3, 2)));
×
201
          finVertex.SetBoneWeights(boneWeights);
×
202

203
          finVertices.AddLast(finVertex);
×
204
          break;
×
205
        }
206
        case D3dCommandType.VERTEX_TEXTURE_COLOR: {
×
207
          var d3dParams = d3dCommand.Parameters.AsSpan();
×
208

209
          var finVertex = finSkin.AddVertex(new Vector3(d3dParams[..3]));
×
210
          finVertex.SetUv(new Vector2(d3dParams.Slice(3, 2)));
×
211
          finVertex.SetColor(new Vector3(d3dParams.Slice(5, 3)) / 255f);
×
212
          finVertex.SetBoneWeights(boneWeights);
×
213

214
          finVertices.AddLast(finVertex);
×
215
          break;
×
216
        }
217
        default: throw new ArgumentOutOfRangeException();
×
218
      }
219
    }
4,823✔
220
  }
13✔
221
}
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