ScriptSpot

Forum topic · Scripts Wanted

copy mat+modifiers from file A to file B (object to object)

By 1rv · 2014-04-08

Description
Comments (20)

gone testing

1rv · 2014-04-10

first off it works!
I need your clarification:
If, Say I have 2 shortcuts:
1. 'R'- to copy mat+mod
2. 'T'- pastes the donor's mat+mod, keeps receiver's old mat name
2a.(Alt+Shift+T, Shift+T DO THE SAME, AM I CORRECT?)
2b. Alt+T - pastes mat ONLY, keeps receiver's old mat name.

What I noticed, the script tentatively inserts the donor's mesh, which sometimes could be huge and time consuming. could this mesh be substituted with say simple box
(mat+mod holder)?
Once again, salute!

.

miauu · 2014-04-10

After 4 hours I have to go at work. When I go back home(after 24h shift) i will modify the script.
In the listenre will be printed what is happen - the mats or mats+mods are transmited to the receivers.

1rv · 2014-04-11

Now I think all those key combinations just mess the things up. What do you think?
May be it'd be better to keep simple key hit for mat+mod+the old mat's name preserving,
AND hitting ALT+users key would pop-up the tiny window with following options (with combo boxes to check\uncheck:
1. keep the donor's mat name
2. don't transfer mods.
3. materials purging\instancing (tough one?):
a.instance all mats with the same name by inserted one;
b.instance all mats with the same maps\values by inserted one
BTW if the script could pick-up the isolated member of Multi\SubObject mat and do p.3
it'd be awesome.
Thank you for attention.

.

miauu · 2014-04-12

I don't have much time, but try this:
When you dun the PASTE script it will create RC menu so you have to choose what action to be done. Feel free to change the names of the RC menu so you can undestand better what it will do.


macroScript Copy_MaterialsAndModifiers_To_File Category:"CG_Tools" toolTip:"Copy MatsAndMods to File"
(
    thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT
    thecopypastefile = "\pastefile.max" --this is the filename to save as...
    thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string
 
    if selection.count == 1 do with redraw off
	(
		curO = selection[1]
		b = box lengthsegs:1 widthsegs:1 heightsegs:1 isSelected:false
		b.name = ((timestamp()) as string) + "_" + ((timestamp()) as string)
		b.material = curO.material
		if curO.modifiers.count != 0 do
		(
			for m = curO.modifiers.count to 1 by -1 do
				addModifier b curO.modifiers[m]
		)
		saveNodes b thecopypastestring --this saves ("copies") the objects as a file
		delete b	
	)
)


macroScript Paste_MaterialsAndModifiers_From_File Category:"CG_Tools" toolTip:"Paste MatsAndMods from File"
(
	function CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:true =
	(
		if obj.material != undefined do
		(
			for i in selObjsArr do
			(
				oldName = if i.material != undefined then i.material.name else undefined
				i.material = obj.material				
				if keepMatName == true and oldName != undefined do
					i.material.name = oldName
			)
		)
		if copyMods == true do
		(
			try
			(
				x = obj.modifiers.count+1
				while x > 1 do
				(
					objmod = obj.modifiers[x-=1]
					for obj in parent_array do addModifier obj objmod
				)
			)catch()
		)
	)
	function CopyMatAndMods01 oldName:true copyMods:true =
	(
		if selection.count != 0 then with redraw off
		(
			local    selObjsArr
			local    parent_array = #()
			local    temp_array = #()

			selObjsArr = for o in selection as array where isGroupHead o == false collect o

			if selObjsArr.count != 0 do
			(
				for i in selObjsArr where (finditem temp_array i == 0) do
				(
					InstanceMgr.GetInstances i &inst_array
					append parent_array inst_array[1]
					join temp_array inst_array
				)

				thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT
				thecopypastefile = "\pastefile.max" --this is the filename to save as...
				thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string

				mergemaxfile (thecopypastedir + thecopypastefile) #select --this merges ("pastes") and selects objects from file
				obj = selection[1]		
				-- 
				if obj!=undefined do
				(
					CopyMatAndMods obj selObjsArr parent_array keepMatName:oldName copyMods:copyMods
				)
				--
				delete obj
				select selObjsArr
			)
		)	
	)
			
	rcMenu rcMapSize
	(
		menuItem matModOld "Transfer Mat + Mod + Old Mat Name" checked:false
		menuItem matMotKeep "Transfer Mat + Mod + Keep Mat Name" checked:false
		menuItem matOld "Transfer Mat + Old Mat Name" checked:false
		menuItem matKeep "Transfer Mat + Keep Mat Name" checked:false
		
		on matModOld picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:true copyMods:true
		)
		on matMotKeep picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:false copyMods:true
		)
		on matOld picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:true copyMods:false
		)
		on matKeep picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:false copyMods:false
		)		
	) 
	popUpMenu rcMapSize pos:mouse.screenpos
)

