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

MeltyPlayer / MeltyTool / 28220998723

26 Jun 2026 06:19AM UTC coverage: 40.975% (-0.1%) from 41.112%
28220998723

push

github

MeltyPlayer
Updated MarioArtist goldens.

7326 of 19830 branches covered (36.94%)

Branch coverage included in aggregate %.

30582 of 72686 relevant lines covered (42.07%)

59979.76 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

14
using gm.schema.d3d;
15

16

17
namespace gm.api;
18

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

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

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

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

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

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

42
    AddToModel(modelFileBundle, finModel, fileSet, finRootBone);
×
43

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

48
    return finModel;
×
49
  }
×
50

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

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

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

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

87
      var baseTexture = frameTextures[0];
×
88

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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