-- SleepyZay --

fn ReadFixedString bstream fixedLen = (
   local str = ""
   For i = 1 to fixedLen do
   (
      str0 = ReadByte bstream #unsigned
      If str0!=0xFD AND str0!=0xFC do str+= bit.intAsChar str0
   )
   str
)
fn addHexaDecimalPadding nr = (
	case of (
		(nr <= 15): ("0" + ((bit.intAsHex(nr))as string))
		(nr > 15): ((bit.intAsHex(nr))as string)
	)
)	
fn ReadFixedByteString bstream fixedLen = (
   local str = ""
   For i = 1 to fixedLen do
   (
      str += addHexaDecimalPadding (ReadByte bstream #unsigned)
	  If mod i 1 == 0 do str += " "
   )
   str
   print str
)
fn GetName bstream Offset = (
	fseek bstream Offset #seek_set
	MeshName = readstring bstream
	return MeshName
)
fn Readword fstream = (
return readshort fstream #unsigned
)
fn FindNumofOcurrences narray num = (
	j=0
	for i in narray do (
		if i == num do j+=1
	)
	return j
)
fn paddstring len instring = (
	instring=instring as string
	local str=""
	if instring.count <=len then (
		for i = 1 to (len-instring.count) do(
			str+="0"
		)
		str = (str+instring)
	)
	else (
		for i = 1 to len do(
			str+="0";str[i]=instring[i]
		)
	)
	str
)
fn ApplyNormals amesh nArr toggle= (
	max modify mode
	cui.expertModeOn()

	with redraw off (
	   --your import code
		
	   for face = 1 to amesh.numfaces do setFaceSmoothGroup amesh face 1
		
	   select amesh
	   addmodifier amesh (Edit_Normals ()) ui:off
	   amesh.Edit_Normals.MakeExplicit selection:#{1..nArr.count}
	   EN_convertVS = amesh.Edit_Normals.ConvertVertexSelection
	   EN_setNormal = amesh.Edit_Normals.SetNormal
	   normID = #{}
		
	   for v = 1 to nArr.count do
	   (
		  free normID
		  EN_convertVS #{v} &normID
		  for id in normID do EN_setNormal id nArr[v]
	   )
	   
	   if toggle == 1 do collapseStack amesh
	)

	cui.expertModeOff()
)
fn SplitLayout Split =(
	str=""
	j=0
	for i in Split do (
		j+=1
		if j >1 do (
			str += i
			if j != Split.count do str += "_" 
		)
	)
	str
)
fn PrintFileCount Files= (
	If Files.count == 1 then (print ((Files.Count as string)+ " File"))
	Else(print ((Files.Count as string)+ " Files"))
)

fname = GetOpenFileName caption:"" types:"(.)|*.geo"
If (fname!=undefined) and ((DoesFileExist fname)==true) then (
f = fopen fname "rb"   --open file in read only format
clearlistener()
Global fscale=100

FilePath = GetFilenamePath fname
Leaf = pathConfig.removePathLeaf fname
ParentFolder = pathConfig.removePathLeaf Leaf
FileExtension = getFileNameType fname
UVFolder = ParentFolder + "\MeshVolatile\\"
FileName = getFileNameFile fname

Split = filterString FileName "_"
UVID= ((Split[1] as number)+1)
Rest = SplitLayout (Split)
UVPath = (UVFolder + (paddstring 4 (UVID as string)) + "_" + Rest + ".geo")
-- print UVPath as string
-- format "\n"


delete $*
Print "===================================="
print (FileName + FileExtension) as string
Print "===================================="
--)

Ext_UV = false
-- print uvpath as string
If  (UVPath!=undefined) and ((DoesFileExist UVPath)==true) do (
-- print "true"
	Ext_UV = true
	g = fopen UVPath "rb"
	print g as string
)

Magic = readfixedstring f 4
Ukw = readlong f	-- always 0x32
Ukw2 = readlong f	-- always 0x3
fseek f 0x14 #seek_cur	-- bunch of shit

ModelNameOffset = readlong f #unsigned
Ukw3 = readlong f
fseek f 0xc #seek_cur

TableCount = readlong f
Ukw4 = readlong f	-- always 0x83
fseek f 0xc #seek_cur	-- look at later, may be important

UkwTableCount=readlong f
UkwTable=readlong f

DataTable1=readlong f
UkwTable2=readlong f
fseek f 0x08 #seek_cur

UkwBuffer=readlong f	-- looks like uv's
null = readlong f
DataTable2=readlong f
ukw3=readlong f		--always 40 more than datatable2

fseek f 0x9c #seek_set
UVOffsetLocal = readlong f


-- 				print ("Table count is "+((TableCount)as string))	
-- 				print ("DataTable 1 offset is 0x"+((bit.intAsHex(DataTable1))as string))
-- 				print ("DataTable 2 offset is 0x"+((bit.intAsHex(DataTable2))as string))
-- 				format "\n"

MeshNameOffset=#()
VertCount=#()
VertSize=#()
VertOffset=#()
VertID=#()
UVSize=#()
FaceOffset=#()
FaceCount=#()
LodType=#()

fseek f DataTable1 #seek_set	
For x=1 to TableCount do (
-- 					Print "===================================="------------------------------
-- 					Print (("Table "+((x)as string))+("					   0x"+(bit.intAsHex(ftell f))))
-- 					Print "===================================="------------------------------
	
	MeshNameOffset[x]=readlong f 
	backjump = ftell f
	fseek f MeshNameOffset[x] #seek_set
	print (readstring f)
	fseek f backjump #seek_set
	fseek f 0x4 #seek_cur	-- data, look into
	null = readlong f
	fseek f 0x14 #seek_cur
	TableOffset = readlong f
	ukw2=readshort f
	_0x14 = readbyte f	-- always 0x14
	UVSize[x]=readbyte f
	fseek f 0x08 #seek_cur
	
	FaceCount[x]=readlong f 
	null=readlong f 
	VertCount[x]=readshort f 
	ukwcount = readshort f
	LodType[x]=readshort f 	--determines whether or not its a lod model and uses tristrips.  5 If it is, 4 If it isnt
	ukw4 = readlong f 	-- looks like an offset
	ukw5 = readshort f
	ukwOffset=readlong f 
	fseek f 0x1c #seek_cur	-- blank
	ReadFixedByteString f 0xc
	fseek f (-12) #seek_cur
	VertSize[x]=readlong f	--	-1 For vertsize of 0x20,  Else For 0x14
	Ukw6 = readlong f
	VertID[x] = readlong f
	fseek f 0xc #seek_cur
	null = readlonglong f
	VertOffset[x]=readlong f 
	FaceOffset[x]=readlong f 
	fseek f 0x34 #seek_cur
	
-- 					Print ("Vertex offset is 0x"+((bit.intAsHex(VertOffset[x]))as string))
-- 					Print ("Vertex size is "+(VertSize[x]as string))
-- 					Print ("Lod type is 0x"+((bit.intAsHex(LodType[x]))as string))
	/*
	
	
	Print ("Vertex count is 0x"+((bit.intAsHex(VertCount[x]))as string))
	Print ("Face count is 0x"+((bit.intAsHex(FaceCount[x]))as string))
	Print ("Face offset is 0x"+((bit.intAsHex(FaceOffset[x]))as string))
	*/
)
format "\n"

UniqueID_array = makeUniqueArray VertID	-- array of all ID's w/o duplications
-- 				print ("VertID = "+(VertID)as string)
print ("UniqueID_array = "+(UniqueID_array)as string)

BaseVertArray=#()
BaseNormalArray=#()
BaseFaceArray=#()
BaseUVArray=#()
UVBufferSize=#()
BaseUVOffsetArray=#()
MeshNameArray=#()

For x=1 to UniqueID_array.count do (
	append BaseVertArray(#())
	append BaseUVArray(#())
	append BaseUVOffsetArray(0)
	append UVBufferSize(0)
	append BaseNormalArray(#())
	append BaseFaceArray(#())
	append MeshNameArray(#())
)

-- 				format "\n"
-- 				print ("BaseVertArray = "+(BaseVertArray)as string)	-- an array of all the verts. where an element would an array of all verts of the same id. each id consisting of an array of each individual vert buffer.
-- 				print ("BaseFaceArray = "+(BaseFaceArray)as string)
-- 				print ("MeshNameArray = "+(MeshNameArray)as string)
print ("UVBufferSize = "+(UVBufferSize)as string)
print ("BaseUVOffsetArray = "+(BaseUVOffsetArray)as string)


j=0
For a in BaseFaceArray do (
	j+=1
	For x=1 to (FindNumofOcurrences VertID UniqueID_array[j]) do (
		append a (#())
	) 
)

-- 				format "\n"
-- 				print ("BaseVertArray after = "+(BaseVertArray)as string)
-- 				print ("BaseFaceArray after = "+(BaseFaceArray)as string)
-- print ("MeshNameArray after = "+(MeshNameArray)as string)



-- Getting UV buffer size associated by vert id
For x=1 to TableCount do (
	GetUniqueIDElement = FindItem UniqueID_array VertID[x]
	
	If Ext_UV == true then (						
		Case UVSize[x] of (
			
			(0x8):(
				UVBufferSize[GetUniqueIDElement] += (VertCount[x] * 0x8)
			)
			(0xc):(
				UVBufferSize[GetUniqueIDElement] += (VertCount[x] * 0xc)
			)
			(0x10):(
				UVBufferSize[GetUniqueIDElement] += (VertCount[x] * 0x10)
			)
			(0x14):(
				UVBufferSize[GetUniqueIDElement] += (VertCount[x] * 0x14)
			)
			(0x1c):(
				UVBufferSize[GetUniqueIDElement] += (VertCount[x] * 0x1c)
			)
			
		)
	)
)

-- Setting the initial offset of the vert id's uv buffer
addto = 0
For x=2 to (UniqueID_Array.count ) do (
	BaseUVOffsetArray[x] += UVBufferSize[x-1] + addto
	addto = BaseUVOffsetArray[x] 
)

format "\n"
print ("BaseUVOffsetArray updated = "+(BaseUVOffsetArray)as string)
print ("UVBufferSize updated = "+(UVBufferSize)as string)
format "\n"

UV_array=#()
UV_Offset = 0
For x=1 to TableCount do ( --should be tablecount
	
	Vert_array=#()
	Normal_array=#()
	Face_array=#()
	
	Tri_strip = false
	
	-- Building Vertices --
	fseek f VertOffset[x] #seek_set
	
	GetUniqueIDElement = FindItem UniqueID_array VertID[x]	-- getting the index position of the basevertarray based on the current table's id
-- 	print GetUniqueIDElement	-- this would be 1
-- 					format "\n"
	
	Case VertSize[x] of (
		
		(-1): (
			
-- 							print "x20"
-- 							print "Tri Lists"
			
			For y = 1 to VertCount[x] do(
				vx=readfloat f
				vy=readfloat f
				vz=readfloat f
				nx=readword f
				ny=readword f
				nz=readword f
				fseek f 0xe #seek_cur
				append BaseVertArray[GetUniqueIDElement]([vx*-1,vz,vy]*fscale)
				append BaseNormalArray[GetUniqueIDElement]([nx*-1,nz,ny]*fscale)
				append UV_array[0,0,0]
				
			)
			
		)
		
		default:(
			Case LodType[x] of (
				(4):(
-- 									print "x14"
-- 									print "Tri Lists"
					
					for x = 1 to VertCount[x] do(
						vx=readfloat f
						vy=readfloat f
						vz=readfloat f
						nx=readword f
						ny=readword f
						nz=readword f
						fseek f 0x2 #seek_cur
						append BaseVertArray[GetUniqueIDElement]([vx*-1,vz,vy]*fscale)
						append UV_array[0,0,0]
					)
				)
				
				(5):(
-- 									print "x0c"
-- 									print "Tri Strips"
					Tri_Strip = true
					
					for x = 1 to VertCount[x] do(
						vx=readfloat f
						vy=readfloat f
						vz=readfloat f
						append BaseVertArray[GetUniqueIDElement]([vx*-1,vz,vy]*fscale)
						append UV_array[0,0,0]
					)
				)
				
				default: Throw "Lod type unrecognized"
			)
		)
	)
	
	-- Reading UV's --
	If Ext_UV == true then (
		Print "External UV's"
-- 						fseek g UV_Offset #seek_set
		fseek g BaseUVOffsetArray[GetUniqueIDElement] #seek_set
		print (bit.intashex(UVSize[x]) as string)
-- 						append UV_array[0,0,0]
		
		Case UVSize[x] of (
			
			(0x8):(
				For y=1 to VertCount[x] do (
					tu = readfloat g
					tv = readfloat g
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]		
				)
				Print ("Last Read g @ 0x"+((bit.intAsHex(ftell g))as string))
			)
			(0xc):(
				For y=1 to VertCount[x] do (
					tu = readfloat g
					tv = readfloat g
					tw = readfloat g
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]
				)
				Print ("Last Read g @ 0x"+((bit.intAsHex(ftell g))as string))
			)
			(0x10):(
				For y=1 to VertCount[x] do (
					tu = readfloat g
					tv = readfloat g
					fseek g 0x8 #seek_cur
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]
				)
				Print ("Last Read g @ 0x"+((bit.intAsHex(ftell g))as string))
			)
			(0x14):(
				For y=1 to VertCount[x] do (
					tu = readfloat g
					tv = readfloat g
					fseek g 0xc #seek_cur
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]		
				)
				Print ("Last Read g @ 0x"+((bit.intAsHex(ftell g))as string))
			)
			(0x1c):(
				For y=1 to VertCount[x] do (
					tu = readfloat g
					tv = readfloat g
					tw = readfloat g
					fseek g 0x10 #seek_cur
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]
				)
				Print ("Last Read g @ 0x"+((bit.intAsHex(ftell g))as string))
			)
			
		)
	)
	Else (
		print "Local UV's"
		fseek f UVOffsetLocal #seek_set
		print (bit.intashex(UVSize[x]) as string)
-- 						append UV_array[0,0,0]
		
		Case UVSize[x] of (
			
			(0xc):(
				For y=1 to VertCount[x] do (
					tu = readfloat f
					tv = readfloat f
					tw = readfloat f
					append BaseUVArray[GetUniqueIDElement][tu,tv*-1,tw]
				)
				Print ("Last Read uv @ 0x"+((bit.intAsHex(ftell f))as string))
			)
			(0x8):(
				For y=1 to VertCount[x] do (
					tu = readfloat f
					tv = readfloat f
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]		
				)
				Print ("Last Read uv @ 0x"+((bit.intAsHex(ftell f))as string))
			)
			(0x14):(
				For y=1 to VertCount[x] do (
					tu = readfloat f
					tv = readfloat f
					fseek f 0xc #seek_cur
					append BaseUVArray[GetUniqueIDElement][tu,1-tv,0]		
				)
				Print ("Last Read uv @ 0x"+((bit.intAsHex(ftell f))as string))
			)
			
		)
	)
-- 					UV_Offset = ftell g
	BaseUVOffsetArray[GetUniqueIDElement] = ftell g
	
	-- Building Indices --
	fseek f FaceOffset[x] #seek_set
	
	j=0	-- Getting the index value of the first empty array
	For a in BaseFaceArray[GetUniqueIDElement] do (
		j+=1
		if a.count == 0 then exit
	)
-- 					print ("j is "+(j)as string)
	
	If Tri_Strip == true then (
		facestart = (ftell f)
		StartDirection = 1	--was -1
		f1 = (Readword f) + 1
		f2 = (Readword f) + 1  
		FaceDirection = StartDirection
		Do (
			f3 = (Readword f)
			if (f3==0xFFFF) then (
				f1 = (Readword f) + 1
				f2 = (Readword f) + 1
				FaceDirection = StartDirection   
			)
			else (
				f3 += 1
				FaceDirection *= -1
				if (f1!=f2)AND(f2!=f3)AND(f3!=f1) then (
					if FaceDirection > 0 then append BaseFaceArray[GetUniqueIDElement][j] [f1,f2,f3]
					else append BaseFaceArray[GetUniqueIDElement][j] [f1,f3,f2]
				)
				f1 = f2
				f2 = f3
			)  
		)
		while (ftell f) < (facestart + (FaceCount[x]*2))	
	)
	Else (
		for y = 1 to FaceCount[x]/3 do (
			fa = (readword f) + 1
			fb = (readword f) + 1
			fc = (readword f) + 1
			append BaseFaceArray[GetUniqueIDElement][j] [fa,fb,fc]
		)
	)
	
	MeshNameArray[GetUniqueIDElement][j] = GetName f MeshNameOffset[x]
	
-- 	print BaseVertArray[2]
-- 	print BaseFaceArray[1]
	
)

For x=1 to UniqueID_Array.count do (
	
	For y=1 to BaseFaceArray[x].count do (
		msh = mesh vertices:BaseVertArray[x] faces:BaseFaceArray[x][y]
		msh.numTVerts = UV_array.count
		msh.wirecolor = random black white
		msh.name = MeshNameArray[x][y]
		buildTVFaces msh
		for j = 1 to BaseUVArray[x].count do setTVert msh j BaseUVArray[x][j]
		for j = 1 to BaseFaceArray[x][y].count do setTVFace msh j BaseFaceArray[x][y][j]
		meshop.deleteIsoVerts msh
		
		bar = filterString MeshNameArray[x][y] "_"
		if bar.count == 4 and bar[3].count == 4 do (
-- 							print bar
			delete msh
		)
		
-- 						ApplyNormals msh BaseNormalArray[x] 0
-- 						select msh
-- 						convertTo $ PolyMeshObject
-- 						$.EditablePoly.deleteIsoVerts ()
-- 						convertTo $ TriMeshGeometry
-- 						modPanel.addModToSelection (smooth ()) ui:on
-- 						$.modifiers[#Smooth].autosmooth = on
-- 						deselect msh
		
	)
	
)









Print ("Last Read @ 0x"+((bit.intAsHex(ftell f))as string))
)
gc()
fclose f
