make money

Award Winning Plant Industry Community

Polyform Importer: The DWG batch importer for 3ds Max and 3ds Max Design

I recently released my dwg batch import utility for 3ds Max Design called “Polyform Importer”. The purpose for creating the utility was to solve the problem of only being able to import one file at a time into 3ds Max. In this article, I will show you how to install it and then talk about how it works.

Installing the Polyform Importer

1. Navigate to the folder that you exported the project DWG files to
2. Download the Polyform Importer.ms script and drop it into any 3ds Max Design scene
3. From the main menu click Customize then click Customize User Interface
4. Click on the Menus tab
5. Click New… To create a new menu and name it Polyform Tools
6. In the Menus list on the left bottom section find Polyform Tools and drag it over to the main menu list on the left just after MAXScript
7. In your menus list click the + to expand the PolyformTools menu
8. In the Category drop-down list navigate to PolyformTools
9. Click and drag Polyform Importer underneath your new Polyform Tools menu in the menus list
10. Close the Customize User Interface window
11. You should now see the Polyform Tools menu option
12. If you’re not seeing the importer, go back through the steps and find where you may have made an error




Installing and Using the Polyform Importer Video

For those of us who need to SEE it done, there is also this video. If YouTube is blocked at your work, try this




The Code

For you code geeks out there, here is the source. Feel free to modify or try stuff. If you make something cool with it, please share! It will only help make everyone better.

UI Element Setup…

