Notifications
Clear all

[Closed] Replace Object with maxscript

Hi guys,
i try to learn maxscript and i’m actually freeze in my code since a few days…

I have a multilist, where i can add, remove or sort items.
I need to select all the items in this multilist before to execute my code but i don’t know how to do that.

(actually i use getcurrentselection() to create an array)

just in case, here is my code:

Blockquote

try (cui.unregisterdialogbar myscript) catch ()
try (destroydialog myscript) catch ()

rollout myscript “object_replacer” width:280 height:538
(

global ReplacerObjectsSet = #()
global ReplacedObjectsSet = #()

multiListBox 'lbx_objects' "Objects:" pos:[8,7] width:260 height:12 align:#left
button 'bt_add' "+" pos:[10,192] width:24 height:24 align:#left
button 'bt_delete' "-" pos:[34,192] width:24 height:24 align:#left
button 'bt_moveUp' "Up" pos:[190,192] width:40 height:24 align:#left
button 'bt_moveDown' "Down" pos:[230,192] width:40 height:24 align:#left

button 'ClearRefListBtn' "Clear List" pos:[10,224] width:260 height:25 align:#left

GroupBox 'grp1' "Reference" pos:[10,264] width:260 height:140 align:#left
label 'lbl2' "Object:" pos:[20,284] width:100 height:15 align:#left
pickbutton 'itemselect' "-- none --" pos:[64,282] width:196 height:20 align:#left		


checkbox 'chk1' "Keep Original Scale - (in progress)" pos:[20,317] width:237 height:16 align:#left
checkbox 'KeepMod' "Apply Modifiers on Copy" pos:[20,338] width:132 height:16 checked:true align:#left
checkbox 'DelObj' "Delete replaced objects" pos:[20,360] width:132 height:16 align:#left

button 'ReplaceBtn' "Replace Substitudes by Reference Object" pos:[12,457] width:254 height:59 align:#left	

	on myscript open do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	callbacks.addscript #selectionSetChanged "myscript.SelectionChanged()" id:#ID0X7FB0F2910X78FF0B50
)

on myscript close do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	myscript=()
)


fn SelectionChanged =
(
	lbx_objects.selection = for j in selection collect finditem lbx_objects.items j.name
	
)

fn AddNodes ctrl =
(
	ctrl.items = makeuniquearray (ctrl.items + (for j in selection collect j.name))
)

fn DeleteNodes ctrl =
(
	if not ctrl.selection.isEmpty do
	(
		ctrl.items = for j = 1 to ctrl.items.count where not ctrl.selection[j] collect ctrl.items[j]
		clearselection()
		for j in ctrl.selection do select (getnodebyname ctrl.items[j])
	)
)

fn MoveItem ctrl dir:1 =
(
	if ctrl.selection.numberset == 1 do
	(
		local arr = ctrl.items
		sel = (ctrl.selection as array)[1]
		
		if case dir of
		(
			(-1):sel > 1
			( 1):sel < arr.count
		)
		do
		(
			swap arr[sel] arr[sel+dir]
			ctrl.items = arr
			ctrl.selection = sel+dir
		)
	)
)


on lbx_objects selected arg do
(
	select (for j in lbx_objects.selection collect getnodebyname lbx_objects.items[j])
)

on bt_add pressed do
	AddNodes lbx_objects

on bt_delete pressed do
	DeleteNodes lbx_objects

on bt_moveUp pressed do
	MoveItem lbx_objects dir:-1

on bt_moveDown pressed do
	MoveItem lbx_objects dir:1


on ClearRefListBtn pressed do
(
		ReplacerObjectsSet = #()
		lbx_objects.items = #()
)

on itemselect picked obj do
(
itemselect.text = obj.name
Cursel = obj
)

on ReplaceBtn pressed do
(
	ReplacedObjectsSet = #()
	--slect all the multilist items then:
	ReplacerObjectsSet = getcurrentselection()

	
	if lbx_objects != undefined OR Cursel != undefined do
	(
		undo "Object Relpacer" on 
		(
			for i = 1 to ReplacerObjectsSet.count do
			(
			maxops.clonenodes Cursel newNodes:&objClones cloneType:#instance	
			objClone = objClones[1]
			objClone.transform = ReplacerObjectsSet[(i)].transform
			i+1
			append ReplacedObjectsSet objClone				
			)
			
		if KeepMod.checked do (
			local ReverseModList = for i = ReplacerObjectsSet[1].modifiers.count to 1 by -1 collect ReplacerObjectsSet[1].modifiers[i]
			for m in ReverseModList do (addmodifier Cursel m)
			)
			
		if DelObj.checked do (
			for i = 1 to ReplacerObjectsSet.count do (delete ReplacerObjectsSet[(i)])
			)
		)
	)		
)

)
createdialog myscript
cui.registerdialogbar myscript
cui.dockdialogbar myscript #cui_d