1rv · 2014-04-13

man it's fantastic, many thanks!
RC menu suites the best, but may be you could still ADD the possibility to the first option (mat+mod+old name) get executed with Cntl+key (just because it will be choosen in 90% of the cases)?
Once again, many thanks!

.

miauu · 2014-04-13

When you run the script:
- click in the viewport will perform mat+mod+old mat name
- shift+click will invoke the rc menu


macroScript Paste_MaterialsAndModifiers_From_File Category:"CG_Tools" toolTip:"Paste MatsAndMods from File"
(
	global miauuMouseToolCopyPasteMatsAndMods
	
	function CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:true =
	(
		if obj.material != undefined do
		(
			for i in selObjsArr do
			(
				oldName = if i.material != undefined then i.material.name else undefined
				i.material = obj.material				
				if keepMatName == true and oldName != undefined do
					i.material.name = oldName
			)
		)
		if copyMods == true do
		(
			try
			(
				x = obj.modifiers.count+1
				while x > 1 do
				(
					objmod = obj.modifiers[x-=1]
					for obj in parent_array do addModifier obj objmod
				)
			)catch()
		)
	)
	function CopyMatAndMods01 oldName:true copyMods:true =
	(
		if selection.count != 0 then with redraw off
		(
			local    selObjsArr
			local    parent_array = #()
			local    temp_array = #()
 
			selObjsArr = for o in selection as array where isGroupHead o == false collect o
 
			if selObjsArr.count != 0 do
			(
				for i in selObjsArr where (finditem temp_array i == 0) do
				(
					InstanceMgr.GetInstances i &inst_array
					append parent_array inst_array[1]
					join temp_array inst_array
				)
 
				thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT
				thecopypastefile = "\pastefile.max" --this is the filename to save as...
				thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string
 
				mergemaxfile (thecopypastedir + thecopypastefile) #select --this merges ("pastes") and selects objects from file
				obj = selection[1]		
				-- 
				if obj!=undefined do
				(
					CopyMatAndMods obj selObjsArr parent_array keepMatName:oldName copyMods:copyMods
				)
				--
				delete obj
				select selObjsArr
			)
		)	
	)
	
	rcMenu rcMapSize
	(
		menuItem matModOld "Transfer Mat + Mod + Old Mat Name" checked:false
		menuItem matMotKeep "Transfer Mat + Mod + Keep Mat Name" checked:false
		menuItem matOld "Transfer Mat + Old Mat Name" checked:false
		menuItem matKeep "Transfer Mat + Keep Mat Name" checked:false
 
		on matModOld picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:true copyMods:true
		)
		on matMotKeep picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:false copyMods:true
		)
		on matOld picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:true copyMods:false
		)
		on matKeep picked do with undo "Smart Spline Extrude" on
		(
			CopyMatAndMods01 oldName:false copyMods:false
		)		
	) 
	
	tool miauuMouseToolCopyPasteMatsAndMods
	(
		-- -- set up so that a node is created on a mouse button down, move node -- drag, release node at mouse button up. -- -- if clickno == 1, then we are at first mouse click, which is a mouse -- button down. If clickno != 1, at following mouse button up.
		on mousePoint clickno do
		(
			if clickno == 1 then
			(
				if keyboard.ShiftPressed then
				(
					popUpMenu rcMapSize pos:mouse.screenpos
				)
				else
				(
					CopyMatAndMods01 oldName:true copyMods:true
				)
				#stop
			)
			else
				#stop
		)
	)
	startTool miauuMouseToolCopyPasteMatsAndMods
)

1rv · 2014-04-13

fantastic script,- put it into your pack! and sorry if I tortured you too much :)

1rv · 2014-04-13

hm.. I can't make it work the new way- still only RC menu. What Am I Doing Wrong?

.

miauu · 2014-04-13

Assign a hotkey to run the script
Press the hotkey
click anywehere in the screen.
If you have selected objects the script will transfer mat+mods+old mat names.

If you shift+click the RC menu will appear.