global dwgList --global variable needed for name collection
global importDrawingPath --global variable for path to imports
-- 
macroScript Polyform_Importer category: "PolyFormTools"
(
	Rollout ImportExport "Import/Export"
(
	group "Directory and files"
		(
			edittext txt_dir "Directory" align:#left across:2 width:225
			button btn_browse "..." align:#right width:20 
			edittext txt_pre "Prefix:" text:"" tooltip:"Put your file prefix here" align:#left width:105 across:2
			button btnUpdate "Update" enabled:false
			edittext txt_ext "Extension" text:"dwg" align:#left width:105
			--edittext txt_suf "Sufffix: *" text:"" tooltip:"Put your suffix here" align:#left width:105
			label lblNumFiles "No files selected"
		)
	group "Import Options"
		(
			checkbox chkFLM "Link File"
			checkbox chkIMP "Import" checked:true	
			checkbox chkCreateMaxFile "Save import as .Max file" across:2
			checkbox chkMergeXrefs "Merge Xrefs" enabled:false align:#right
			checkbox chk_prefixmodelname "File Name Prefix" tooltip:"This will prefix each object with the file that it came from" align:#left --offset:[-45,0]
			checkbox chkSmooth "Smooth Modifier" across:2 enabled:false
			edittext txt_NoSmoothType text:"beam,stair,steel" width:75 tooltip:"Do not apply smooth modifier to files with this prefix"
			checkbox chk_unparent "Unparent Objects" align:#left checked:true
			label lbl_status "Ready"
		)
		group "Do it!"
		(
			button btn_Import "GO" width:75 height:40
		)




When I check a box or press a button do something

		on chkFLM changed state do
		(
			chkIMP.checked = false
		)
		on chkIMP changed state do
		(
			chkFLM.checked = false
		)

We can’t Import AND use the File Link Manager. If we check one, we will uncheck the other.



Toggle Checkbox when other Checkbox gets Checked

		on chkCreateMaxFile changed state do
		(
			if not chkMergeXrefs.enabled then chkMergeXrefs.enabled = true else chkMergeXrefs.enabled = false --Allockse from the forum suggested I modify this. Have not done it yet but I will!
		)
		on chk_prefixmodelname changed state do
		(
			if not chkSmooth.enabled then chkSmooth.enabled = true else chkSmooth.enabled = false
		)

Same idea behind then Prefix Model Name. If we check it, the Smooth checkbox enabled property is toggled. Why? Because we need the file name to apply the smooth modifier



Setting import directory, tell us how many files will be imported

		on btn_browse pressed do
		(
			local fpath = getSavePath initialDir:@"F:\Projects\Autodesk\Technical Conference\dataset" caption:"Select any file in the source directory:" 
			--shellLaunch "explorer.exe" (getdir #scene)
			if fpath != undefined then
			(
			local extension = txt_ext.text
			local pfix = if txt_pre.text == "" then pfix = "*" else pfix = txt_pre.text 
			local thepath = fpath + "\\" +  pfix + "." + extension
			local dcount = (for f in getfiles (thepath) collect f).count
			if dcount > 0 then 
				(
					lblNumFiles.text = dcount as string + " files will be imported"
					importDrawingPath = fpath + "\\" + pfix + "." + extension 
					txt_dir.text = fpath
				)
			)
			btnUpdate.enabled = true
		)

When the user pressed the browse button the code checks to see how many dwg’s are in the directory and displays that on the label. After the directory is set, the update button is enabled.



Update the imported drawing count

		on btnUpdate pressed do
		(
			local pfix = if txt_pre.text == "" then pfix = "*" else pfix = txt_pre.text 
			local thepath = (getfilenamepath importDrawingPath) +  pfix + "." + txt_ext.text
			importDrawingPath = thePath
			local dcount = (for f in getfiles (thepath) collect f).count
						if dcount > 0 then 
									(
										lblNumFiles.text = dcount as string + " files will be imported"
										--txt_dir.text = thepath
									) else (
										lblNumFiles.text = "No files will be imported"
									)
		)

When the user changes the value in the prefix text box to *PIP* or something like that, the resulting import number will be filtered down to all drawings that contain the letters PIP in the drawing name. This is NOT case sensitive.



GO Button pressed! Work your magic computer!

Write results to log file function

		on btn_Import pressed do
		(
			fn writetolog dir larr fileLog=
						(				
									local t = localtime							
									local exportlog = openfile fileLog mode:"a"
									format "%\n" t to:exportlog
									for i = 1 to larr.count do format "% % seconds\n" larr[i][1] larr[i][2] to:exportlog
									format "<--##############################-->\n" to:exportlog	
									close exportlog
						)

During the import process, we are collecting data into an array. At the end we write to a text file that will be located in the same directory as the drawings.



Xref the DWG’s into a single drawing and merge them (if you want)

	
			fn xrefobjs dirname mergebool = 
						(
										resetmaxfile #noprompt
										for f in (getFiles (dirName+"\\*.max")) do
										 (
											mf = xrefs.addNewXrefFile f
											if mergebool then merge mf
										 )
						)

If the Save import as .Max file option is checked, all of the imported drawings will be referenced into a new drawing at the end. This allows you to get a quick visual on the imported drawings. You can discard this file if you choose. It won’t affect the other drawings.



IMPORTING WAS HERE

			fn importObjects filename nsmooth sm=
						(
										local impobjs = for o in objects where o.isfrozen == false collect o
										for obj in impobjs where classof obj == Editable_mesh do obj.name = (substring obj.name (6+1) obj.name.count)
										for obj in impobjs where classof obj == Editable_mesh  do obj.name = (filename + "_" + obj.name)
										local smootharr = #()
										if chkSmooth.checked == true then 
											(
														for ns = 1 to nsmooth.count do
														(	
															local cfilter = "*" + nsmooth[ns] + "*" -- ("*" + nsmooth[ns] + "*")
																	for imp = impobjs.count to 1 by -1 where matchpattern impobjs[imp].name pattern:cfilter == true do
																	(
																			deleteitem impobjs imp
																	)
														)
														if impobjs.count > 0 then for i = 1 to impobjs.count where impobjs[i].modifiers.count == 0 do addmodifier impobjs sm
											)
											local impobjs = for o in objects where o.isfrozen == false do freeze o
						)

This is the meat of the import process where we

  • Rename objects to the-file-they-came-from_the-layer-they-are-on
  • Apply smooth modifier to any object that does not contain the characters in the do-no-smooth-if text box
  • Freeze the imported objects




Clean this mess up!

			fn unparent =	
						(
														startobjects = objects.count
														thedel=#()
														for o in geometry do (
														o.controller=prs()
														if classof o.parent == LinkComposite then
														(
															o.parent = undefined
														) else ( 
															o.parent = undefined
														)
														)
															for sp in objects where classof sp == splineshape do append thedel sp
															for o in geometry where classof o == LinkComposite do converttomesh o --append thedel o
															for o in geometry where classof o == LinkComposite do append thedel o
															for o in objects where classof o == NURBSCurveshape do append thedel o
--
															local count = thedel.count
															delete thedel
															count
						)

This function deals with the cleanup and runs when the Unparent checkbox is checked. Make sure you do this.

  • Unparent everything
  • Convert any block objects to meshes
  • Delete Block objects, Splines, and NURBS curves

If you find that this part is breaking your model. Please contact me. It would also help to send your model that is breaking it.




The rest of it

			local startimp=timestamp()
			local theobj = #()
			local thedwg = #()
			local s = smooth()
			local noSmooth = filterstring txt_NoSmoothType.text ","
			s.autosmooth=true
			clearlistener()	
			disablesceneredraw()
			local exportfilelog = txt_dir.text + "\\importlog.txt"
			local importFileList = txt_dir.text + "\\importFileList.txt"
			if doesFileExist exportfilelog == false then
				( 
					cf = createFile exportfilelog
					close cf
				)
						for f in getfiles (importDrawingPath) do append thedwg f
						for tf = 1 to thedwg.count do
									(
										local logarr = #()
										local mfn = getfilenamefile thedwg[tf]
										local startIntTime = timestamp()
												local filename = filenameFromPath thedwg[tf]
												if chkFLM.checked then
												(
													filelinkmgr.attach thedwg[tf]	
												) else (
															if chkCreateMaxFile.checked == true then
															(
																					resetmaxfile #noprompt
																					savefile = txt_dir.text + "\\" + mfn + ".max" --@"C:\Dropbox\projects\iso15926\Plant3D Sample\exported acad file\" + mfn + ".max"
																					if tf != 1 then importFile thedwg[tf] #noprompt else importFile thedwg[tf]					
																					append logarr #("File saved successfully: ", savefile)
															)	else (												
																					if tf != 1 then importFile thedwg[tf] #noprompt else importFile thedwg[tf]
																					append logarr #("File imported successfully: ", thedwg[tf])
															)
												)
--												
--												
										if chk_unparent.checked == true then
													(
														local thecount = unparent()
														lbl_Status.text = "Deleted " + thecount as string + " objects"
													)		
										if chk_prefixmodelname.state == true then local impobjs = importObjects mfn nosmooth	s					
										if chkCreateMaxFile.checked == true then savemaxfile savefile
--													
										local finIntTime = timestamp()
--
										local intTotal = ((finIntTime-startIntTime)/1000) as float
										append logarr #("File Import Time: ", intTotal)
										writetolog txt_dir.text logarr exportfilelog
										format "imported % in %\n" filename intTotal
									)
--							
		local tend=timestamp()
		local mbool = false
		local intTotal = ((tend-startimp)/1000) as float
		if chkMergeXrefs.checked == true then mbool = true
		if chkCreateMaxFile.checked == true then xrefobjs txt_dir.text mbool
		format "imported % files in %\n seconds" thedwg.count intTotal 
		lbl_Status.text = "Imported " + thedwg.count as string + " files in " + intTotal as string + " seconds"
--					
		enablesceneredraw()									
--		
		)

This is the main portion of the import where we are getting files, throwing them into functions and returning values, timestamping, writing to the log file.

If you need furthur clarity on some of this code. Again, don’t hesitate to contact me. I would love to hear you comments and/or suggestions for improvement. They tell me that I have to say you are using this code at your own risk and if something gets messed up as a result of your using it incorrectly, its on you. Fortunately, that is not likely to happen unless you alter the code somehow. :)

Until next time!

Tags: , , , , , ,

About the Author

About the Author: Dave Tyner is a 3DS Max 2013 Certified Professional working as a visualization artist for one of the worlds largest EPC firms. dave@davetyner.com @davetyner3D www.davetyner.com .

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

There Are 8 Brilliant Comments

Trackback URL | Comments RSS Feed

  1. Troy says:

    Thanks for the step-by-step Dave!

  2. shaun Dykes says:

    Thanks for the routine very useful.
    one question is there a way to get rid of the annoying popup
    Do you really want to cancel the current import process?
    keeps popping up after 4 or5 drawings have been imported.

    • dave says:

      What does the pop-up say? If its the “This drawing contains no valid data” message then I don’t know of a way to do that. Other than that the import should be silent except for the first prompt that asks you for your import settings.

  3. shaun Dykes says:

    Importing 71 drawings into 3ds
    Does 5 or so then up pops the message
    “Do you really want to cancel the current import process?”
    I make sure not touch any keys or anything while script is running. Its like at a certain stage something interrupts the import process. Its also seems dependent upon file sizes

    • dave says:

      Interesting! I have never seen this behavior. Sadly, I can’t troubleshoot this until next week. I will def. make a note to do so. Are the files you’re trying to import strait Autocad dwgs?

  4. shaun Dykes says:

    yes. Each individual drawing is about 1mb in size.
    your script works great. I suspect its a 3dsmax problem where the processor is interrupting the program causing it to put up a cancel dialogue box. I am using 3dsmax 2011. I even tried changing processing priority to high on computer. thanks

Post a Comment

Your email address will not be published. Required fields are marked *

Top