8 Replies

This will select all items in the multilistbox:

lbx_objects.selection = #{1…(lbx_objects.items.count)}

thx Miauu for helping… but i’m still stuck with this.

–first i select all the item in the list:

lbx_objects.selection = #{1…(lbx_objects.items.count)}

– As the item are in an array, i try to select all this item in the scene:

for i=1 to lbx_objects.items.count do
(
selectmore (“$”+ lbx_objects.selection[(i)])
)

– FInally i define ReplacerObjectsSet

ReplacerObjectsSet = getcurrentselection()

The second step doesn’t work and give me a Handler Exception.

If there is no need to select objects – avoid it.

-- try (cui.unregisterdialogbar myscript) catch ()
try (destroydialog myscript) catch ()

rollout myscript "object_replacer" width:280 height:538
(

local ReplacerObjectsSet = #()
local ReplacedObjectsSet = #()
	
	local addedObjsArr = #()
	local addedObjsNamesArr = #()

multiListBox 'lbx_objects' "Objects:" pos:[8,7] width:260 height:12 align:#left
button 'bt_add' "+" pos:[10,192] width:24 height:24 align:#left
button 'bt_delete' "-" pos:[34,192] width:24 height:24 align:#left
button 'bt_moveUp' "Up" pos:[190,192] width:40 height:24 align:#left
button 'bt_moveDown' "Down" pos:[230,192] width:40 height:24 align:#left

button 'ClearRefListBtn' "Clear List" pos:[10,224] width:260 height:25 align:#left

GroupBox 'grp1' "Reference" pos:[10,264] width:260 height:140 align:#left
label 'lbl2' "Object:" pos:[20,284] width:100 height:15 align:#left
pickbutton 'itemselect' "-- none --" pos:[64,282] width:196 height:20 align:#left		


checkbox 'chk1' "Keep Original Scale - (in progress)" pos:[20,317] width:237 height:16 align:#left
checkbox 'KeepMod' "Apply Modifiers on Copy" pos:[20,338] width:132 height:16 checked:true align:#left
checkbox 'DelObj' "Delete replaced objects" pos:[20,360] width:132 height:16 align:#left

button 'ReplaceBtn' "Replace Substitudes by Reference Object" pos:[12,457] width:254 height:59 align:#left	

	on myscript open do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	callbacks.addscript #selectionSetChanged "myscript.SelectionChanged()" id:#ID0X7FB0F2910X78FF0B50
)

on myscript close do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	myscript=()
)


fn SelectionChanged =
(
	lbx_objects.selection = for j in selection collect finditem lbx_objects.items j.name
	
)

fn AddNodes ctrl =
(
	for j in selection do
	(
		append addedObjsArr j
		append addedObjsNamesArr j.name
	)
	ctrl.items = addedObjsNamesArr
)

fn DeleteNodes ctrl =
(
	if not ctrl.selection.isEmpty do
	(
		ctrl.items = for j = 1 to ctrl.items.count where not ctrl.selection[j] collect ctrl.items[j]
		clearselection()
		for j in ctrl.selection do select (getnodebyname ctrl.items[j])
	)
)

fn MoveItem ctrl dir:1 =
(
	if ctrl.selection.numberset == 1 do
	(
		local arr = ctrl.items
		sel = (ctrl.selection as array)[1]
		
		if case dir of
		(
			(-1):sel > 1
			( 1):sel < arr.count
		)
		do
		(
			swap arr[sel] arr[sel+dir]
			ctrl.items = arr
			ctrl.selection = sel+dir
		)
	)
)


on lbx_objects selected arg do
(
	select (for j in lbx_objects.selection collect getnodebyname lbx_objects.items[j])
)

on bt_add pressed do
	AddNodes lbx_objects

on bt_delete pressed do
	DeleteNodes lbx_objects

on bt_moveUp pressed do
	MoveItem lbx_objects dir:-1

on bt_moveDown pressed do
	MoveItem lbx_objects dir:1


on ClearRefListBtn pressed do
(
		ReplacerObjectsSet = #()
		lbx_objects.items = #()
)

