You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
817 lines
17 KiB
D
817 lines
17 KiB
D
/*
|
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
|
Copyright (C) 2008 Nicolay Korslund
|
|
Email: < korslund@gmail.com >
|
|
WWW: http://openmw.snaptoad.com/
|
|
|
|
This file (data.d) is part of the OpenMW package.
|
|
|
|
OpenMW is distributed as free software: you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License
|
|
version 3, as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
version 3 along with this program. If not, see
|
|
http://www.gnu.org/licenses/ .
|
|
|
|
*/
|
|
|
|
module nif.data;
|
|
import nif.record;
|
|
|
|
class NiSourceTexture : Named
|
|
{
|
|
byte external;
|
|
union
|
|
{
|
|
char[] filename;
|
|
NiPixelData data;
|
|
}
|
|
|
|
/* Pixel layout
|
|
0 - Palettised
|
|
1 - High color 16
|
|
2 - True color 32
|
|
3 - Compressed
|
|
4 - Bumpmap
|
|
5 - Default */
|
|
int pixel;
|
|
|
|
/* Mipmap format
|
|
0 - no
|
|
1 - yes
|
|
2 - default */
|
|
int mipmap;
|
|
|
|
/* Alpha
|
|
0 - none
|
|
1 - binary
|
|
2 - smooth
|
|
3 - default (use material alpha, or multiply material with texture if present)
|
|
*/
|
|
int alpha;
|
|
|
|
override:
|
|
void sortOut(Record[] list)
|
|
{
|
|
super.sortOut(list);
|
|
if(!external)
|
|
data = lookup!(NiPixelData)(list);
|
|
}
|
|
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
external = nifFile.getByteIs(0,1);
|
|
debug(verbose) writefln("Use external file: ", external);
|
|
|
|
if(external)
|
|
{
|
|
filename = nifFile.getString;
|
|
debug(verbose) writefln("Filename: ", filename);
|
|
}
|
|
else
|
|
{
|
|
nifFile.wgetByteIs(1);
|
|
debug(verbose) writef("Pixel Data ");
|
|
getIndex();
|
|
}
|
|
|
|
pixel = nifFile.getInt;
|
|
mipmap = nifFile.getInt;
|
|
alpha = nifFile.getIntIs(3);
|
|
|
|
debug(verbose)
|
|
{
|
|
writefln("Pixel layout: ", pixel);
|
|
writefln("Mipmap: ", mipmap);
|
|
writefln("Alpha: ", alpha);
|
|
}
|
|
|
|
nifFile.wgetByteIs(1);
|
|
}
|
|
}
|
|
|
|
// Common ancestor for several classes
|
|
class ShapeData : Record
|
|
{
|
|
float[] vertices, normals, colors, uvlist;
|
|
Vector center;
|
|
float radius;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
short verts = nifFile.getShort;
|
|
debug(verbose) writefln("Vertices: ", verts);
|
|
|
|
if(nifFile.getInt != 0)
|
|
{
|
|
debug(verbose) writefln("Reading vertices");
|
|
if(verts == 0) nifFile.warn("Empty vertex array");
|
|
vertices = nifFile.getArraySize!(float)(verts*3);
|
|
}
|
|
else nifFile.warn("No vertices found");
|
|
|
|
if(nifFile.getInt != 0)
|
|
{
|
|
debug(verbose) writefln("Reading normals");
|
|
normals = nifFile.getArraySize!(float)(verts*3);
|
|
}
|
|
|
|
center = nifFile.getVector();
|
|
radius = nifFile.getFloat();
|
|
debug(verbose)
|
|
{
|
|
writefln("Center: ", center.toString);
|
|
writefln("Radius: ", radius);
|
|
}
|
|
|
|
if(nifFile.getInt != 0)
|
|
{
|
|
debug(verbose) writefln("Reading vertex colors");
|
|
colors = nifFile.getArraySize!(float)(verts*4);
|
|
}
|
|
|
|
short uvs = nifFile.getShort;
|
|
debug(verbose) writefln("Number of UV sets: ", uvs);
|
|
|
|
if(nifFile.getInt != 0)
|
|
{
|
|
if(uvs == 0) nifFile.warn("Empty UV list");
|
|
|
|
// Only the 6 first bits are used as a count, the rest are
|
|
// (unknown) flags.
|
|
if(uvs > 0b111111)
|
|
{
|
|
nifFile.warn("UV count contains (unknown) flags");
|
|
uvs = cast(short)(uvs & 0b111111);
|
|
}
|
|
|
|
uvlist = nifFile.getArraySize!(float)(uvs*verts*2);
|
|
}
|
|
else if(uvs != 0) nifFile.warn("UV list was unexpectedly missing");
|
|
}
|
|
}
|
|
|
|
class NiAutoNormalParticlesData : ShapeData
|
|
{
|
|
ushort activeCount;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
nifFile.assertWarn(uvlist.length == 0, "UV coordinates are not expected in this record");
|
|
|
|
debug(verbose) writef("Active vertices: ");
|
|
|
|
// Number of active vertices (always matches count?)
|
|
activeCount = nifFile.wgetUshortIs(cast(ushort)(vertices.length/3));
|
|
|
|
nifFile.wgetFloat(); // Active radius (?)
|
|
nifFile.wgetShort(); // Number of valid entries in the following arrays
|
|
|
|
//writefln("%x", nifFile.position);
|
|
if(nifFile.wgetInt == 0) nifFile.warn("Particle size list is missing");
|
|
else
|
|
for(int i; i<activeCount; i++)
|
|
{
|
|
float fl = nifFile.getFloat; // Particle sizes
|
|
debug(veryverbose)
|
|
writefln(" %d: ", i, fl);
|
|
}
|
|
}
|
|
}
|
|
|
|
class NiRotatingParticlesData : NiAutoNormalParticlesData
|
|
{
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
nifFile.assertWarn(normals.length == 0, "Normals are not expected in this record");
|
|
|
|
Vector4 v;
|
|
|
|
if(nifFile.wgetInt == 0) nifFile.warn("Rotation data is not present");
|
|
else
|
|
// This is either activeCount or vertices.length/3, until I
|
|
// find a file in which the two differs (if one exists), we
|
|
// can't know which is correct.
|
|
for(int i; i<activeCount; i++)
|
|
{
|
|
v = nifFile.getVector4; // Quaternions
|
|
debug(veryverbose)
|
|
writefln(" %d: ", i, v.toString);
|
|
}
|
|
//writefln("%x", nifFile.position);
|
|
}
|
|
}
|
|
|
|
class NiPosData : Record
|
|
{
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
int count = nifFile.getInt;
|
|
debug(verbose) writefln("Count: ", count);
|
|
int type = nifFile.wgetIntIs(1,2);
|
|
for(int i; i<count; i++)
|
|
{
|
|
// TODO: Make a generalized struct of this? Seems to be the
|
|
// same as in NiKeyframeData.
|
|
float time = nifFile.getFloat;
|
|
debug(verbose) writef("Time %f: ", time);
|
|
Vector v;
|
|
if(type == 1)
|
|
{
|
|
v = nifFile.getVector;
|
|
debug(verbose) writef(v.toString);
|
|
}
|
|
else if(type == 2)
|
|
{
|
|
v = nifFile.getVector;
|
|
debug(verbose) writef(v.toString, " ");
|
|
v = nifFile.getVector;
|
|
debug(verbose) writef(v.toString, " ");
|
|
v = nifFile.getVector;
|
|
debug(verbose) writef(v.toString);
|
|
}
|
|
else nifFile.fail("Unknown type");
|
|
debug(verbose) writefln();
|
|
}
|
|
}
|
|
}
|
|
|
|
class NiUVData : Record
|
|
{
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
debug(verbose) writef("Count: ");
|
|
int count = nifFile.wgetInt();
|
|
|
|
// TODO: This is claimed to be a "float animation key", which is
|
|
// also used in FloatData and KeyframeData
|
|
if(count != 5 && count != 3 && count != 2 && count != 0)
|
|
nifFile.warn("Untested count");
|
|
|
|
if(count)
|
|
{
|
|
nifFile.wgetIntIs(2);
|
|
debug(verbose) writefln("%d entries in list 1:", count);
|
|
for(int i; i<count; i++)
|
|
{
|
|
float time = nifFile.getFloat;
|
|
Vector v = nifFile.getVector;
|
|
debug(verbose)
|
|
writefln(" Time %f: ", time, v.toString);
|
|
}
|
|
}
|
|
|
|
count = nifFile.getInt;
|
|
|
|
if(count)
|
|
{
|
|
nifFile.wgetIntIs(2);
|
|
debug(verbose) writefln("%d entries in list 2:", count);
|
|
for(int i; i<count; i++)
|
|
{
|
|
float time = nifFile.getFloat;
|
|
Vector v = nifFile.getVector;
|
|
debug(verbose)
|
|
writefln(" Time %f: ", time, v.toString);
|
|
|
|
}
|
|
}
|
|
|
|
nifFile.getIntIs(0);
|
|
nifFile.getIntIs(0);
|
|
}
|
|
}
|
|
|
|
class NiPixelData : Record
|
|
{
|
|
uint rmask, gmask, bmask, amask;
|
|
int bpp;
|
|
int mips;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
nifFile.wgetIntIs(0,1);
|
|
rmask = nifFile.getUintIs(0xff);
|
|
gmask = nifFile.getUintIs(0xff00);
|
|
bmask = nifFile.getUintIs(0xff0000);
|
|
amask = nifFile.getUintIs(0xff000000,0);
|
|
|
|
bpp = nifFile.getIntIs(24,32);
|
|
|
|
nifFile.wgetByte();
|
|
|
|
nifFile.wgetByteIs(8);
|
|
nifFile.wgetUbyteIs(130);
|
|
|
|
nifFile.wgetByteIs(0,32);
|
|
|
|
nifFile.wgetByteIs(0);
|
|
nifFile.wgetByteIs(65);
|
|
|
|
nifFile.wgetByteIs(0,12);
|
|
|
|
nifFile.wgetByteIs(0);
|
|
nifFile.wgetIntIs(-1);
|
|
|
|
mips = nifFile.getInt;
|
|
int bytes = nifFile.getIntIs(bpp>>3);
|
|
|
|
debug(verbose)
|
|
{
|
|
writefln("Red mask %8xh", rmask);
|
|
writefln("Green mask %8xh", gmask);
|
|
writefln("Blue mask %8xh", bmask);
|
|
writefln("Alpha mask %8xh", amask);
|
|
writefln("Bits per pixel: ", bpp);
|
|
writefln("Number of mipmaps: ", mips);
|
|
writefln("Bytes per pixel: ", bytes);
|
|
}
|
|
|
|
for(int i; i<mips; i++)
|
|
{
|
|
int x = nifFile.getInt;
|
|
int y = nifFile.getInt;
|
|
uint offset = nifFile.getUint;
|
|
debug(verbose)
|
|
{
|
|
writefln("Mipmap %d:", i);
|
|
writefln(" Size: %dx%d", x, y);
|
|
writefln(" Offset in data field: %xh", offset);
|
|
}
|
|
}
|
|
|
|
uint dataSize = nifFile.getUint;
|
|
nifFile.seekCur(dataSize);
|
|
}
|
|
}
|
|
|
|
class NiColorData : Record
|
|
{
|
|
struct ColorData
|
|
{
|
|
float time, R, G, B, A;
|
|
}
|
|
static assert(ColorData.sizeof == 20);
|
|
|
|
ColorData colors[];
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
int count = nifFile.getInt;
|
|
nifFile.getIntIs(1);
|
|
colors = nifFile.getArraySize!(ColorData)(count);
|
|
}
|
|
}
|
|
|
|
class NiVisData : Record
|
|
{
|
|
align(1)
|
|
struct VisData
|
|
{
|
|
float time;
|
|
byte isSet;
|
|
|
|
static assert(VisData.sizeof == 5);
|
|
}
|
|
|
|
VisData vis[];
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
int count = nifFile.getInt;
|
|
vis = nifFile.getArraySize!(VisData)(count);
|
|
debug(check)
|
|
foreach(VisData v; vis)
|
|
if(v.isSet!=0 && v.isSet!=1) nifFile.warn("Unknown bool value");
|
|
}
|
|
}
|
|
|
|
class NiFloatData : Record
|
|
{
|
|
struct FloatData
|
|
{
|
|
float time;
|
|
float[3] alpha;
|
|
}
|
|
static assert(FloatData.sizeof == 16);
|
|
|
|
FloatData data[];
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
int cnt = nifFile.getInt;
|
|
|
|
nifFile.getIntIs(2);
|
|
|
|
data = nifFile.getArraySize!(FloatData)(cnt);
|
|
|
|
// This might be the "keyfloat" type, ie. a value and forward
|
|
// and backward tangents. Might be used for animating in the
|
|
// alpha space?
|
|
debug(verbose)
|
|
foreach(FloatData d; data)
|
|
writefln("Time: %f Alpha: %f, %f, %f", d.time,
|
|
d.alpha[0], d.alpha[1], d.alpha[2]);
|
|
}
|
|
}
|
|
|
|
class NiSkinData : Record
|
|
{
|
|
align(1)
|
|
struct Weight
|
|
{
|
|
ushort vertex;
|
|
float weight;
|
|
|
|
static assert(Weight.sizeof == 6);
|
|
}
|
|
|
|
Weight weights[][];
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
Matrix m;
|
|
Vector v;
|
|
Vector4 v4;
|
|
|
|
nifFile.getMatrix(m);
|
|
v = nifFile.getVector();
|
|
nifFile.getFloatIs(1);
|
|
debug(verbose)
|
|
{
|
|
writefln("Matrix:\n", m.toString);
|
|
writefln("Vector: ", v.toString);
|
|
writefln("Float: 1 (always)");
|
|
}
|
|
|
|
int count = nifFile.getInt;
|
|
debug(verbose) writefln("Bones: ", count);
|
|
nifFile.getIntIs(-1);
|
|
|
|
nifFile.fitArray(70,count);
|
|
|
|
weights = nifRegion.allocateT!(Weight[])(count);
|
|
|
|
foreach(int i, ref Weight[] wl; weights)
|
|
{
|
|
nifFile.getMatrix(m); // Rotation offset of the skin from this
|
|
// bone in bind position.
|
|
v = nifFile.getVector(); // Translation -ditto-
|
|
nifFile.getFloatIs(1); // Scale -ditto- ?
|
|
debug(verbose)
|
|
{
|
|
writefln("Bone #%d:", i);
|
|
writefln(" Rotation:\n", m.toString);
|
|
writefln(" Translation: ", v.toString);
|
|
writefln(" Scale: 1 (always)");
|
|
}
|
|
v4 = nifFile.getVector4;
|
|
|
|
// Number of vertex weights
|
|
ushort cnt2 = nifFile.getUshort;
|
|
|
|
debug(verbose)
|
|
{
|
|
writefln(" 4-Vector: ", v4.toString);
|
|
writefln(" Number of vertex weights: ", cnt2);
|
|
}
|
|
|
|
wl = nifFile.getArraySize!(Weight)(cnt2);
|
|
|
|
debug(veryverbose)
|
|
foreach(ref Weight w; wl)
|
|
writefln(" %d: ", w.vertex, w.weight);
|
|
}
|
|
}
|
|
}
|
|
|
|
class NiTriShapeData : ShapeData
|
|
{
|
|
short[] triangles;
|
|
short[][] matches;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
ushort verts = cast(ushort)(vertices.length/3);
|
|
|
|
short tris = nifFile.getShort;
|
|
debug(verbose) writefln("Number of faces: ", tris);
|
|
if(tris)
|
|
{
|
|
// Must have three times as many vertices as triangles
|
|
int cnt = nifFile.getIntIs(tris*3);
|
|
triangles = nifFile.getArraySize!(short)(cnt);
|
|
}
|
|
|
|
short match = nifFile.getShort;
|
|
if(match)
|
|
{
|
|
nifFile.fitArray(match,2);
|
|
matches = nifRegion.allocateT!(short[])(match);
|
|
if(match != verts) nifFile.warn("Expected verts and match to be equal");
|
|
foreach(ref short[] s; matches)
|
|
{
|
|
short sh = nifFile.getShort;
|
|
if(sh>=verts || sh < 0)
|
|
nifFile.warn("Presumed vertex index was out of bounds");
|
|
s = nifFile.getArraySize!(short)(sh);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class NiMorphData : Record
|
|
{
|
|
//float[] vertexList;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
int morphCount = nifFile.getInt;
|
|
|
|
int vertCount = nifFile.getInt;
|
|
|
|
debug(verbose)
|
|
{
|
|
writefln("Number of morphs: ", morphCount);
|
|
writefln("Vertices: ", vertCount);
|
|
}
|
|
|
|
nifFile.wgetByteIs(1);
|
|
|
|
//nifFile.getIntIs(0);
|
|
//nifFile.getIntIs(1);
|
|
//vertexList = nifFile.getArraySize!(float)(3*vertCount);
|
|
|
|
for(int i=0; i<morphCount; i++)
|
|
{
|
|
int magic = nifFile.getInt;
|
|
|
|
debug(veryverbose)
|
|
{
|
|
writefln("Getting morph batch %d", i);
|
|
writefln(" Number of 4-vectors ", magic);
|
|
}
|
|
|
|
nifFile.wgetIntIs(0,1,2); // Is always 1 for i=0, 0 or 2 otherwise
|
|
|
|
float[] l;
|
|
|
|
// Time, data, forward, backward tangents
|
|
if(magic)
|
|
l = nifFile.getArraySize!(float)(magic*4);
|
|
|
|
debug(veryverbose)
|
|
for(int j; j<magic; j++)
|
|
writefln(" Time %f : [", l[4*j], l[4*j+1],",", l[4*j+2],",", l[4*j+3],"]");
|
|
|
|
l = nifFile.getArraySize!(float)(vertCount*3);
|
|
|
|
debug(veryverbose)
|
|
for(int j; j<vertCount; j++)
|
|
writefln(" Vertex morph %d: ", j, " [%f, %f, %f]",
|
|
l[j*3], l[j*3+1], l[j*3+2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
class NiKeyframeData : Record
|
|
{
|
|
// These should be moved out of this class, given their own reader
|
|
// functions, and used elsewhere. But it currently works, and I
|
|
// haven't really confirmed that these ARE used elsewhere, yet.
|
|
|
|
struct Rotation1
|
|
{
|
|
float time;
|
|
float[4] quaternion;
|
|
|
|
static assert(Rotation1.sizeof == 5*4);
|
|
}
|
|
|
|
struct Rotation3
|
|
{
|
|
float time;
|
|
float[4] quaternion;
|
|
float tension;
|
|
float bias;
|
|
float continuity;
|
|
|
|
static assert(Rotation3.sizeof == 8*4);
|
|
}
|
|
|
|
struct Rotation4
|
|
{
|
|
float time;
|
|
|
|
struct R
|
|
{
|
|
struct R1
|
|
{
|
|
float time;
|
|
float unknown;
|
|
|
|
static assert(R1.sizeof == 8);
|
|
}
|
|
|
|
struct R2
|
|
{
|
|
float time;
|
|
float unknown[3];
|
|
|
|
static assert(R2.sizeof == 16);
|
|
}
|
|
|
|
int type;
|
|
union
|
|
{
|
|
R1[] r1;
|
|
R2[] r2;
|
|
}
|
|
}
|
|
|
|
R r3[3];
|
|
}
|
|
|
|
struct Translation1
|
|
{
|
|
float time;
|
|
float[3] translation;
|
|
static assert(Translation1.sizeof==4*4);
|
|
}
|
|
struct Translation2
|
|
{
|
|
float time;
|
|
float[3] translation;
|
|
float[3] forward;
|
|
float[3] backward;
|
|
static assert(Translation2.sizeof==4*10);
|
|
}
|
|
struct Translation3
|
|
{
|
|
float time;
|
|
float[3] translation;
|
|
float tension;
|
|
float bias;
|
|
float continuity;
|
|
static assert(Translation3.sizeof==4*7);
|
|
}
|
|
|
|
struct Scale1
|
|
{
|
|
float time;
|
|
float scale;
|
|
static assert(Scale1.sizeof == 4*2);
|
|
}
|
|
struct Scale2
|
|
{
|
|
float time;
|
|
float scale;
|
|
float forward;
|
|
float backward;
|
|
static assert(Scale2.sizeof == 4*4);
|
|
}
|
|
struct Scale3
|
|
{
|
|
float time;
|
|
float scale;
|
|
float tension;
|
|
float bias;
|
|
float continuity;
|
|
static assert(Scale3.sizeof == 4*5);
|
|
}
|
|
|
|
// Data arrays. Only one of each type will be used. I used to have
|
|
// them in unions, but then I realized that was just asking for trouble.
|
|
|
|
Rotation1 rot1[];
|
|
Rotation3 rot3[];
|
|
Rotation4 rot4[];
|
|
|
|
Translation1 tra1[];
|
|
Translation2 tra2[];
|
|
Translation3 tra3[];
|
|
|
|
Scale1 sca1[];
|
|
Scale2 sca2[];
|
|
Scale3 sca3[];
|
|
|
|
int rotType, traType, scaleType;
|
|
|
|
override:
|
|
void read()
|
|
{
|
|
super.read();
|
|
|
|
int count;
|
|
|
|
count = nifFile.getInt;
|
|
debug(verbose) writefln("Number of rotations: ", count);
|
|
|
|
if(count)
|
|
{
|
|
rotType = nifFile.getInt;
|
|
|
|
if(rotType == 1)
|
|
rot1 = nifFile.getArraySize!(Rotation1)(count);
|
|
else if(rotType == 3)
|
|
rot3 = nifFile.getArraySize!(Rotation3)(count);
|
|
else if(rotType == 4)
|
|
{
|
|
if(count!=1) nifFile.warn("Rotation type 4, but count was not 1, it was "
|
|
~ .toString(count));
|
|
nifFile.fitArray(count,6*4); // Minimum size
|
|
rot4 = nifRegion.allocateT!(Rotation4)(count);
|
|
|
|
foreach(ref Rotation4 rr; rot4)
|
|
{
|
|
rr.time = nifFile.getFloat;
|
|
foreach(ref rr.R r; rr.r3)
|
|
{
|
|
int cnt = nifFile.getInt;
|
|
r.type = nifFile.getInt;
|
|
if(r.type == 1)
|
|
nifFile.getArraySize!(r.R1)(cnt);
|
|
else if(r.type == 2)
|
|
nifFile.getArraySize!(r.R2)(cnt);
|
|
else nifFile.fail("Unknown rotation subtype " ~ .toString(r.type));
|
|
}
|
|
}
|
|
}
|
|
else nifFile.fail("Don't know how to handle rotation type " ~ .toString(rotType));
|
|
} // End of rotations
|
|
|
|
count = nifFile.getInt;
|
|
debug(verbose) writefln("Number of translations: ", count);
|
|
|
|
if(count)
|
|
{
|
|
traType = nifFile.getInt;
|
|
|
|
if(traType == 1)
|
|
tra1 = nifFile.getArraySize!(Translation1)(count);
|
|
else if(traType == 2)
|
|
tra2 = nifFile.getArraySize!(Translation2)(count);
|
|
else if(traType == 3)
|
|
tra3 = nifFile.getArraySize!(Translation3)(count);
|
|
else nifFile.fail("Don't know how to handle translation type "
|
|
~ .toString(traType));
|
|
} // End of translations
|
|
|
|
count = nifFile.getInt;
|
|
debug(verbose) writefln("Number of scalings: ", count);
|
|
|
|
if(count)
|
|
{
|
|
int scaleType = nifFile.getInt;
|
|
if(scaleType == 1) sca1 = nifFile.getArraySize!(Scale1)(count);
|
|
else if(scaleType == 2) sca2 = nifFile.getArraySize!(Scale2)(count);
|
|
else if(scaleType == 3) sca3 = nifFile.getArraySize!(Scale3)(count);
|
|
else nifFile.fail("Don't know how to handle scaling type "
|
|
~ .toString(scaleType));
|
|
} // End of scalings
|
|
|
|
}
|
|
}
|