-- Plug-O-Matic v2.0: Generates scripted object plugins from any editable mesh -- Developed and tested with 3dsmax 4.2 -- (c) 2001-2004 Martin Breidt (martin@breidt.net) -- Last modified: 06.03.04 -- -- Run this script and go to Utilities/MAXScript, then start Plug-O-Matic from the -- Utilities drop-down box. Select any geometric source object, change the plugin name if you like, -- adjust options and hit "Export"; then chose a filename. When running the resulting scripted plugin -- 3dsmax will have a new geometric object under the category "Plug-O-Matic". Adjustable parameters -- currently are width, height and length. You can optionally switch on/off specific mesh data. -- Press Ctrl key while creating a new object to unconstrain the object from its original proportions. -- Depending on the options you select, Plug-O-Matic also exports smoothing groups, edge visibility, -- material IDs and texture coordinates. Use only what you need, every extra data slows down the -- interactive object creation process. -- -- Changes in v2.0 -- * Support for non-editable meshes -- * speed-up, optimized array construction -- * code cleanup -- * reversed CTRL key behaviour: without CTRL, created object will be proportional; press CTRL for non-prop. creation -- * Added support for texture coordinates -- * Exported plugins have additional options for turning on/off extra mesh data like smooting groups or texture coords -- * Mouse Tool updated to avoid inverted normals -- -- Changes in v1.1: -- * Fix for bug when plugin name contains special characters -- * Pickbutton reflects picked object name -- * Pickbutton selection filter will avoid emeshes within groups -- * Options for exporting smoothing groups, material IDs, edge visibility -- -- Known Issues: -- * Currently only works with single objects. Groups and Splines are not supported. -- * Class IDs are randomly generated for the new plugin scripts, so it might happen that the -- Class ID is already in use by some other plugin; simply repeat the generation procedure -- until you get no errors when running the new plugin script. -- * No support for vertex colors or additional vertex data channels. -- * Generated script plugins can get fairly large and slow when using high-poly meshes -- as source object. Use with care! -- -- TO DO: -- - better mousetool Utility PlugOMatic "Plug-O-Matic" ( local src -- Source object node local src_mesh -- Source object TriMesh local plugname -- Name for the new plugin local clID1, clID2 -- random classID values, generated per pick action -- Arrays for vertex and face data local vp = #() -- vertex positions local fl = #() -- face list local fm = #() -- face matID local fs = #() -- face smoothing local fe = #() -- face edge vis local tv = #() -- texture vertices local tf = #() -- texture faces fn pickfilter obj = ( (superClassOf obj == GeometryClass) and not (isGroupMember obj) ) fn savestring txt = ( -- return string with illegal characters replaced by '_' illegal = " +<>|!\"$%&/()=?\´`'#.,;:" newtxt = copy txt for x = 1 to txt.count do ( pos = findString illegal newtxt[x] if (pos!=undefined) do newtxt[x]="_" ) newtxt ) fn writeDataToStream datName datArray datStream = ( -- write array data from datArray as static array with name "datName" into filestream format "\t\t% = #(" datName to:datStream local datNum = datArray.count if datNum > 0 then ( for i = 1 to datNum-1 do ( format "\t\t%,\n" datArray[i] to:datStream ) format "\t\t%" datArray[datNum] to:datStream ) format ")\n" to:datStream ) label l0 "Object: " across:2 offset:[-20,5] pickButton pButton "" width:110 message:"Select source object" filter:pickfilter offset:[-12,0] edittext namebox "Plugin Name:" enabled:false group "Export Options" ( checkbox do_matid "Material IDs" checked:false checkbox do_smooth "Smoothing Groups" checked:true checkbox do_edgevis "Edge Visibility" checked:true checkbox do_uv "Texture Coordinates" checked:false spinner uv_spin "Map Channel: " range:[1,99,1] type:#integer fieldWidth:25 enabled:false ) checkbox run_now "Run plugin after export" checked:false button goButton " Export as plugin " enabled:false button aboutButton " About " on do_uv changed val do uv_spin.enabled = val on pButton picked obj do ( pButton.text = obj.name src = obj src_mesh = obj.mesh if (namebox.text=="") then namebox.text = ("POM_"+ obj.name) namebox.enabled = goButton.enabled = true local maxInt = 2147483647 -- max. positive integer value clID1 = (random 100000 maxInt) clID2 = (random 100000 maxInt) ) on aboutButton pressed do ( messageBox ("Plug-O-Matic v2.0\n\n"+ "Generates scripted plugin objects from editable meshes.\n\n" + "(c) 2001-04 Martin Breidt (martin@breidt.net)") title:"About Plug-O-Matic" ) on goButton pressed do ( plugname = namebox.text out_n = getSaveFileName filename:(plugname + ".ms") types:"MAXScript(*.ms)|*.ms" if (out_n!=undefined) then ( pushPrompt "Exporting object as plugin... " out_s = createFile out_n map_ch = uv_spin.value if not (meshOp.getMapSupport src_mesh map_ch) then ( messageBox ("Map channel " + (map_ch as string) + " not available!\nTexture coordinates will not be exported.") title:"Plug-O-Matic Error" beep:true do_uv.checked = uv_spin.enabled = false ) -- write out some header info format "-- Scripted object plugin - generated by Plug-O-Matic v2.0 (by martin@breidt.net)\n--\n" to:out_s format "-- Run this script or place it script in the $scripts\startup directory.\n" to:out_s format "-- This will create a new object under 'Geometry > Plug-O-Matic' in the creation tab.\n" to:out_s format "-- Click and drag to create a new object. Hold Ctrl to unconstrain the new object\n" to:out_s format "-- from the original width/length/height proportions.\n--\n" to:out_s format "-- Export options used:\n" to:out_s if do_matid.checked then format "-- Material IDs\n" to:out_s if do_smooth.checked then format "-- Smoothing Groups\n" to:out_s if do_edgevis.checked then format "-- Edge Visibility\n" to:out_s if do_uv.checked then format "-- Texture coordinates\n\n" to:out_s -- plugin code generation starts here ------------- format "plugin simpleObject %\n" (savestring(plugname)) to:out_s format "name:\"%\"\n" plugname to:out_s format "category:\"Plug-O-Matic\"\n" to:out_s format "classID:#(%,%)\n" clID1 clID2 to:out_s format "(\n\tparameters main rollout:params (\n" to:out_s deflength = (src.max - src.min).y defwidth = (src.max - src.min).x defheight = (src.max - src.min).z format "\t\tlength type:#float ui:length default:%\n" deflength to:out_s format "\t\twidth type:#float ui:width default:%\n" defwidth to:out_s format "\t\theight type:#float ui:height default:%\n" defheight to:out_s format "\t)\n" to:out_s format "\tparameters options rollout:optRO (\n" to:out_s format "\t\tuse_matid type:#boolean ui:check_matid default:%\n" do_matid.checked to:out_s format "\t\tuse_smooth type:#boolean ui:check_smooth default:%\n" do_smooth.checked to:out_s format "\t\tuse_edgevis type:#boolean ui:check_edgevis default:%\n" do_edgevis.checked to:out_s format "\t\tuse_uv type:#boolean ui:check_uv default:%\n" do_uv.checked to:out_s format "\t)\n" to:out_s format "\trollout params \"Parameters\" (\n" to:out_s format "\t\tspinner length \"Length\" range:[0,10000,%] align:#right fieldwidth:60\n" deflength to:out_s format "\t\tspinner width \"Width\" range:[0,10000,%] align:#right fieldwidth:60\n" defwidth to:out_s format "\t\tspinner height \"Height\" range:[0,10000,%] align:#right fieldwidth:60\n\t)\n" defheight to:out_s format "\trollout optRO \"Options\" (\n" to:out_s format "\t\tcheckbox check_matid \"Material ID\"" to:out_s format (if do_matid.checked then "\n" else " enabled:false\n") to:out_s format "\t\tcheckbox check_smooth \"Smoothing Groups\"" to:out_s format (if do_smooth.checked then "\n" else " enabled:false\n") to:out_s format "\t\tcheckbox check_edgevis \"Edge Visibility\"" to:out_s format (if do_edgevis.checked then "\n" else " enabled:false\n") to:out_s format "\t\tcheckbox check_uv \"Texture coordinates\"" to:out_s format (if do_uv.checked then "\n" else " enabled:false\n") to:out_s format "\t)\n" to:out_s format "\trollout aboutRO \"About\" (\n" to:out_s format "\t\tlabel l1 \"Exported on\"\n" to:out_s format "\t\tlabel l2 \"%\"\n" localTime to:out_s format "\t\thyperlink h1 \"Plug-O-Matic v2.0\" address:\"http://www.breidt.net/scripts/\" color:(color 0 0 255) align:#center\n" to:out_s format "\t)\n" to:out_s format "\ton buildMesh do (\n" to:out_s popPrompt() -- Collect vertex positions progressStart "Collecting vertex positions... " nv = getNumVerts src_mesh for i = 1 to nv do ( progressUpdate (i/(nv*0.01)) vp[i] = getVert src_mesh i -- collect vertex positions ) progressEnd() -- collect all face data in one pass progressStart "Collecting face data... " nf = getNumFaces src_mesh for i = 1 to nf do ( progressUpdate (i/(nf*0.01)) fl[i] = getFace src_mesh i -- facelist fm[i] = getFaceMatID src_mesh i -- face material fs[i] = getFaceSmoothGroup src_mesh i -- face smoothing group fe[i] = #() -- edge visibility for j = 1 to 3 do (fe[i][j] = getEdgeVis src_mesh i j) ) progressEnd() -- collect texture coordinate data local map_ch, nt if do_uv.checked then ( progressStart "Collecting texture coordinate data... " -- store texture vertices nt = meshOp.getNumMapVerts src_mesh map_ch for i = 1 to nt do ( progressUpdate (i/((nt+nf)*0.01)) tv[i] = (meshOp.getMapVert src_mesh map_ch i) ) -- store texture faces for i = 1 to nf do ( -- #(faces) = #(texture faces) progressUpdate ((nt+i)/((nt+nf)*0.01)) tf[i] = (meshOp.getMapFace src_mesh map_ch i) ) progressEnd() ) pushPrompt "Writing data to file... " -- Write geometry to plugin file format "\t\t-- Vertex data (% verts)-----------------------\n" nv to:out_s writeDataToStream "vp" vp out_s -- Write face list data into static array format "\t\t-- Face data (% faces) ---------------------------\n" nf to:out_s writeDataToStream "fl" fl out_s -- Write MaterialID data into static array if do_matid.checked then ( format "\t\t-- Material ID data (%) ---------------------------\n" nf to:out_s writeDataToStream "fm" fm out_s ) -- Write smoothing data into static array if do_smooth.checked then ( format "\t\t-- Smoothing data (%) ---------------------------\n" nf to:out_s writeDataToStream "fs" fs out_s ) -- Write edge visibility data into static array if do_edgevis.checked then ( format "\t\t-- Edge visibility data (%) ---------------------------\n" nf to:out_s writeDataToStream "fe" fe out_s ) -- Write texture coordinate data into static array if do_uv.checked then ( format "\t\t-- Texture coordinate vertices (%) ---------------------------\n" nt to:out_s writeDataToStream "tv" tv out_s format "\t\t-- Texture coordinate faces (%) ---------------------------\n" nf to:out_s writeDataToStream "tf" tf out_s ) -- scaling parameters format "\n\t\t-- scaling vertex positions\n" to:out_s format "\t\tfor i = 1 to % do (\n" nv to:out_s format "\t\t\toldpos = vp[i]\n" to:out_s format "\t\t\tvp[i] = point3 (oldpos.x * (width/%)) (oldpos.y * (length/%)) (oldpos.z * (height/%))\n\t\t)\n" defwidth deflength defheight to:out_s format "\t\t-- Create mesh for buildMesh\n" to:out_s format "\t\tif use_matid then(\n" to:out_s format "\t\t\tsetMesh mesh vertices:vp faces:fl" to:out_s if do_matid.checked then format " materialIDs:fm\n" to:out_s else format "\n" to:out_s format "\t\t) else (\n" to:out_s format "\t\t\tsetMesh mesh vertices:vp faces:fl\n" to:out_s format "\t\t)\n" to:out_s if do_uv.checked then ( format "\t\tif use_uv then (\n" to:out_s format "\t\t\t-- Create texture coordinates\n" to:out_s format "\t\t\tmeshOp.setMapSupport mesh % true\n" map_ch to:out_s -- activate map support -- create TVerts format "\t\t\tmeshOp.setNumMapVerts mesh % %\n" map_ch nt to:out_s format "\t\t\tfor i=1 to % do (\n" nt to:out_s format "\t\t\t\tmeshOp.setMapVert mesh % i tv[i]\n" map_ch to:out_s format "\t\t\t)\n" to:out_s format "\t\t) else ( \n" to:out_s format "\t\t\t-- Delete any texture coordinates\n" to:out_s format "\t\t\tmeshOp.setMapSupport mesh % false\n" map_ch to:out_s format "\t\t)\n" to:out_s ) if do_smooth.checked or do_edgevis.checked then ( format "\t\t-- Apply additional face data\n" to:out_s format "\t\tfor i = 1 to % do (\n" nf to:out_s if do_smooth.checked then format "\t\t\tif use_smooth then setFaceSmoothGroup mesh i fs[i]\n" to:out_s if do_edgevis.checked then format "\t\t\tif use_edgevis then for j = 1 to 3 do (setEdgeVis mesh i j fe[i][j])\n" to:out_s if do_uv.checked then format "\t\t\tif use_uv then meshOp.setMapFace mesh % i tf[i]\n" map_ch to:out_s format "\t\t)\n" to:out_s ) format "\t) -- end on buildmesh\n\n" to:out_s format "\ttool create prompt:\"Click and drag to begin creation process. Hold Ctrl for original object proportions.\" (\n" to:out_s format "\t\ton mousePoint click do (\n" to:out_s format "\t\t\tcase click of (\n" to:out_s format "\t\t\t\t1: nodeTM.translation = gridPoint\n" to:out_s format "\t\t\t\t3: #stop\n" to:out_s format "\t\t\t)\n" to:out_s format "\t\t)\n" to:out_s format "\t\ton mouseMove click do (\n" to:out_s format "\t\t\tcase click of (\n" to:out_s format "\t\t\t\t2: (\n" to:out_s format "\t\t\t\t\tif ctrlKey then (\n" to:out_s format "\t\t\t\t\t\twidth = abs gridDist.x\n" to:out_s format "\t\t\t\t\t\tlength = abs gridDist.y\n" to:out_s format "\t\t\t\t\t) else (\n" to:out_s format "\t\t\t\t\t\told_width = %\n" defwidth to:out_s format "\t\t\t\t\t\twidth = sqrt ((gridDist.y)^2+(gridDist.x)^2)\n" to:out_s format "\t\t\t\t\t\tlength = (width/old_width)*%\n" deflength to:out_s format "\t\t\t\t\t\theight = (width/old_width)*%\n" defheight to:out_s format "\t\t\t\t\t)\n" to:out_s format "\t\t\t\t)\n" to:out_s format "\t\t\t\t3: if ctrlKey then height = abs gridDist.z else #stop\n" to:out_s format "\t\t\t) -- end on case\n" to:out_s format "\t\t) -- end on mouseMove\n" to:out_s format "\t) -- end create tool\n" to:out_s format ") -- end Plug-O-Matic plugin\n" to:out_s close out_s popPrompt() if run_now.checked then ( fileIn out_n max create mode messageBox ("New scripted plugin object created and temporarily installed.\n"+ "Note: You still need to install the script for permanent use!") title:"Plug-O-Matic: Success" ) else ( messageBox ("New scripted plugin object created.\n"+ "Run '" + out_n + "' to add a new\n"+ "object called '" + plugname + "' to the\n"+ "'Plug-O-Matic' object category.") title:"Plug-O-Matic: Success" ) ) -- end of if ) )