on itemselect picked obj do
(
itemselect.text = obj.name
Cursel = obj
)

on ReplaceBtn pressed do
(
	ReplacedObjectsSet = #()
	--slect all the multilist items then:	
	lbx_objects.selection = #{1..(lbx_objects.items.count)}
	
	--	"select objects in the scene if no objects are deleted"
-- 	select addedObjsArr
	--	"if objects in the scene are deleted"
	ReplacerObjectsSet = for o in addedObjsArr where isValidNode o collect o
	--	"there is no need the select the objects. The "
-- 	select ReplacerObjectsSet
	--	""
-- 	ReplacerObjectsSet = getcurrentselection()

	
	if lbx_objects != undefined OR Cursel != undefined do
	(
		undo "Object Relpacer" on 
		(
			for i = 1 to ReplacerObjectsSet.count do
			(
			maxops.clonenodes Cursel newNodes:&objClones cloneType:#instance	
			objClone = objClones[1]
			objClone.transform = ReplacerObjectsSet[(i)].transform
			i+1
			append ReplacedObjectsSet objClone				
			)
			
		if KeepMod.checked do (
			local ReverseModList = for i = ReplacerObjectsSet[1].modifiers.count to 1 by -1 collect ReplacerObjectsSet[1].modifiers[i]
			for m in ReverseModList do (addmodifier Cursel m)
			)
			
		if DelObj.checked do (
			for i = 1 to ReplacerObjectsSet.count do (delete ReplacerObjectsSet[(i)])
			)
		)
	)		
)

)
createdialog myscript
-- cui.registerdialogbar myscript
-- cui.dockdialogbar myscript #cui_d

thx again miauu, if i well understand, you create 2 new array : one for the geometries and the other with the names and you collect the geometries before to execute the code

is that correct ?

One array for geometries and one for their names. Both arrays has the same amount of items, so when you remove/move an object from the multilistbox you have to remove/move this object in both arrays. This way in both arrays each item(object) will have the same index.
When you select and object in the multiListBox you have to find its index and then you can use addedObjsArr[index] to access the real object in the scene. This way you can have multiple objects with the same name but you will select proper object in the scene.

Geometries are collected when you press the [ + ] button. If you want to go with two arrays you have to change your code.

Once again, thx for your help. Everything is clear … but to do it is less easy ^^

First i had somme issue with the PickButton. I’ve notice sometimes itemselect.text show something (like Box001) but itemselect.object is still undifined… How is that possible ?

I fixed it usign global but not sure it’s the good way to do it:

on itemselect picked obj do
(
itemselect.text = obj.name
global RefObject = itemselect.object
)

Also, i used appendifunique to avoid multiple same object in the list like:

fn AddNodes ctrl =
(
for j in selection do
(
appendIfUnique addedObjsArr j
appendIfUnique addedObjsNamesArr j.name
)
ctrl.items = addedObjsNamesArr
)

But sor the delete button, i have some issue even if your explenation are clear.

i am able to remove one object from the list using this code:

fn DeleteNodes ctrl =
(

  if not ctrl.selection.isEmpty do
  (
  	ctrl.items = for j = 1 to ctrl.items.count where not ctrl.selection[j] collect ctrl.items[j]
  	
  	for j in ctrl.selection do (
  	deleteItem addedObjsNamesArr j
  	deleteItem addedObjsArr j
  )
  	
  	clearselection()
  	
  	for j in ctrl.selection do select (getnodebyname ctrl.items[j])
  )

)

But if i select more than 1 object, it doesn’t work.
I’ve try to use stuff like

for j=1 to ctrl.selection.count in ctrl.selection

but this is not how it’s works

can you give me some advise ?

Test this:

-- try (cui.unregisterdialogbar myscript) catch ()
try (destroydialog myscript) catch ()