1rv · 2014-04-13

it's OK now:)

1rv · 2014-04-10

May be it would help you to shorten the things..
Alex, the author of original script helped me to cook alternative version that keeps original mat name:

in TrackScripts.mcr, find the fragment

MacroScript CopyMat category:"Track" tooltip:"Copy Material and Modifiers" Icon:#("Material_Modifiers",3)(

in the function the line

for i in selobjs do i.material=obj.material

to be replaced with:

for i in selobjs do
(
local oldName = i.material.Name
i.material = obj.material
i.material.Name = oldName
)

---
It worked well, but what I didn't like in this alternative (please pay attention to this case) is the Error pop-ups when the receiver had no
material (and it's name of course) before mat switching.
Thank you, Miauu once again

.

miauu · 2014-04-10

Test the scripts. I have made some changes to the Copy_ script. The saved object will be saved with unique name, so when you use the Paste script there will be no problems when you have object with the same name in the scene(there is a built-in solution for cases like this, but they will works on max2011+).
The Paste script works as follows:
- run it and click anywhere in the viewport. The Alt and Alt+Shift keys will works as is described in the code.


macroScript Copy_MaterialsAndModifiers_To_File Category:"CG_Tools" toolTip:"Copy MatsAndMods to File"
(
    thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT
    thecopypastefile = "\pastefile.max" --this is the filename to save as...
    thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string
 
    if selection.count == 1 do
	(
		c = copy selection[1]
		c.name = ((timestamp()) as string) + "_" + ((timestamp()) as string)
		saveNodes c thecopypastestring --this saves ("copies") the objects as a file
                delete c		
	)
)
 
macroScript Paste_MaterialsAndModifiers_From_File Category:"CG_Tools" toolTip:"Paste MatsAndMods from File"
(
	global miauuMouseToolCopyPasteMatsAndMods
	tool miauuMouseToolCopyPasteMatsAndMods
	(
		-- -- set up so that a node is created on a mouse button down, move node -- drag, release node at mouse button up. -- -- if clickno == 1, then we are at first mouse click, which is a mouse -- button down. If clickno != 1, at following mouse button up.
		on mousePoint clickno do
		(
			function CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:true =
			(
				if obj.material != undefined do
				(
					for i in selObjsArr do
					(
						oldName = if i.material != undefined then i.material.name else undefined
						i.material = obj.material
						if keepMatName == true and oldName != undefined do
							obj.material.name = oldName
					)
				)
				if copyMods == true do
				(
					try
					(
						x = obj.modifiers.count+1
						while x > 1 do
						(
							objmod = obj.modifiers[x-=1]
							for obj in parent_array do addModifier obj objmod
						)
					)catch()
				)
			)
			if clickno == 1 then
			(
				if selection.count != 0 then with redraw off
				(
					local    selObjsArr
					local    parent_array = #()
					local    temp_array = #()
					
					selObjsArr = for o in selection as array where isGroupHead o == false collect o
					
					if selObjsArr.count != 0 then
					(
						for i in selObjsArr where (finditem temp_array i == 0) do
						(
							InstanceMgr.GetInstances i &inst_array
							append parent_array inst_array[1]
							join temp_array inst_array
						)
				 
						thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT
						thecopypastefile = "\pastefile.max" --this is the filename to save as...
						thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string
				 
						mergemaxfile (thecopypastedir + thecopypastefile) #select --this merges ("pastes") and selects objects from file
						obj = selection[1]		
						-- 
						if obj!=undefined then
						(
							if keyboard.AltPressed and keyboard.ShiftPressed then
							(
								print "Material and Modifiers are copied. Original Material's Name is preserved"
								CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:false
							)
							else
							(
								if keyboard.AltPressed then
								(
									print "Material is copied. Original Material's Name is preserved"
									CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:false
								)	
								else
								(
									print "Material and Modifiers are copied"
									CopyMatAndMods obj selObjsArr parent_array keepMatName:true copyMods:true
								)
							)
						)
						--
						delete obj
						select selObjsArr
						#stop
					)
					else
						#stop
				)
				else
					#stop
			)
			else
				#stop
		)
	)
	startTool miauuMouseToolCopyPasteMatsAndMods
)

1rv · 2014-04-09

Mate, it works precisely as expected! Amazing, thank you so much!
Now the routine of revisions (I import models from Sketchup) will be much more easier.
Thought about some polishing:
1. IF ADDITIONALLY , the ALT key will be used, so the object-receiver would get the mat, but preserve its original mat name (only name!)
2. IF ADDITIONALLY , the ALT+SHIFT key will be used, so the receiver object would preserve its original mat name (only name!) and receive mat+UVW.
NB: If there's no mat upon the receiver the script, the shouldn't be the Error pop-up.
Is it possible?
---
Once again, thank you!

.

miauu · 2014-04-09

Now you can't use Alt, Shift or Ctrl to achieve different results because the script is a macro and if you run it with hotkey then the keyboard kyes can't be used. Tommorow I will ty to add what you have asked and will change the way of how the script works so you can use it with a hotkey.

1rv · 2014-04-08

@fajar: No, it's overcomplicated, I dreamt about something elegant, fluent and easy like eye dropper. Essentially the Track's script is ideal (the main limitation it works within one file).
@miauu My bad :( by saying modifiers I meant UVW mod. So is my humble request doable?
Thank you in advance.

.

miauu · 2014-04-08

You will have two instances of 3dsMax running at the same time or the situation is different?

1rv · 2014-04-09

Yep, 2 (BTW are 2+ instances of 3ds max problem?) Windows of Max will be open side by side.
This is how I see this tool :
1. In file A, select object-donator and hit shortcut (i.e. Cntl+C for mat copy only, Cntl+Shift+C for copying mat+UVW mod)
2. In file B,select object and hit shortcut (i.e. Cntl+V for mat paste only, Cntl+Shift+V for pasting mat+UVW mod)
3. Profit..

BTW may be it will also help:

http://www.scriptspot.com/3ds-max/scripts/copy-and-paste-objects

http://www.scriptspot.com/3ds-max/scripts/copypaste-material-to-file

Use them constantly

.

miauu · 2014-04-10

Test the scripts below. I just combined(with little modification) the Track's and Christopher Grant's scripts.

</p>
<p>macroScript Copy_MaterialsAndModifiers_To_File Category:"CG_Tools" toolTip:"Copy MatsAndMods to File"<br>(<br>&nbsp;&nbsp;&nbsp; thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT<br>&nbsp;&nbsp;&nbsp; thecopypastefile = "\pastefile.max" --this is the filename to save as...<br>&nbsp;&nbsp;&nbsp; thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; if selection.count == 1 do <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; saveNodes $ thecopypastestring --this saves ("copies") the objects as a file<br>)<br>&nbsp;<br>macroScript Paste_MaterialsAndModifiers_From_File Category:"CG_Tools" toolTip:"Paste MatsAndMods from File"<br>(<br>&nbsp;&nbsp;&nbsp; if selection.count != 0 then with redraw off<br>&nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;&nbsp; selobjs<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;&nbsp; parent_array = #()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;&nbsp; temp_array = #()<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; selobjs = for o in selection as array where isGroupHead o == false collect o<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for i in selobjs where (finditem temp_array i == 0) do <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; InstanceMgr.GetInstances i &amp;inst_array<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; append parent_array inst_array[1]<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; join temp_array inst_array<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; thecopypastedir = getdir #autoback -- CHANGE THIS TO ANY FOLDER YOU WANT<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; thecopypastefile = "\pastefile.max" --this is the filename to save as...<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; thecopypastestring = thecopypastedir + thecopypastefile --this is the complete string<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mergemaxfile (thecopypastedir + thecopypastefile) #select --this merges ("pastes") and selects objects from file<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; obj = selection[1]<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if obj!=undefined then<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if obj.material!= undefined do <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for i in selobjs do i.material=obj.material<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; format (obj.material.name + "\n")<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; x=obj.modifiers.count+1<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while x&gt;1 do<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; objmod=obj.modifiers[x-=1]<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for obj in parent_array do addModifier obj objmod<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )catch()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; --<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete obj<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; select selobjs<br>&nbsp;&nbsp;&nbsp; )<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; messagebox "Select som eobjects" title:"Empty Selection"&nbsp;&nbsp;&nbsp; <br>)</p>
<p>

fajar · 2014-04-08

the way to do it , may be make little box dummy object then copy selected object material & modifier to box dummy and save node those box and then load the box dummy to another file then apply to desired object on those file [file 2]

.

miauu · 2014-04-08

There is one thing tht you should to know - you can't copy the Edit Poly modifier. The script will add is as a modifier to the new object, but it will be as new modifier. All changes to geometry that the original Edit Poly mod has made to the object will not be applied to the new object(where the copy is applyed).