/*
Corsix and fneep's RGM Tools for Company of Heroes
Copyright (C) 2006 Corsix (and fneep :D)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
This file loads RGM files into max and also handles the GUI parts of the script.
Version history:
0.1 (Oct 8th 2006):
- Initial release
- Loads vertex X,Y,Z and faces
0.11 (Feb 19th 2007):
- Bugfix and tweaks
- Loads Material IDs
- Parses Texture chunks and spits out data into listener
0.12 (Feb 23th 2007):
- Textures loaded
0.15 (Mar 1st 2007):
- Loads meshes as seperate objects
- Bugfixes and tweaks
0.151 (Mar 1st 2007):
- Fixed bug where script did not load infantry models
0.152 (Mar 3rd 2007):
- Minor cleanup and commented
- XREF warning messages added
0.16 (Mar 18th 2007):
- Loading of FOLDTRIM chunks added
- Fixed bug where only first mesh chunk was loaded
0.17 (Mar 23rd 2007):
- Added directory and recursive directory imports
- Fixed bug where texture paths were loaded incorrectly
*/
include "Corsix_Chunky.ms" -- include Corsix's chunky library
ClearListener() -- Clear the listener window to make for easier reading of data printed by script.
/*
Gets the filename of the ini file for this script
*/
fn Corsix_RGMImportIni =
(
local ini_dir = getINISetting (getMAXIniFile()) "Directories" "Startup Scripts"
return ini_dir + "\\Corsix_RGM_Import.ini"
)
/*
Handles a DATADATA chunk from an RGM file
oRgm - the RGM file
oChunk - the DATADATA chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_Mesh_DataData oRgm oChunk =
(
fseek oRgm.fFile (oChunk.iDataPosition + 1) #seek_set -- jump to chunk
/*
Objects
*/
struct sGlobalMeshInfo -- holds global mesh data to compare to and collect from
(
iVertCount = 0,
aVertArray = #(),
aUVArray = #(),
aFaceArray = #()
)
struct sObjectID -- holds data for the Object identifiers
(
iVertCount = 0,
aVertArray = #(),
aUVArray = #(),
iFaceCount = 0,
aFaceList = #()
)
struct sObjectStruct -- holds data for a single object
(
sObjectName = "",
sOIDStruct = sObjectID()
)
oMeshInfo = sGlobalMeshInfo() -- holds all mesh data
local iObjectCount = ReadLong oRgm.fFile #unsigned -- number of separate objects
aObjectList = #()
for i=1 to iObjectCount do
(
oObject = sObjectStruct()
oObject.sOIDStruct.iFaceCount = (ReadLong oRgm.fFile #unsigned)/3 -- number of faces as the verts that make them. Meshes are triangles so divide by 3
for i=1 to oObject.sOIDStruct.iFaceCount do
(
local aFace = point3 0 0 0
aFace.x = (ReadShort oRgm.fFile) + 1 -- vertex ID's given as vertnumber - 1 because of the way that C++ handles arrays (the exporter is in C++). To convert to maxscript, add one.
aFace.z = (ReadShort oRgm.fFile) + 1
aFace.y = (ReadShort oRgm.fFile) + 1
append oObject.sOIDStruct.aFaceList [aFace.x, aFace.y, aFace.z]
)
fseek oRgm.fFile 13 #seek_cur -- skip unknown
local iStrLen = ReadLong oRgm.fFile #unsigned
oObject.sObjectName = Corsix_ReadStringN oRgm.fFile iStrLen
append aObjectList oObject
)
/*
Per-Vertex Component Data
*/
local iComponentCount = ReadLong oRgm.fFile #unsigned
struct sPerVertStruct
(
iVertComponent = 0,
iUnknown = 0,
iDataType = 0
)
local aComponentVector = #()
for i=1 to iComponentCount do
(
oComponent = sPerVertStruct()
oComponent.iVertComponent = ReadLong oRgm.fFile #unsigned
oComponent.iUnknown = ReadLong oRgm.fFile #unsigned -- This number should usually be three. Its current purpose is unknown
oComponent.iDataType = ReadLong oRgm.fFile #unsigned
append aComponentVector oComponent
)
Print aComponentVector as string
/*
Per-Vertex Data
*/
struct sVertStruct
(
p3Position = point3 0 0 0,
iBoneIndex = 0,
iBoneWeight = 0,
iNormal = 0,
iBiNormal = 0,
iTangent = 0,
iDiffuseColour = color 0 0 0 0,
iSpecularColour = color 0 0 0 0,
p3UVCh1 = point3 0 0 0,
p3UVCh2 = point3 0 0 0,
p3UVCh3 = point3 0 0 0
)
local aVerticies = #()
local iVertCount = ReadLong oRgm.fFile #unsigned
local iVertexSize = ReadLong oRgm.fFile #unsigned -- number of bytes taken up by each vertex on disk.
for i=1 to iVertCount do
(
local oVertex = sVertStruct()
for oComponent in aComponentVector do
(
case oComponent.iVertComponent of
(
/*
0 = Position
*/
0:
(
oVertex.p3Position.x = -(ReadFloat oRgm.fFile)
oVertex.p3Position.z = ReadFloat oRgm.fFile
oVertex.p3Position.y = -(ReadFloat oRgm.fFile)
)
/*
1 = Bone Index
*/
1:
(
oVertex.iBoneIndex = ReadLong oRgm.fFile #unsigned
)
/*
2 = Bone Weight
*/
2:
(
oVertex.iBoneWeight = ReadLong oRgm.fFile #unsigned
)
/*
3 = Normal
*/
3:
(
oVertex.iNormal = ReadLong oRgm.fFile #unsigned
)
/*
4 = BiNormal
*/
4:
(
oVertex.iBiNormal = ReadLong oRgm.fFile #unsigned
)
/*
5 = Tangent
*/
5:
(
oVertex.iTangent = ReadLong oRgm.fFile #unsigned
)
/*
6 = Diffuse Vertex Colour
*/
6:
(
oVertex.iDiffuseColour.r = ReadByte oRgm.fFile
oVertex.iDiffuseColour.g = ReadByte oRgm.fFile
oVertex.iDiffuseColour.b = ReadByte oRgm.fFile
oVertex.iDiffuseColour.a = ReadByte oRgm.fFile
)
/*
7 = Specular Vertex Colour
*/
7:
(
oVertex.iSpecularColour.r = ReadByte oRgm.fFile
oVertex.iSpecularColour.g = ReadByte oRgm.fFile
oVertex.iSpecularColour.b = ReadByte oRgm.fFile
oVertex.iSpecularColour.a = ReadByte oRgm.fFile
)
/*
8 = UV Channel 1
*/
8:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh1.x = ReadFloat oRgm.fFile
oVertex.p3UVCh1.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh1.x = ReadLong oRgm.fFile
)
)
/*
9 = UV Channel 2
*/
9:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh2.x = ReadFloat oRgm.fFile
oVertex.p3UVCh2.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh2.x = ReadLong oRgm.fFile
)
)
/*
10 = UV Channel 3
*/
10:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh3.x = ReadFloat oRgm.fFile
oVertex.p3UVCh3.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh3.x = ReadLong oRgm.fFile
)
)
)
)
append aVerticies oVertex
)
Print aVerticies as string
VertUnknown = ReadLong oRgm.fFile
/*
Faces and Material IDs
*/
local aFaces = #()
local iFaceCount = ReadLong oRgm.fFile #unsigned
FaceUnknown = ReadLong oRgm.fFile
FaceUnknown = ReadLong oRgm.fFile
iFaceCount = iFaceCount / 3
for i=1 to iFaceCount do
(
local aFace = point3 0 0 0
aFace.x = (ReadShort oRgm.fFile) + 1
aFace.z = (ReadShort oRgm.fFile) + 1
aFace.y = (ReadShort oRgm.fFile) + 1
append aFaces [aFace.x, aFace.y, aFace.z]
)
local iStrLen = ReadLong oRgm.fFile #unsigned
sMaterialName = Corsix_ReadStringN oRgm.fFile iStrLen
local iMatIDFace = 0
iMatIDFace = findItem aMatIDArray sMaterialName
oMeshInfo.aFaceArray = aFaces
/*
Organise the verts for the per object mesh construction
*/
for oTempObject in aObjectList do
(
aRelativeFaceArray = #()
for i=1 to oTempObject.sOIDStruct.aFaceList.count do
(
aVert = oTempObject.sOIDStruct.aFaceList[i] -- find the vert
----------[ X Vert ]----------
aRelativeVert = oMeshInfo.aVertArray[aVert.x]
if (finditem oTempObject.sOIDStruct.aVertArray aRelativeVert) == 0 then
(
append oTempObject.sOIDStruct.aVertArray aRelativeVert -- and send it to the correct object structure
)
----------[ Y Vert ]----------
aRelativeVert = oMeshInfo.aVertArray[aVert.y]
if (finditem oTempObject.sOIDStruct.aVertArray aRelativeVert) == 0 then
(
append oTempObject.sOIDStruct.aVertArray aRelativeVert
)
----------[ Z Vert ]----------
aRelativeVert = oMeshInfo.aVertArray[aVert.z]
if (finditem oTempObject.sOIDStruct.aVertArray aRelativeVert) == 0 then
(
append oTempObject.sOIDStruct.aVertArray aRelativeVert
)
)
for oFace in oTempObject.sOIDStruct.aFaceList do
(
iRelativeFace = point3 0 0 0 -- new face
iRelativeFace.x = finditem oTempObject.sOIDStruct.aVertArray oMeshInfo.aVertArray[oFace.x] -- find the vertex from our global vert array
iRelativeFace.y = finditem oTempObject.sOIDStruct.aVertArray oMeshInfo.aVertArray[oFace.y]
iRelativeFace.z = finditem oTempObject.sOIDStruct.aVertArray oMeshInfo.aVertArray[oFace.z]
append aRelativeFaceArray iRelativeFace
)
oTempObject.sOIDStruct.aFaceList = aRelativeFaceArray
)
/*
Construct Meshes
*/
/*
for oTempObject in aObjectList do
(
oMesh = mesh vertices:(oTempObject.sOIDStruct.aVertArray) faces:(oTempObject.sOIDStruct.aFaceList) -- construct mesh. oMesh = current mesh handle.
oMesh.name = oTempObject.sObjectName -- set object name
oMesh.wireColor = (color 0 0 0) -- set wire colour to black
oMesh.material = mCorsixMultiMat -- assign material
update oMesh
deselect oMesh
for i = 1 to oMesh.numfaces do
(
oFace = (getFace oMesh i)
setFaceSmoothGroup oMesh i 0 -- clear smoothing groups (o = none)
setFaceMatID oMesh i iMatIDFace -- set the material ID
)
meshop.weldVertsByThreshold oMesh oMesh.verts 0.00001 -- weld our new mesh
Print ("Mesh: " + oMesh.name + " built!")
)
*/
)
/*
Handles a FOLDTRIM/DATADATA chunk from an RGM file
oRgm - the RGM file
oChunk - the DATADATA chunk
sName - the name of the mesh
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldTrim_DataData oRgm oChunk sName =
(
fseek oRgm.fFile (oChunk.iDataPosition) #seek_set -- jump to chunk
/*
Per-Vertex Component Data
*/
local iComponentCount = ReadLong oRgm.fFile #unsigned
struct sPerVertStruct
(
iVertComponent = 0,
iUnknown = 0,
iDataType = 0
)
local aComponentVector = #()
for i=1 to iComponentCount do
(
oComponent = sPerVertStruct()
oComponent.iVertComponent = ReadLong oRgm.fFile #unsigned
oComponent.iUnknown = ReadLong oRgm.fFile #unsigned -- This number should usually be three. Its current purpose is unknown
oComponent.iDataType = ReadLong oRgm.fFile #unsigned
append aComponentVector oComponent
)
Print aComponentVector as string
/*
Per-Vertex Data
*/
struct sVertStruct
(
p3Position = point3 0 0 0,
iBoneIndex = 0,
iBoneWeight = 0,
iNormal = 0,
iBiNormal = 0,
iTangent = 0,
iDiffuseColour = color 0 0 0 0,
iSpecularColour = color 0 0 0 0,
p3UVCh1 = point3 0 0 0,
p3UVCh2 = point3 0 0 0,
p3UVCh3 = point3 0 0 0
)
local aVerticies = #()
local iVertCount = ReadLong oRgm.fFile #unsigned
local iVertexSize = ReadLong oRgm.fFile #unsigned -- number of bytes taken up by each vertex on disk.
for i=1 to iVertCount do
(
local oVertex = sVertStruct()
for oComponent in aComponentVector do
(
case oComponent.iVertComponent of
(
/*
0 = Position
*/
0:
(
oVertex.p3Position.x = -(ReadFloat oRgm.fFile)
oVertex.p3Position.z = ReadFloat oRgm.fFile
oVertex.p3Position.y = -(ReadFloat oRgm.fFile)
)
/*
1 = Bone Index
*/
1:
(
oVertex.iBoneIndex = ReadLong oRgm.fFile #unsigned
)
/*
2 = Bone Weight
*/
2:
(
oVertex.iBoneWeight = ReadLong oRgm.fFile #unsigned
)
/*
3 = Normal
*/
3:
(
oVertex.iNormal = ReadLong oRgm.fFile #unsigned
)
/*
4 = BiNormal
*/
4:
(
oVertex.iBiNormal = ReadLong oRgm.fFile #unsigned
)
/*
5 = Tangent
*/
5:
(
oVertex.iTangent = ReadLong oRgm.fFile #unsigned
)
/*
6 = Diffuse Vertex Colour
*/
6:
(
oVertex.iDiffuseColour.r = ReadByte oRgm.fFile
oVertex.iDiffuseColour.g = ReadByte oRgm.fFile
oVertex.iDiffuseColour.b = ReadByte oRgm.fFile
oVertex.iDiffuseColour.a = ReadByte oRgm.fFile
)
/*
7 = Specular Vertex Colour
*/
7:
(
oVertex.iSpecularColour.r = ReadByte oRgm.fFile
oVertex.iSpecularColour.g = ReadByte oRgm.fFile
oVertex.iSpecularColour.b = ReadByte oRgm.fFile
oVertex.iSpecularColour.a = ReadByte oRgm.fFile
)
/*
8 = UV Channel 1
*/
8:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh1.x = ReadFloat oRgm.fFile
oVertex.p3UVCh1.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh1.x = ReadLong oRgm.fFile
)
)
/*
9 = UV Channel 2
*/
9:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh2.x = ReadFloat oRgm.fFile
oVertex.p3UVCh2.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh2.x = ReadLong oRgm.fFile
)
)
/*
10 = UV Channel 3
*/
10:
(
if oComponent.iDataType == 3 then
(
oVertex.p3UVCh3.x = ReadFloat oRgm.fFile
oVertex.p3UVCh3.y = ReadFloat oRgm.fFile
)
else
(
oVertex.p3UVCh3.x = ReadLong oRgm.fFile
)
)
)
)
append aVerticies oVertex
)
Print aVerticies as string
fseek oRgm.fFile 8 #seek_cur -- skip unknown
/*
Faces and Material IDs
*/
local aFaces = #()
local iVertsPerFace = ReadLong oRgm.fFile -- number of verts in a face
local iFaceCount = ReadLong oRgm.fFile
iFaceCount = iFaceCount / iVertsPerFace
for i=1 to iFaceCount do
(
local aFace = point3 0 0 0
aFace.x = (ReadShort oRgm.fFile) + 1
aFace.z = (ReadShort oRgm.fFile) + 1
aFace.y = (ReadShort oRgm.fFile) + 1
append aFaces [aFace.x, aFace.y, aFace.z]
)
local iStrLen = ReadLong oRgm.fFile #unsigned
sMaterialName = Corsix_ReadStringN oRgm.fFile iStrLen
local iMatIDFace = 0
iMatIDFace = findItem aMatIDArray sMaterialName
/*
Construct Mesh
*/
/*
oMesh = mesh vertices:aVerticies faces:aFaces -- construct mesh.
oMesh.name = sName -- set object name
oMesh.wireColor = (color 0 0 0) -- set wire colour to black
oMesh.material = mCorsixMultiMat -- assign material
update oMesh
deselect oMesh
for i = 1 to oMesh.numfaces do
(
oFace = (getFace oMesh i)
setFaceSmoothGroup oMesh i 0 -- clear smoothing groups (o = none)
setFaceMatID oMesh i iMatIDFace -- set the material ID
)
meshop.weldVertsByThreshold oMesh oMesh.verts 0.00001 -- weld our new mesh
Print ("Mesh: " + oMesh.name + " built!")
*/
)
/*
Handles a FOLDMRGM chunk from an RGM file
oRgm - the RGM file
oChunk - the FOLDMRGM chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMrgm oRgm oChunk =
(
iDataDataCount = 0
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"DATADATA":
(
if iDataDataCount == 0 then
(
Corsix_RgmIntoMax_Mesh_DataData oRgm oChunk.aChildren[i]
iDataDataCount = 1
)
)
)
i += 1
)
)
/*
Handles a FOLDMGRP chunk from an RGM file (Mesh Group)
oRgm - the RGM file
oChunk - the FOLDMGRP chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMgrp oRgm oChunk =
(
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"FOLDMESH": Corsix_RgmIntoMax_FoldMesh oRgm oChunk.aChildren[i]
)
i += 1
)
)
/*
Handles a FOLDMESH chunk from an RGM file
oRgm - the RGM file
oChunk - the FOLDMESH chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMesh oRgm oChunk =
(
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"FOLDMGRP": Corsix_RgmIntoMax_FoldMgrp oRgm oChunk.aChildren[i]
"FOLDMRGM": Corsix_RgmIntoMax_FoldMrgm oRgm oChunk.aChildren[i]
"FOLDTRIM": Corsix_RgmIntoMax_FoldTrim oRgm oChunk.aChildren[i]
)
i += 1
)
)
/*
Handles a FOLDTRIM chunk from an RGM file
oRgm - the RGM file
oChunk - the FOLDMESH chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldTrim oRgm oChunk =
(
iDataDataCount = 0
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"DATADATA":
if iDataDataCount == 0 then
(
Corsix_RgmIntoMax_FoldTrim_DataData oRgm oChunk.aChildren[i] oChunk.sName
iDataDataCount = 1
)
)
i += 1
)
)
/*
Handles a FOLDSKEL chunk from an RGM file (Skeleton data)
oRgm - the RGM file
oChunk - the FOLDSKEL chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMesh_FoldSkel oRgm oChunk =
(
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"DATABONE": Corsix_RgmIntoMax_FoldMesh_FoldSkel_DataBone oRgm oChunk.aChildren[i]
)
i += 1
)
)
/*
Handles a DATABONE chunk from an RGM file (Bone data)
oRgm - the RGM file
oChunk - the DATABONE chunk
sName - the name of the bone
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMesh_FoldSkel_DataBone oRgm oChunk sName =
(
fseek oRgm.fFile (oChunk.iDataPosition + 1) #seek_set -- jump to chunk
)
/*
Handles a FOLDMTRL chunk from an RGM file
oRgm - the RGM file
oChunk - the FOLDMTRL chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMtrl oRgm oChunk =
(
/*
Handles a DATAINFO chunk from an RGM file (Shader Names)
oRgm - the RGM file
oChunk - the DATAINFO chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMtrl_DataInfo oRgm oChunk =
(
fseek oRgm.fFile oChunk.iDataPosition #seek_set -- jump to chunk
local iStrLen = ReadLong oRgm.fFile #unsigned
sShaderName = Corsix_ReadStringN oRgm.fFile iStrLen -- read the shader name
print (" Shader: " + sShaderName as string + "\n") -- and spit it inot the listener
)
/*
Handles a DATAVAR chunk from an RGM file (Material Variables)
oRgm - the RGM file
oChunk - the DATAVAR chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldMtrl_DataVar oRgm oChunk =
(
fseek oRgm.fFile oChunk.iDataPosition #seek_set -- jump to chunk
local iStrLen = ReadLong oRgm.fFile #unsigned
sTexType = Corsix_ReadStringN oRgm.fFile iStrLen
Print (" Texture type: " + sTexType as string)
fseek oRgm.fFile 4 #seek_cur -- skip unknown 4 bytes
local iStrLen = ReadLong oRgm.fFile #unsigned
sTexPath = Corsix_ReadStringN oRgm.fFile iStrLen
if sTexType != "camouflagecolour" and sTexType != "teamcolour" and sTexType != "diffuse_offsetu" and sTexType != "diffuse_offsetv" and sTexType != "dirtvisibility" and sTexType != "diffuseOffsetScale" and sTexType != "material_specular" and sTexType != "material_specularExp" then -- these ones don't have texture paths. Just colour values, offset values etc.
(
Print (" Path: " + sTexPath as string + "\n")
)
texturepath = (sCohPath as string + "\\DataSrc\\" + sModFolder as string + "\\" + sTexPath + ".tga") -- construct the texture path
texture_map = bitmaptexture filename:texturepath -- new bitmap texture to hold our newly read path
case sTexType of
(
"diffusetex": oMaterial.diffusetex = texture_map -- only handle the ones that have texture paths
"normalmap": oMaterial.normalmap = texture_map
"teamtex": oMaterial.teamtex = texture_map
"occlusiontex": oMaterial.occlusiontex = texture_map
"glosstex": oMaterial.glosstex = texture_map
"speculartex": oMaterial.speculartex = texture_map
)
global mCorsixMaterial = standardMaterial diffuseMap: oMaterial.diffusetex name:(aMatIDArray[aMatIDArray.count] as string) specularMap:oMaterial.speculartex glossinessMap:oMaterial.glosstex showInViewport:true
mCorsixMultiMat[mCorsixMultiMat.numsubs] = mCorsixMaterial
mCorsixMultiMat.names[mCorsixMultiMat.numsubs] = aMatIDArray[aMatIDArray.count]
setMeditMaterial 1 mCorsixMultiMat -- set mCorsixMultiMat to slot one in the ME
)
local i = 1
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"DATAVAR": Corsix_RgmIntoMax_FoldMtrl_DataVar oRgm oChunk.aChildren[i]
"DATAINFO": Corsix_RgmIntoMax_FoldMtrl_DataInfo oRgm oChunk.aChildren[i]
)
i += 1
)
)
/*
Handles a FOLDMODL chunk from an RGM file
oRgm - the RGM file
oChunk - the FOLDMODL chunk
returns - nothing
*/
fn Corsix_RgmIntoMax_FoldModl oRgm oChunk =
(
local i = 1
local iMatID = 0
while i <= oChunk.iChildCount do
(
case oChunk.aChildren[i].sType of
(
"FOLDMESH": Corsix_RgmIntoMax_FoldMesh oRgm oChunk.aChildren[i]
"FOLDSKEL": Corsix_RgmIntoMax_FoldMesh oRgm oChunk.aChildren[i]
"FOLDMTRL":
(
iMatID += 1
Print "----------------------------------------------"
print (" Material ID Name: " + oChunk.aChildren[i].sName as string)
append aMatIDArray oChunk.aChildren[i].sName
print (" Material ID: " + iMatID as string)
struct sShaderTexturesStruct
(
diffusetex = noMaterial(), -- noMaterial() will set the texture to 'none in the ME. Other wise we will get undefined errors
teamtex = noMaterial(),
normalmap = noMaterial(),
occlusiontex = noMaterial(),
glosstex = noMaterial(),
speculartex = noMaterial()
)
global oMaterial = sShaderTexturesStruct() -- an object to hold each material as we read them
Corsix_RgmIntoMax_FoldMtrl oRgm oChunk.aChildren[i] -- handle the FOLDMTRL and its sub chunks
mCorsixMultiMat.numsubs += 1 -- another one please!
Print "----------------------------------------------"
)
)
i += 1
)
)
/*
Handles an RGM file
oRgm - the RGM file
returns - nothing
*/
fn Corsix_RgmIntoMax oRgm =
(
local i = 1
while i <= oRgm.iChunkCount do
(
case oRgm.aChunks[i].sType of
(
"FOLDMODL": Corsix_RgmIntoMax_FoldModl oRgm oRgm.aChunks[i]
)
i += 1
)
)
/*
Cleans up the scene after import
*/
fn Corsix_RgmIntoMax_SceneCleanup oRgm =
(
mCorsixMultiMat.numsubs -= 1 -- remove empty multimaterial stub
viewport.setLayout #layout_1 -- set all sorts of viewport related things
viewport.setType #view_persp_user
viewport.SetRenderLevel #smooth
viewport.SetShowEdgeFaces true
max tool zoomextents all
if iDataDataCount != 0 then
(
Print (sModelName as string + " imported successfully!")
)
else
(
messagebox "All meshes X-Reffed. No meshes to be loaded in file." title:"RGM importer"
)
)
/*
Cleans up the scene after directory and recursive directory import
*/
fn Corsix_RgmIntoMax_SceneCleanup_DirImport oRgm =
(
mCorsixMultiMat.numsubs -= 1 -- remove empty multimaterial stub
viewport.setLayout #layout_1 -- set all sorts of viewport related things
viewport.setType #view_persp_user
viewport.SetRenderLevel #smooth
viewport.SetShowEdgeFaces true
max tool zoomextents all
if iDataDataCount != 0 then
(
Print (sModelName as string + " imported successfully!")
)
else
(
(Print "Import failed. All meshes X-REFFED. No meshes to load in file: " + sModelName as string)
)
)
/*
Recursively gets all RGM files under the root directory (from maxscript docs. No use in reinventing the wheel)
*/
fn Corsix_RgmIntoMax_RecDirFileFind dirRecDir =
(
aDirectories = GetDirectories (dirRecDir + "/*")
for d in aDirectories do
(
join aDirectories (GetDirectories (d + "/*"))
)
aFiles = #()
for f in aDirectories do
(
join aFiles (getFiles (f + "*.rgm"))
)
return aFiles
)
/*
Graphical user interface stuff
*/
utility Corsix_RGM_Import "RGM Import" width:166 height:137
(
button btn_RGM_Import "Import RGM" pos:[13,5] width:140 height:21 toolTip:"Import an RGM file"
button btn_Dir_Import "RGM Directory Import" pos:[13,32] width:140 height:21 toolTip:"Import all RGM files in a folder"
button btn_RecDir_Import "Recursive Directory Import" pos:[13,58] width:140 height:21 toolTip:"Import RGM files from a directory recursively"
button btn_Set_CoH_Directory "Set CoH Dir" pos:[13,84] width:140 height:21 toolTip:"Set the location of your Company of Heroes directory"
button btn_Set_Mod_Directory "Set Mod Dir" pos:[13,110] width:140 height:21 toolTip:"Set the location of your mod directory"
on btn_RGM_Import pressed do
(
ClearListener()
global sModelName = ""
global iDataDataCount = 0 -- global variable to check if there are any DATADATA chunks in a file
global aMatIDArray = #() -- global array to hold materials and their IDs
global mCorsixMultiMat = MultiMaterial numsubs:1 -- a nice new multimaterial
global sCohPath = getINISetting (Corsix_RGMImportIni()) "Directories" "Company_Of_Heroes" -- load various bits of info from the ini file
global sModFolder = getINISetting (Corsix_RGMImportIni()) "Directories" "Mod_Folder"
global sLastFile = getINISetting (Corsix_RGMImportIni()) "Files" "Last_File"
local sFilename = getOpenFileName caption:"Select a RGM file to import" filename:sLastFile types:"RGM (*.rgm)|*.rgm"
if sFilename != undefined then
(
setINISetting (Corsix_RGMImportIni()) "Files" "Last_File" sFilename
sModelName = getFilenameFile sFilename
local oRgm = Corsix_Chunky() -- Yay! New object!
if (oRgm.loadFromFile sFilename) == false then -- Boo. We failed.
(
messagebox "Unable to load file"
)
else
(
resetMaxFile #noPrompt -- reset max
if sCohPath != undefined then
(
local sSavePath = getSavePath caption:"Select a where you want to save your file" initialDir:sCohPath
if sSavePath != undefined then
(
Makedir (sSavePath + "Model\\")
Makedir (sSavePath + "Animations\\")
Corsix_RgmIntoMax oRgm -- IMPORT!
Corsix_RgmIntoMax_SceneCleanup oRGM -- contains all the post import functions
SaveMaxfile (sSavePath + "Model\\Reference.max")
)
else
(
messagebox "The model will be loaded but not saved" title:"RGM importer" -- Ah! The joys of messageboxes!
Corsix_RgmIntoMax oRgm
Corsix_RgmIntoMax_SceneCleanup oRGM
)
)
else
(
messagebox "Please locate your Company of Heroes directory and try again" title:"RGM importer"
)
)
)
)
on btn_Dir_Import pressed do
(
ClearListener()
global sModelName = ""
global iDataDataCount = 0 -- global variable to check if there are any DATADATA chunks in a file
global aMatIDArray = #() -- global array to hold materials and their IDs
global mCorsixMultiMat = MultiMaterial numsubs:1 -- a nice new multimaterial
global sCohPath = getINISetting (Corsix_RGMImportIni()) "Directories" "Company_Of_Heroes" -- load various bits of info from the ini file
global sModFolder = getINISetting (Corsix_RGMImportIni()) "Directories" "Mod_Folder"
global sLastFile = getINISetting (Corsix_RGMImportIni()) "Files" "Last_File"
local sRgmImportFolder = getSavePath caption:"Locate folder to import RGMs from..." initialDir:sCohPath
local sRgmSaveFolder = getSavePath caption:"Locate location to save loaded files..." initialDir:sCohPath
if sRgmImportFolder != undefined and sRgmSaveFolder != undefined then
(
aRgmImportFiles = getFiles (sRgmImportFolder + "\\*.RGM")
for fFile in aRgmImportFiles do
(
sModelName = getFilenameFile fFile
local oRgm = Corsix_Chunky()
if (oRgm.loadFromFile fFile) == false then -- Boo. We failed.
(
messagebox "Unable to load file"
)
else -- it worked
(
resetMaxFile #noPrompt
if sCohPath != undefined then
(
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\")
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\Model\\")
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\Animations\\")
Corsix_RgmIntoMax oRgm -- IMPORT!
Corsix_RgmIntoMax_SceneCleanup_DirImport oRGM -- contains directory import specific cleanup functions
SaveMaxfile (sRgmSaveFolder + "\\" + sModelName + "\\Model\\Reference.max")
Print "\n"
)
else
(
messagebox "Please locate your Company of Heroes directory and try again" title:"RGM importer"
)
)
)
resetMaxFile #noPrompt
messagebox "All models imported and saved successfully!" title:"Directory Import"
)
else
(
messagebox "Please locate both the folder to import and the folder to save to and try again." title:"Directory Import"
)
)
on btn_RecDir_Import pressed do
(
ClearListener()
global sModelName = ""
global iDataDataCount = 0 -- global variable to check if there are any DATADATA chunks in a file
global aMatIDArray = #() -- global array to hold materials and their IDs
global mCorsixMultiMat = MultiMaterial numsubs:1 -- a nice new multimaterial
global sCohPath = getINISetting (Corsix_RGMImportIni()) "Directories" "Company_Of_Heroes" -- load various bits of info from the ini file
global sModFolder = getINISetting (Corsix_RGMImportIni()) "Directories" "Mod_Folder"
global sLastFile = getINISetting (Corsix_RGMImportIni()) "Files" "Last_File"
local sRgmImportFolder = getSavePath caption:"Locate top level folder to import RGMs from..." initialDir:sCohPath
local sRgmSaveFolder = getSavePath caption:"Locate location to save loaded files..." initialDir:sCohPath
if sRgmImportFolder != undefined and sRgmSaveFolder != undefined then
(
local aRgmImportFiles = Corsix_RgmIntoMax_RecDirFileFind sRgmImportFolder
for fFile in aRgmImportFiles do
(
sModelName = getFilenameFile fFile
local oRgm = Corsix_Chunky()
if (oRgm.loadFromFile fFile) == false then -- Boo. We failed.
(
messagebox "Unable to load file"
)
else -- it worked
(
resetMaxFile #noPrompt
if sCohPath != undefined then
(
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\")
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\Model\\")
Makedir (sRgmSaveFolder + "\\" + sModelName + "\\Animations\\")
Corsix_RgmIntoMax oRgm -- IMPORT!
Corsix_RgmIntoMax_SceneCleanup_DirImport oRGM -- contains directory import specific cleanup functions
SaveMaxfile (sRgmSaveFolder + "\\" + sModelName + "\\Model\\Reference.max")
Print "\n"
)
else
(
messagebox "Please locate your Company of Heroes directory and try again" title:"RGM importer"
)
)
)
resetMaxFile #noPrompt
messagebox "All models imported and saved successfully!" title:"Recursive Directory Import"
)
else
(
messagebox "Please locate both the folder to import and the folder to save to and try again." title:"Recursive Directory Import"
)
)
on btn_Set_CoH_Directory pressed do
(
local sCohPath = getSavePath caption:"Locate Company of Heroes directory"
if sCohPath != undefined then
(
setINISetting (Corsix_RGMImportIni()) "Directories" "Company_Of_Heroes" sCohPath
)
)
on btn_Set_Mod_Directory pressed do
(
local sCohFolder = getINISetting (Corsix_RGMImportIni()) "Directories" "Company_Of_Heroes"
local sModFolder = getSavePath "Locate mod directory" sCohFolder
if sModFolder != undefined then
(
local aModFolder = filterString sModFolder "\\"
sModFolder = aModFolder[aModFolder.count]
setINISetting (Corsix_RGMImportIni()) "Directories" "Mod_Folder" sModFolder
)
)
)