rollout myscript "object_replacer" width:280 height:538
(

local ReplacerObjectsSet = #()
local ReplacedObjectsSet = #()
	
	local addedObjsArr = #()
	local addedObjsNamesArr = #()
	
	local Cursel = undefined

multiListBox 'lbx_objects' "Objects:" pos:[8,7] width:260 height:12 align:#left
button 'bt_add' "+" pos:[10,192] width:24 height:24 align:#left
button 'bt_delete' "-" pos:[34,192] width:24 height:24 align:#left
button 'bt_moveUp' "Up" pos:[190,192] width:40 height:24 align:#left
button 'bt_moveDown' "Down" pos:[230,192] width:40 height:24 align:#left

button 'ClearRefListBtn' "Clear List" pos:[10,224] width:260 height:25 align:#left

GroupBox 'grp1' "Reference" pos:[10,264] width:260 height:140 align:#left
label 'lbl2' "Object:" pos:[20,284] width:100 height:15 align:#left
pickbutton 'itemselect' "-- none --" pos:[64,282] width:196 height:20 align:#left		


checkbox 'chk1' "Keep Original Scale - (in progress)" pos:[20,317] width:237 height:16 align:#left
checkbox 'KeepMod' "Apply Modifiers on Copy" pos:[20,338] width:132 height:16 checked:true align:#left
checkbox 'DelObj' "Delete replaced objects" pos:[20,360] width:132 height:16 align:#left

button 'ReplaceBtn' "Replace Substitudes by Reference Object" pos:[12,457] width:254 height:59 align:#left	

	on myscript open do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	callbacks.addscript #selectionSetChanged "myscript.SelectionChanged()" id:#ID0X7FB0F2910X78FF0B50
)

on myscript close do
(
	callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
	myscript=()
)


fn SelectionChanged =
(
	lbx_objects.selection = for j in selection collect finditem lbx_objects.items j.name
	
)

fn AddNodes ctrl =
(
	for j in selection do
	(
		appendIfUnique addedObjsArr j
		appendIfUnique addedObjsNamesArr j.name
	)
	ctrl.items = addedObjsNamesArr
)



    fn DeleteNodes ctrl =
    (
		selItemsArr = lbx_objects.selection as array
		
		if selItemsArr.count != 0 do
		(
			for i = selItemsArr.count to 1 by -1 do
			(
				deleteItem addedObjsArr selItemsArr[i]
				deleteItem addedObjsNamesArr selItemsArr[i]
			)
			lbx_objects.items = addedObjsNamesArr
		)
    )


fn MoveItem ctrl dir:1 =
(
	if ctrl.selection.numberset == 1 do
	(
		local arr = ctrl.items
		sel = (ctrl.selection as array)[1]
		
		if case dir of
		(
			(-1):sel > 1
			( 1):sel < arr.count
		)
		do
		(
			swap arr[sel] arr[sel+dir]
			ctrl.items = arr
			ctrl.selection = sel+dir
		)
	)
)


on lbx_objects selected arg do
(
	select (for j in lbx_objects.selection collect getnodebyname lbx_objects.items[j])
)

on bt_add pressed do
	AddNodes lbx_objects

on bt_delete pressed do
	DeleteNodes lbx_objects

on bt_moveUp pressed do
	MoveItem lbx_objects dir:-1

on bt_moveDown pressed do
	MoveItem lbx_objects dir:1


on ClearRefListBtn pressed do
(
		ReplacerObjectsSet = #()
		lbx_objects.items = #()
)

on itemselect picked obj do
(
itemselect.text = obj.name
Cursel = obj
)

on ReplaceBtn pressed do
(
	ReplacedObjectsSet = #()
	--slect all the multilist items then:	
	lbx_objects.selection = #{1..(lbx_objects.items.count)}
	
	--	"select objects in the scene if no objects are deleted"
-- 	select addedObjsArr
	--	"if objects in the scene are deleted"
	ReplacerObjectsSet = for o in addedObjsArr where isValidNode o collect o
	--	"there is no need the select the objects. The "
-- 	select ReplacerObjectsSet
	--	""
-- 	ReplacerObjectsSet = getcurrentselection()

	
	if lbx_objects != undefined OR Cursel != undefined do
	(
		undo "Object Relpacer" on 
		(
			for i = 1 to ReplacerObjectsSet.count do
			(
			maxops.clonenodes Cursel newNodes:&objClones cloneType:#instance	
			objClone = objClones[1]
			objClone.transform = ReplacerObjectsSet[(i)].transform
			i+1
			append ReplacedObjectsSet objClone				
			)
			
		if KeepMod.checked do (
			local ReverseModList = for i = ReplacerObjectsSet[1].modifiers.count to 1 by -1 collect ReplacerObjectsSet[1].modifiers[i]
			for m in ReverseModList do (addmodifier Cursel m)
			)
			
		if DelObj.checked do (
			for i = 1 to ReplacerObjectsSet.count do (delete ReplacerObjectsSet[(i)])
			)
		)
	)		
)

)
createdialog myscript
-- cui.registerdialogbar myscript
-- cui.dockdialogbar myscript #cui_d

It works perfectly !

thx a lot for your help !