-- --------------------------------------------------------------------------------------
--
-- .x Exporter
-- Ben Kenwright
-- Email: bkenwright@xbdev.net
--
-- --------------------------------------------------------------------------------------

fn writeTOKEN_NAME f str=
(
	writeshort f 1		       -- // U16 - token ID  1
	writelong  f str.count     -- // U32 - Length of name field, in bytes 
						    
	for i = 1 to str.count do  -- // Array U8 - array count ASCII name
	(
	   	c = bit.charAsInt(str[i])
		writebyte f c	
	)
)

fn writeTOKEN_OBRACE f=
(
	writeshort f 10		       -- // U16 - token ID  1
)

fn writeTOKEN_CBRACE f=
(
	writeshort f 11		       -- // U16 - token ID  11
)

fn writeTOKEN_TEMPLATE f=
(
	writeshort f 31		       -- // U16 - token ID  31
)

fn writeTOKEN_DWORD f=
(
	writeshort f 41		       -- // U16 - token ID
)

fn writeTOKEN_SEMICOLON f=
(
	writeshort f 20		       -- // U16 - token ID
)

fn writeTOKEN_ARRAY f=
(
	writeshort f 52		       -- // U16 - token ID
)

fn writeTOKEN_OBRACKET f=
(
	writeshort f 14		       -- // U16 - token ID
)

fn writeTOKEN_CBRACKET f=
(
	writeshort f 15		       -- // U16 - token ID
)

fn writeTOKEN_SEMICOLON f=
(
	writeshort f 20		       -- // U16 - token ID
)

fn writeTOKEN_LPSTR f=
(
	writeshort f 49		       -- // U16 - token ID
)

fn writeTOKEN_DOT f=
(
	writeshort f 18		       -- // U16 - token ID
)

fn writeTOKEN_FLOAT f=
(
	writeshort f 42		       -- // U16 - token ID
)


fn writeTOKEN_INTEGER_LIST f iList iSize=
(
	writeshort f 6		       -- // U16 - token ID  1
	writelong  f iSize         -- // U32 - Number of integers in list field
	
	for i = 1 to iSize do      -- // Array U32 - array integers
	(
		writelong f iList[i]
	) 
)

fn writeTOKEN_FLOAT_LIST f fList iSize=
(
	writeshort f 7		       -- // U16 - token ID  7
	writelong  f iSize         -- // U32 - Number of integers in list field
	
	for i = 1 to iSize do      -- // Array U32 - array integers
	(
		writefloat f fList[i]
	) 
)

fn writeTOKEN_GUID f data=
(
	writeshort  f 5		       -- // U16 - token ID  5
	writeshort  f data[1]
	writeshort  f data[2] 

	writeshort  f data[3]
	writeshort  f data[4]

	for i = 1 to 8 do
	(
		writebyte f data[4 + i]
	)
)

-- --------------------------------------------------------------------------------------

fn writeTemplateFVF f=
(
	writeTOKEN_TEMPLATE 	f
	writeTOKEN_NAME 		f 	"FVFData"
	writeTOKEN_OBRACE   	f

    guid = #(0x0a0e, 0xb6e7, 0x8ef9, 0x4e83, 0x94, 0xad, 0xec, 0xc8, 0xb0, 0xc0, 0x48, 0x97)
    writeTOKEN_GUID			f 	guid
	writeTOKEN_DWORD    	f
	writeTOKEN_NAME			f	"dwFVF"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_DWORD	    f
	writeTOKEN_NAME			f	"nDWords"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_ARRAY		f
	writeTOKEN_DWORD		f
	writeTOKEN_NAME			f	"data"	
	writeTOKEN_OBRACKET		f
	writeTOKEN_NAME			f	"nDWords"
	writeTOKEN_CBRACKET		f
	writeTOKEN_SEMICOLON	f
	writeTOKEN_CBRACE		f
)

fn writeTemplateEffectInstance f=
(
	writeTOKEN_TEMPLATE 	f
	writeTOKEN_NAME			f	"EffectInstance"
	writeTOKEN_OBRACE		f
	
	guid = #(0xf7e4, 0xe331, 0x0559, 0x4cc2, 0x8e, 0x99, 0x1c, 0xec, 0x16, 0x57, 0x92, 0x8f)
	writeTOKEN_GUID			f 	guid
	writeTOKEN_LPSTR		f
	writeTOKEN_NAME			f	"EffectFilename"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_OBRACKET		f
	writeTOKEN_DOT			f
	writeTOKEN_DOT			f
	writeTOKEN_DOT			f
	writeTOKEN_CBRACKET		f
	writeTOKEN_CBRACE		f
)


