Material add OBJ - custom link checkbox with radiobuttons


#1

Hi,

I would need to link multilistbox material and multilistbox obj from scene. On the material editor I would use checkboxes so that more “IDs” could be marked but on the object I would use radiobuttons so that only one group could be selected.

struct my code

(
struct MyFunctionsStruct
(
fn RMa =
(
— defining range
sc = 0
for m in matarrayoptiA do sc = sc + m[2]
— random function in range

    --- defining the hit in range
    for o in selection do
    (	
        r = random 0.0 sc
        trg = true
        tmpm = undefined
        s = 0
        for m in matarrayoptiA do
        (
            s = s + m[2] -- greater limit
            if r <= s then 
            (	
                
                if trg then 
                (	
                    --print m[1].name
                    tmpm = m[1]
                )
                trg = false
            )
        ) -- end for matarray
        try
        (
            o.material = tmpm
            o.material.showInViewport = true
        )
        catch()
    ) -- end for selection
    ) , 

(
global MyFn = MyFunctionsStruct()
try(DestroyDialog ::main)catch()

rollout main “Layer Seting” width:250 height:200
multiListBox lbxSelOBJ1 “Sel OBJ Group 1” pos:[10,7] width:180 height:12
radiobuttons rdo_obj1 “Group ID” pos:[220,20] labels:#(“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”) columns:1
multiListBox lbxSelOBJ2 “Sel OBJ Group 1” pos:[10,7] width:180 height:12
radiobuttons rdo_obj2 “Group ID” pos:[220,20] labels:#(“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”) columns:1
multiListBox lbxSelOBJ3 “Sel OBJ Group 1” pos:[10,7] width:180 height:12
radiobuttons rdo_obj3 “Group ID” pos:[220,20] labels:#(“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”) columns:1

rollout VDopti “Layers Mats V1” width:330 height:600
listbox lbx1opti1 “” height:10 pos:[8,40] width:180
checkbox chk_1 “” pos:[255,40] checked:true
checkbox chk_2 “” pos:[255,60] checked:true
checkbox chk_3 “” pos:[255,80] checked:true
checkbox chk_4 “” pos:[255,100] checked:true
checkbox chk_5 “” pos:[255,120] checked:true
checkbox chk_6 “” pos:[255,140] checked:true
checkbox chk_7 “” pos:[255,160] checked:true
checkbox chk_8 “” pos:[255,180] checked:true
checkbox chk_9 “” pos:[255,200] checked:true
button rnopti1 “Randomize Materials 1” width:180 height:32 pos:[8,200]

)

my idea was such a function

on rnopti1 pressed do MyFunctionstruct.RMa()
if chk_1.checked = rdo_obj1 “1” and rdo_obj2 “1” and rdo_obj1 “2” do add material for all obj.name in “multilistbox” lbxSelOBJ1,lbxSelOBJ2,lbxSelOBJ3

any idea how to do it? well thank you


#2

What’s the logic behind all that? What IDs and group IDs are?


#3

The “ID” and “ID group” marks are symbolic. I originally thought of segmenting in the form of an ID, but in another part of the code I use something where the ID doesn’t help me.

I would need to link the material list with the object list. If the material is “1”, only the listbox marked “1” will be assigned.


#4

you can store all objects and materials in arrays and simply use selection indexeses of listbox controls to assign ‘selected’ materials to ‘selected’ objects


delete objects
gc()

try (destroydialog X ) catch ()
rollout X ""
(
	MultiListBox obj_list "objects:"
	MultiListBox mtl_list "materials:"
	
	local scene_objects = #()
	local materials     = #()
	
	on x open do
	(
		scene_objects = for i = 1 to 5 collect teapot pos:(random [-300,-300,0] [300,300,0])
		materials     = for i = 1 to 5 collect Standardmaterial diffuse:(random white black) name:("mtl_" + i as string)
		
		obj_list.items = for obj in scene_objects collect obj.Name
		mtl_list.items = for mtl in materials     collect mtl.Name		
	)
	
	on obj_list selectionEnd do 
	(
		select (for i in obj_list.selection where isValidNode scene_objects[i] collect scene_objects[ i ])
	)
	
	on mtl_list selectionEnd do 
	(
		if obj_list.selection.isEmpty or mtl_list.selection.isEmpty do return ok
		
		local objs = for i in obj_list.selection collect scene_objects[ i ]
		local mtls = for i in mtl_list.selection collect materials[ i ]
			
		
		objs.material = mtls[ 1 ] -- but what you're going to do with the rest of selected materials?	

		format "material assignment complete...\n" 
	)
	

)
createDialog X pos:[100,100]

#5

Thank you for your code. It works great on its own. I couldn’t apply it to my code.

I thought I would do the opposite work.

     on rnopti1 pressed do ( if lbx1opti1.selection != 0 then --OK
			
									(	allNodes = for item in lbxSelOBJ1.items collect getNodeByName item --??
										(	if rdo_obj1.state == 2 then --OK
											(if chk_1.checked == 1 then --OK
												( if selection == allNodes do  --??                                                            
													(MyFunctionsStruct.RMa()))))))--random add material

I would like to create the condition “if the object is selected - the name will be in the multilistbox function will be run” so if the object is not in the multilistbox function it will be skipped.

Is it possible to go in this direction?


#6

make a function that takes collection as the argument and do whatever you need with these nodes

fn RandomWirecolor nodes = 
(
    for n in nodes where isValidNode n do n.WireColor = random white black
)
...
...
allNodes = for item in lbxSelOBJ1.items collect getNodeByName item --??
RandomWirecolor allNodes 

#7

I’m broken.

I’ve been trying for weeks to learn how to do it, but I can’t prove it. If you had free time could you write “fn” for me? I managed to make a better multilistbox with callbacks and it works beautifully. I would need to solve two problems so that I can move on.

“fn allNodes nodes arg”

fn chx = chk_1.checked == 1
local scene_objects = #()

fn SelectionChanged = --OK
(
lbxSelOBJ1.selection = for j in selection collect finditem lbxSelOBJ1.items j.name
)
on main open do --OK
(
callbacks.removescripts id:#ID0X7FB0F2910X78FF0B50
callbacks.addscript #selectionSetChanged “main.SelectionChanged()” id:#ID0X7FB0F2910X78FF0B50
)
on lbxSelOBJ1 selected arg do --OK
(
select (for j in lbxSelOBJ1.selection collect getnodebyname lbxSelOBJ1.items[j])
)

fn allNodes nodes arg =
(
for n in nodes where isValidNode collect lbxSelOBJ1.items n.name = object.items n.name
)

     on rnopti1 pressed do ( if lbx1opti1.selection != 0 then --OK
  									(if rdo_obj1.state == 1 then --OK
  										(if chx() then --OK
  											( if allNodes nodes () do                                      
  												(MyFunctionsStruct.RMa())))))--random add material

fn RMa - work good, but
if i have 100 material in listbox and 100object in scene do random a many material for all objects - but i need call random “ONE” material for all selected object - " i need change defining range?"

fn RMa =
(

            --- defining range
           sc = 0
  		for m in matarrayoptiA do sc = sc + m[2]
  			--- random function in range
            
            --- defining the hit in range
            for o in selection do --= material filename:(lbx1opti1.items [lbx1opti1.selection + (random 0 2 )] )
            (	
                r = random 0.0 sc
                trg = true
                tmpm = undefined
                s = 0
                for m in matarrayoptiA do
                (
                    s = s + m[2] -- greater limit
                    if r <= s then 
                    (	
                        if trg then 
                        (	
                            --print m[1].name
                            tmpm = m[1]
                        )
                        trg = false
                    )
                ) -- end for matarray
                try
                (
                    o.material = tmpm
                    o.material.showInViewport = true
                )
                catch()
            ) -- end for selection

I’m losing strength, thank you


#9

I changed the whole functionality because it was not very logical. I’m working with an ID now. This is my new structure.

Sel OBJ Group - working good.
fn = select obj - assign constant value ID (add in modifier material with ID value and collaps - all face change id)

fn Randomize Materials = assign material from multilistbox on selected obj in scene.

I would need to specify the ID in the material randomize.
If sett value ID 1 assign material for only OBJ with ID 1
but, I will have a selection of many objects with different IDs

Is it realistic to do this?


#10

I guess it is hopeless. Either someone else should write you this script or you need to describe your task precisely in order to get the help. :man_shrugging:


#11

Sorry,

For example: I have two objects “box1 - has ID 1” and “box2 - has ID2” / ID is meant as $ .EditablePoly.setMaterialIndex 1 - element /, I need to solve this problem: If I select “box1” and "box2 “together, material will only be added to” box1 ".

I don’t know how to proceed. Do I have to use a g-buffer object ID? Or is it possible to set my material list as Multi-Sub material? How would the easiest way to solve this problem?


#12

Why it should work like that?


#13

I will have many objects, and I need to divide materials and objects. I will always have all the selection.
Really I want to make: I have a car model. All wheels will be ID1 and I need to use black materials only for wheels. The windows will be ID2 and I only need to assign them materials - glass of “different shades”. The sheets on the car will be ID3 and I only need to add metallic colors there.

I will create 3 different listboxes with materials and I will always randomly add material only to selected ID1 or ID2 or ID3 objects.


#14

Sounds like all you need is a single multimaterial with N submaterials
Changing one submtl won’t affect others if that’s what you need. This will limit you to only one material for each ID.
If you need multiple submaterials for each ID that’s whole different story and you won’t be able solve it with multimaterial


#15

Yes, I need multiple submaterials for each ID. How can this problem be solved? It is possible?


#16

Actually you can try to use multimaterial
Just make a separate ID ranges that won’t intersect with each other
i.e
ID#1 uses 1…10
ID#2 uses 11…20
and so on
this way you can have up to 10 random materials for each ‘ID’ and of course you’ll have to modify geometry ID’s to use that kind of randomization


#17

Yes, I understand the material would be one multi / sub and I would change the random ID object, so I will automatically change the materials. I should be able to do this.


#18

Maybe I found a solution. The material must be a multi / sub material. In multi / sub I can change the ID perfectly. I’ve tested one material and it’s okay “Material # 35” but I’ll have a lot of materials, I can write to make this change for all materials / names in the listbox?

on id_change pressed do
(
currentMaterialLibrary[“Material #35”].materialIDList[1] = idSpn.value
)


#19

I don’t know. This piece of code tells almost nothing. Test it and see if it is what you need


#20

Yes the code works, change the ID according to the spinner. But the ID only changes the material “Material # 35”. I would need to get all the names from the listbox.