Home Unreal Engine

FBXport a maxscript to help automate exporting files to UDK

I got tired of constantly moving objects to 0 0 0 to export for UDK and remembering to do a few other things like triangulate the model and rename the material, so I wrote this maxscript.



With one button "FBXport" does:
  • Records the objects current position.
  • Moves it to 0 0 0.
  • Triangulates the model by adding a turn to poly modifier set to 3 sides.
  • Renames the material to match the object name.
  • Triggers the FBX export and sends it to a new folder called "Exports" which is in the same place as your max file.
  • Moves the object back to its original position.


How To Install:

Open max and go Main Menu > Maxscript > Run script > FBXport.ms
It can now be found in Main Menu > Customize > Category: VigTools
From there you can assign it to a keyboard shortcut, toolbar or quad menu.

You can also drag the main body of the script (below) into your tool bar to make a button.
You can then right click that button and change its appearance.
macroScript FBXport
Category:"VigTools"
toolTip:"FBXport" 
buttonText:"FBXport"
(
	ClearListener()
	gc()
	Global UnrealDisplayName
	Global ForceNameState
	Global TriangulateState
	
	Global UnrealPath = (maxFilePath + "\\FBX\\")

	Global Roll_FBXport
	Try (
		cui.unRegisterDialogBar Roll_FBXport
		Destroydialog Roll_FBXport
	) 
	catch()
	
	fn WriteINI = (
			idxname = ((getdir #userscripts) + "\\FBXport.ini")
			idxfile = createfile idxname
			format (UnrealPath as string + "\n") to:idxfile
			format (ForceNameState as string + "\n") to:idxfile
			format (TriangulateState as string + "\n") to:idxfile
			format (UnrealDisplayname as string + "\n") to: idxfile
			close idxfile
		)
	fn ReadINI = (
		if doesFileExist ((getdir #userscripts) + "\\FBXport.ini")  == false then (
			print "ReadINI was FALSE"
			UnrealPath =  "Please Set Path"
			ForceNameState = false
			TriangulateState = false
			UnrealDisplayname = "None"
			return false
		)
		else (
			ClearListener()
			Print "ReadINI was Success"
			idxname = openfile ((getdir #userscripts) + "\\FBXport.ini") mode:"r"
			while not eof idxname do (
				UnrealPath = readLine idxname as string
				ForceNameState = readLine idxname as string
				TriangulateState = readLine idxname as string
				UnrealDisplayName = readLine idxname as string
			)
			close idxname
			return true
		)	
	)
	ReadINI()
	
	fn ERRORSetProjectPath =	messagebox "Project path needs to be set first." Title: "INI READ ERROR"
	
	rollout Roll_FBXport "FBXport v1.04" width:280 height:33
	(
		edittext edt_UnrealPath "" pos:[47,7] width:136 height:16
		button btn_UnrealPath "..." pos:[186,7] width:24 height:16
		checkbox Chk_Triangulate "Tri?" pos:[6,16] width:41 height:16
		checkbox chk_forceName "Mat?" pos:[6,0] width:41 height:16
		button btn_export "Export" pos:[215,4] width:56 height:24
		
		fn Refresh = (
			ReadINI()
			UnrealDisplayName = ((pathConfig.stripPathToLeaf UnrealPath + "\\FBX\\"))
			edt_UnrealPath.text = ("...\\" + UnrealDisplayName as string)
			if ForceNameState == "true" then (Chk_ForceName.state = true) else (Chk_ForceName.state = false)
			if TriangulateState == "true" then (Chk_Triangulate.state = true) else (Chk_Triangulate.state = false)
		)

		on Roll_FBXport open do (
			Refresh()
		)
		on edt_UnrealPath changed txt do (
			UnrealPath = edt_UnrealPath.text
			edt_UnrealPath.text = UnrealPath
		)
		on btn_UnrealPath pressed do (
			if UnrealPath == undefined then (
				UnrealPath = (getSavePath caption:(("Select UNREAL Project Path:" + "\n\nExample: ...\My Documents\Unreal Projects\My Project") as string) initialDir:(((dotNetClass "System.Environment").GetEnvironmentVariable "UserProfile") + "\\Documents"))
			)
			else (
				UnrealPath = (getSavePath caption:(("Select UNREAL Project Path:" + "\n\nExample: ...\My Documents\Unreal Projects\My Project") as string) initialDir:(UnrealPath))
				UnrealDisplayName = ((pathConfig.stripPathToLeaf UnrealPath + "\\FBX\\"))
			)
			edt_UnrealPath.text = UnrealDisplayName
			WriteINI()
			Refresh()
		)
		on btn_UnrealPath rightClick do
			(shellLaunch "explorer.exe" (UnrealPath + "\\FBX\\"))
		on Chk_Triangulate changed arg do (
			if MyProjectPath == "Please Set Path" then (
				Refresh()
				ERRORSetProjectPath()
			)
			Else (
				TriangulateState = Chk_Triangulate.state
				WriteINI()
				ReadINI()
				if TriangulateState == "true" then (Chk_Triangulate.state = true) else (Chk_Triangulate.state = false)
			)
		)
		on chk_forceName changed arg do (
			if MyProjectPath == "Please Set Path" then (
				Refresh()
				ERRORSetProjectPath()
			)
			Else (		
				ForceNameState = chk_forceName.state
				WriteINI()
				ReadINI()
				if ForceNameState == "true" then (Chk_ForceName.state = true) else (Chk_ForceName.state = false)
			)
		)
		on btn_export pressed do (
			Cursel = selection as array
			For i=1 to cursel.count do (
				Select CurSel[i]
				curObject  = $
				curObjectName = $.name
				curObjectPos = curObject.position
				exportpath = (UnrealPath + "\\FBX\\" + "\\" + curObjectName)
				
				-- Moves the object to the world 0 0 0 node
				curObject.pos = [0,0,0] 
				
				-- Changes the material name to match the object name
				if chk_ForceName.state == true then (
					if  curObject.material == undefined then (
						Print "Created new material"
						newmat = StandardMaterial()
						newmat.name = CurObject.name 
						CurObject.material = newmat
						
					)
					else (
						print "Mat renamed"
						curObject.material.name = CurObject.name 
					)
				)
				else ()
				
				--Add the "turn to  poly" and limit the number of sides to 3
				if chk_Triangulate.state == true then (
					Print "Triangulated"
					modPanel.addModToSelection (Turn_to_Poly ()) ui:on 
					curObject.modifiers[#Turn_to_Poly].limitPolySize = on 
					curObject.modifiers[#Turn_to_Poly].maxPolySize = 3
				)
				else ()
				 
				exportFile exportpath selectedOnly:true #noPrompt
				
				-- get rid of turn to poly modifier
				if chk_Triangulate.state == true then (
					max modify mode
					deleteModifier curObject 1
				)
				else ()
				
				-- moves object back to original position
				move curObject curObjectPos 
					
				)
			)
	)
	destroydialog Roll_FBXport
	createdialog Roll_FBXport 
	cui.RegisterDialogBar Roll_FBXport style:#(#style_sysmenu,#cui_dock_top,#cui_floatable,#cui_handles,#style_minimizebox) 

)
Feel free to change edit, barrow, hack apart and or modify the script however you need. Also if you know of anything better let me know, I was a little surprised I couldn't find script like this already... but maybe I wasn't looking in the right places.

Replies

  • Shogun3d
    Offline / Send Message
    Shogun3d polycounter lvl 12
    Mr.Dygert

    I salute you.

    *Clicks Download*
  • Shogun3d
    Offline / Send Message
    Shogun3d polycounter lvl 12
    *edit* wait never mind. You have to run the script with an object selected and material applied. Would help if I looked at the script. Thanks again Mark!

    //hmmm, getting an -- Unknown preperty: "name" in undefined
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    there's also Paragon's script (i think it does the world-pivot-nulling thing as well) http://www.alexbarcelo.com/#2121107/Scripts
  • Parkar
    Offline / Send Message
    Parkar polycounter lvl 18
    Here is variation (Or more like loosely based) on Marks script.

    Just a very quick job so far to fit my use for this. Also hardly tested at all. I'll probably add some more to it tomorrow tough.

    Edit: Updated.
    • Exports selected Meshes (Editable Poly and Editable Mesh) or all meshes if nothing is selected as one fbx with the same file name and location as the max file.
    • Path, file name and whether the fbx save dialog is shown can be selected before hitting export.
    • Moves meshes to [0,0,0] and triangulates them
    • Moves and exports the matching collision meshes (UCX_*) together with the exported mesh. Collision meshes dose not have to be selected just match one of the selected meshs.
    • Restores the scene using hold/fetch. Undo levels are lost! Not a problem for me so didn't bother with keeping track of all the changes. Might change this once I stop adding stuff to it.

    Installation and usage is the same as for Marks script.
    -- macroScript UdkExport
    -- Category:"Parkar"
    -- toolTip:"UDK Export"
    -- buttontext:"UDK Export"
    (
    	exportFileName = substituteString maxFileName ".max" ".fbx"
    	exportfolderPath = maxfilepath
    	
    	rollout roll_UdkExport "UdkExport" width:512
    	(
    		label lbl1 "Export Path" align:#left
    		edittext edt_ExportPath "" text:exportfolderPath
    		label lbl2 "File Name" align:#left
    		edittext edt_ExportFile "" text:exportFileName
    		button btn_Export "Export"
    		
    		on btn_Export pressed do ( 
    			
    			-- Save current scene state
    			holdMaxFile()
    			
    			-- create export path
    			exportPathFull = exportfolderPath + exportFileName
    			
    			-- Create Exports folder if it doesn't exsist
    			if doesFileExist exportfolderPath  == false do (
    				makedir exportfolderPath
    			)
    		
    			-- Reposition all objects
    			selection.position = [0,0,0]
    			
    			-- Ritriangulate
    			modPanel.addModToSelection (Turn_to_Poly ()) ui:on 
    			for obj in selection do (
    						obj.modifiers[#Turn_to_Poly].limitPolySize = on
    			            obj.modifiers[#Turn_to_Poly].maxPolySize = 3
    			)
    			
    			-- Exports the currently selected objects as fbx
    			exportFile exportpathFull #noPrompt selectedOnly:true
    
    			-- Restore scene
    			fetchMaxFile quiet:true
    			
    		)
    	)
    	createdialog roll_UdkExport
    )
    
    
  • knak47
    Rather than start a new thread I will ask a noob question. Is there an actual need to triangulate your mesh prior to export? I havent been doing so and havent seen any issues once it arrives in UDK. Also the script renames the texture applied to have the same name as the object, I assume this is only for organizational porposes correct?
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    you risk the triangulation done either as part of the fbx export(if enabled) or by the engine at inport being different from what you see in the viewport - which will screw your normal maps.

    you'll generally be alright as most systems will go for the "create the shortest edge" option but if you've turned hidden edges manually for whatever reason then the results may well be different.
  • Parkar
    Offline / Send Message
    Parkar polycounter lvl 18
    One thing worth noting that I discovered yesterday is that if you triangulate (at least using the turn_to_poly modifier) you will loose any changes you have made to the normals. Therefore I added a checkbox to disable that as quiet often I tweak the normals.

    I haven't had a need to do the retriangulation on any of the meshes with adjusted normals before so not sure if it is possible to do without loosing the normals. Of course going down on sub object level and adding the edges one by one in the script is probably going to work but hoping there is an easier way.
  • Mark Dygert
    kaburan, yea I didn't make it smart enough to handle a model without a material, it shouldn't be too hard to get it to create a new material and assign it, but for now just make sure you have a material assigned.

    Nice work parkar!

    I started working on a UI and then thought, I'm making this more complicated than it needs to be, and went for the one button option. Of course I then ran into cases like you mentioned where you need different options hahaha oh well... time to complicate it a bit, lucky for me you did some of the leg work already =)

    About the triangulation.
    I was using the FBX option but noticed would still pop up a message box complaining about turned edges. I too ran into a piece that I needed to edit the normals on and both methods of triangulation where giving me a seam, the only way I could get around it was to let UDK do the triangulation which is did "wrong" but with explicit normals checked on during import they overrode the retrinagulated normals so the seam disappeared.

    Things to add:
    Display and browse/edit export path, remember path.
    Display and edit material name.
    Option to create new material with default bitmaps in the commonly used slots.
    Option to disable turn to poly triangulation.


    I missed a week of work thanks to a bunch of snow and I'm pretty far behind so I don't know when I'll get a chance to work on this next but I'll post a updated version when I do.
  • Shogun3d
    Offline / Send Message
    Shogun3d polycounter lvl 12
    Yeah you're not the only screwed by Friday's nasty snow storm. Took me 4 hours to get home from work >.<
  • Parkar
    Offline / Send Message
    Parkar polycounter lvl 18
    I think a one button click with left mouse button for a quick reuse last options and a right to get an options window where you can make tweaks would be optimal.

    Would need some more complicated script and should preferably save the config in the max file. Taking it all the way, some settings could even be stored per object in the custom parmaters I guess. Then add some quick toggle scripts that can be used on selection to set how each model should be handled.
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    export to prefab would shweet.
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    I' sorry I'm spamming this thread with my ideas but is it possible to make such a script for Xnormal ? I imagine it as two buttons to export high poly and low poly (into SBM format). Unfortunately I lack max script skills to do that. Any thoughts ?

    I noticed its in UDK forum... not the best place. Sorry
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    MrOneTwo wrote: »
    I' sorry I'm spamming this thread with my ideas but is it possible to make such a script for Xnormal ? I imagine it as two buttons to export high poly and low poly (into SBM format). Unfortunately I lack max script skills to do that. Any thoughts ?

    I noticed its in UDK forum... not the best place. Sorry

    need more info.

    you wanting to export to xnoraml as xn's native sbm format or something else?

    are you wanting to export the selections as individual objects, or export everything as 1?

    are you wanting to choose the filename, or have the script automatically figure it out based on the object names and the path of the scene file?
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    I didn't thought it out as precisely since i don't want to tell any one 'YOU! do this this and this.'. I wanted to gather info is it possible and maybe to do it myself in the future.

    I want a script which adds edit mesh modifier to selected mesh, exports to sbm (one script would export with high poly sbm preset and second with low poly), deletes edit mesh mod. One of the solutions i thought of was to solve it like in IOpipeline for modo. Script would export always to the same location. Xnormal would have always those 2 files plugged in (since it remebers what meshes were loaded before). Making bakes would only require to use those 2 scripts on high and low poly. Then you switch to xnormal and just press bake.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    dont even need to know how to script to do that, you can just watch the script listener while doing this by hand, to see what commands it uses, than place them in a script.

    don't even really need to replace with variables, since you really got no dynamic things happening in there since all you want to dumping to the same filenames and path every-time.
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    Dunno why i totally forgot about listener <.< Thought that exporting is some external magic. Must check it out. Thanks
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    Nope not possible through listener. The only thing i can get out of listener is ' max file export selected '.
  • Mark Dygert
    Yea the listener is good at giving you hints and clues at the commands but often the maxscript help file has better code to use with a lot more parameters to tweak.

    For example you might do something and listener says: actionMan.executeAction 0 "40015" which is actually max undo which is much easier to work with.

    You can use actionMan code but its pretty limiting and often very dependent on the situation you currently have set up, "in sub-object face mode, with faces selected and the paint relax tool active". If you rely on ActionMan you need to do all of that manually which is a waste of time if you want to click an object and have all of that happen automatically.

    Also the listener doesn't record everything which can be frustrating so often you have to crack open the maxscript help file and do a bit of searching to find the real useful bits of code.

    To get to the maxscript help file go Main Menu > Help > MaxScript Help. Or with the script editor open press F1.


    MrOneTwo I'm not sure I understand what you're trying to do? Are you trying to export from max to xNormal or from xNormal to UDK? A single button export max to xNormal would be helpful kind of like GoZ in ZBrush, but you can't control xNormal through maxscript (that I know of) so something else would have to be done to get it out of xNormal and into UDK or back to max.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    ya sorry about the listener bit, im used to maya, and the script editor gives pretty decent amounts of output, from commands.

    @ mark seems he just wants a 1 click export that goes to a per-defined location, and filename, useing the xnormal sbm format.
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    Yep what passerby said. I just need to be able to select low or high poly preset from sbm exporter via maxscript. I got this idea from pipelineIO for Modo. It exports selected mesh always to the same place. The script would export the mesh always to the same file (overwriting it). Of course its not super flexible solution but seems to be something really useful if you need to tweak low or high poly and make few test bakes. Then you would just need to run export script, switch to xnormal and press bake. It would be GoXnormal but just to sbm file not directly to xnormal ;p
Sign In or Register to comment.