fn writeTemplateEffectParamFloats f=
(
	writeTOKEN_TEMPLATE		f
	writeTOKEN_NAME			f	"EffectParamFloats"
	writeTOKEN_OBRACE		f
	
	guid = #(0xb9a0, 0x3014, 0x62f5, 0x478c, 0x9b, 0x86, 0xe4, 0xac, 0x9f, 0x4e, 0x41, 0x8b)
	writeTOKEN_GUID			f 	guid
	writeTOKEN_LPSTR		f
	writeTOKEN_NAME			f	"ParamName"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_DWORD		f
	writeTOKEN_NAME			f	"nFloats"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_ARRAY		f
	writeTOKEN_FLOAT		f
	writeTOKEN_NAME			f	"Floats"
	writeTOKEN_OBRACKET		f
	writeTOKEN_NAME			f	"nFloats"
	writeTOKEN_CBRACKET		f
	writeTOKEN_SEMICOLON	f
	writeTOKEN_CBRACE		f
)


fn writeTemplateEffectParamString f=
(

	writeTOKEN_TEMPLATE		f
	writeTOKEN_NAME			f	"EffectParamString"
	writeTOKEN_OBRACE		f

	guid = #(0x4c88, 0x1dbc, 0x94c1, 0x46ee, 0x90, 0x76, 0x2c, 0x28, 0x81, 0x8c, 0x94, 0x81)
	writeTOKEN_GUID			f 	guid
	writeTOKEN_LPSTR		f
	writeTOKEN_NAME			f	"ParamName"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_LPSTR		f
	writeTOKEN_NAME			f	"Value"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_CBRACE		f
)


fn writeTemplateEffectParamDWord f=
(
	writeTOKEN_TEMPLATE		f
	writeTOKEN_NAME			f	"EffectParamDWord"
	writeTOKEN_OBRACE		f

	guid = #(0x63bc, 0xe139, 0xae51, 0x4c5d, 0xb0, 0x0f, 0xcf, 0xa3, 0xa9, 0xd9, 0x7c, 0xe5)
	writeTOKEN_GUID			f 	guid
	writeTOKEN_LPSTR		f
	writeTOKEN_NAME			f	"ParamName"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_DWORD		f
	writeTOKEN_NAME			f	"Value"
	writeTOKEN_SEMICOLON	f
	writeTOKEN_CBRACE		f
)

-- --------------------------------------------------------------------------------------


fn writemesh f obj=
(
    writeTOKEN_NAME   		f "Mesh"
	writeTOKEN_NAME   		f "Box01"
	writeTOKEN_OBRACE 		f
	
	
	a = #()
	a[1] = obj.numverts
	writeTOKEN_INTEGER_LIST f a 1
	
	j = 1
	verts = #()
	for i=1 to obj.numverts do
	(
		local v=in coordsys world(getvert obj i)
		verts[j] = v.x
		j+=1
		verts[j] = v.y
		j+=1
		verts[j] = v.z
		j+=1
	)
	writeTOKEN_FLOAT_LIST f verts (j-1)
	
	
	j = 1
	indices = #()
	
	indices[j] = obj.numfaces
	j+=1
	
	for i=1 to obj.numfaces do
	(
		indices[j] = 3
		j+=1
		
		i1=((getFace obj i).z)-1
		i2=((getFace obj i).y)-1
		i3=((getFace obj i).x)-1
		
		indices[j] = i1
		j+=1
		indices[j] = i2
		j+=1
		indices[j] = i3
		j+=1
	)
	writeTOKEN_INTEGER_LIST f indices (j-1)
	
	
	writeTOKEN_CBRACE f
)

fn writex obj xfilename=
(
	if obj==undefined do return"No object"
	if (classof obj)!=editable_mesh do return "Object is not a mesh"
	
	f=fopen xfilename "wb"

	magic  = 0x20666F78 -- "xof "
	version= 0x33303330 -- "0303"
	type   = 0x206E6962 -- "bin "
	acc    = 0X32333030 -- "0032"

	writelong f magic
	writelong f version
	writelong f type
	writelong f acc    
	
	writeTemplateFVF f
	writeTemplateEffectInstance f
	writeTemplateEffectParamFloats f
	writeTemplateEffectParamString f
	writeTemplateEffectParamDWord  f
	
	writemesh f obj
	
	fclose f
)

-- --------------------------------------------------------------------------------------

fn addcheck cb=
(
 	if classof cb==string do messagebox cb title:"DirectX .X Export Error"
)

-- --------------------------------------------------------------------------------------

utility XExport ".x Mesh Exporter"
(
	group "Export"
	(
		button bexport "     Export    "
	)
	group "About"
	(
		label titleLabel	".x Mesh Exporter v0.01"
		HyperLink addy "by Ben Kenwright" align:#center address:"mailto:bkenwright@xbdev.net" color:(color 0 100 0) hoverColor:(color 0 0 100)
		HyperLink me "HomePage" align:#center address:"www.xbdev.net" color:(color 0 100 0) hoverColor:(color 0 0 100)

	)
	
	on bexport pressed do
	( 
		xfilename=getsavefilename caption:"Save .x" \
			filename:xlastfile \
			types:"DirectX .X (*.x)|*.x|All Files (*.*)|*.*|"
		if xfilename!=undefined do 
		(				
			addcheck (writex $ xfilename)
			xlastfile=xfilename
		)
	)
)


