Hi,
I want a button to cycle through these options for my material:
.selfIllumAmount = 20
.selfIllumAmount = 100
.selfIllumAmount = 0
How can I do it?
Hi,
I want a button to cycle through these options for my material:
.selfIllumAmount = 20
.selfIllumAmount = 100
.selfIllumAmount = 0
How can I do it?
(
myMat = selection[1].material
selfIllumVal = myMat.selfIllumAmount
format "Before: %\n" myMat.selfIllumAmount
case selfIllumVal of
(
0: myMat.selfIllumAmount = 20
20: myMat.selfIllumAmount = 100
100: myMat.selfIllumAmount = 0
default: 0
)
-- "check"
format "After: %\n" myMat.selfIllumAmount
)
(
rollout RO_BUTTON_CYCLE "" width:110 height:48
(
button bt_cycle "Cycle" pos:[8,8] width:96 height:32
local list = #(0, 20, 100)
local current = 1
local mat
on bt_cycle pressed do
(
current = if current == list.count then 1 else current+=1
mat.selfillumamount = list[current]
)
)
createdialog RO_BUTTON_CYCLE
delete objects
RO_BUTTON_CYCLE.mat = (converttomesh (sphere material:(standard diffuse:red selfillumamount:0))).mat
)
You can also keep track of the variable “current” in an item of the array (list) if you don’t want to keep track of two variables.
(
rollout RO_BUTTON_CYCLE "" width:110 height:48
(
button bt_cycle "Cycle" pos:[8,8] width:96 height:32
local list = #(2, 0, 20, 100)
local mat
on bt_cycle pressed do
(
mat.selfillumamount = list[ if list[1] == list.count then list[1]=2 else list[1]+=1 ]
)
)
createdialog RO_BUTTON_CYCLE
delete objects
RO_BUTTON_CYCLE.mat = (converttomesh (sphere material:(standard diffuse:red selfillumamount:0))).mat
)
Max2020 - no stuck. Check this video:
https://drive.google.com/file/d/1kWvRwsxVuhbGo1MjIk58qEjmIfHPfTTc/view
StdMatAdvCA = attributes StdMatAdvCA attribid:#(0x3F981131, 0x7431DD17)
(
fn getOwner =
(
custAttributes.getOwner this
)
parameters params rollout:params
(
undoable type:#boolean default:off ui:undoable_ch
)
rollout params "Advanced Controls"
(
checkbox undoable_ch "Undoable" across:2
button illum_loop_bt "Loop Self Illum" width:172 align:#right offset:[0,-3]
on illum_loop_bt pressed do undo "Change Illum" undoable
(
if iskindof (mat = getOwner()) Standard do
(
si = mat.selfIllumAmount
if keyboard.shiftPressed then
mat.selfIllumAmount = if si <= 0 then 100 else if si <= 20 then 0 else 20
else
mat.selfIllumAmount = if si >= 100 then 0 else if si >= 20 then 100 else 20
)
)
on illum_loop_bt rightclick do undo "Change Illum" undoable
(
if iskindof (mat = getOwner()) Standard do
(
mat.selfIllumAmount = 0
)
)
)
)
-- custattributes.add meditmaterials[1] StdMatAdvCA
These are all very clever solutions. Thank you.
@miauu, unfortunately, I need it to work down to 2016 version at least
@PolyTools3D, thanks it’s easy to take and adapt
@denisT, unfortunately, I couldn’t run it on 2016 version. It’s just nothing happen
@PolyTools3D, when I apply it to multimaterial I get different illum value for every material. I’m using this code:
local mat = $.material
for m in mat do
(
current = if current == illum_arr.count then 1 else current+=1
m.selfIllumAmount = illum_arr[current]
)
I illustrated illum values here:
What do you have with this:
local mat = $.material
current = if current == illum_arr.count then 1 else current+=1
for m in mat do
(
m.selfIllumAmount = illum_arr[current]
)
this works great.
p.s.: realized how stupid I am including multiplier inside the loop for multimaterial
unfortunately you don’t want to try to understand the code which of course works in any version.
@PolyTools3D, unfortunately, it returns random result if I applied it to several objects, any way to adjust the code?
@denisT, you’re right, params and attributes are too complicated for me. My task right now is not to learn maxscript, but to sort out the materials. However, I learn something every time I ask for help.
If you want to see how CA works in this case, uncomment the last line in my code and run the whole code.
Expecting the first material in the material editor is the Standard material, you will get a user interface created by applying CA to the material. This user interface will be available through both the Compact and Slate Mat editors. You should see an additional “Advanced Controls” rollout with a “Loop” button.
From a usability point of view, a solution with a single button that sets one of the predefined values in a loop is inconvenient. It’s easier in all respects to make N buttons with a specific value for each.
In our case, it’s better to make three buttons “0”, “20”, and “100”…
It is easier to implement from the code side, it is clearer from the point of view of the user interface, it is easier to change and expand it functionally.
Play with this:
StdMatAdvCA = attributes StdMatAdvCA attribid:#(0x3F981131, 0x7431DD17)
(
fn getOwner =
(
custAttributes.getOwner this
)
parameters params rollout:params
(
undoable type:#boolean default:on ui:undoable_ch
illumAmounts type:#inttab tabSize:5 tabSizeVariable:false
on illumAmounts set val i do
(
this.params.updateIllumButtons()
)
)
rollout params "Advanced Controls"
(
local btw = 26
checkbox undoable_ch "Undoable" across:2
button illum_loop_bt "Loop Self Illum" width:(5*(btw + 2) - 2) align:#left offset:[16,-3]
button illum_bt0 "" width:btw pos:(illum_loop_bt.pos + [0*(btw + 2),24])
button illum_bt1 "" width:btw pos:(illum_loop_bt.pos + [1*(btw + 2),24])
button illum_bt2 "" width:btw pos:(illum_loop_bt.pos + [2*(btw + 2),24])
button illum_bt3 "" width:btw pos:(illum_loop_bt.pos + [3*(btw + 2),24])
button illum_bt4 "" width:btw pos:(illum_loop_bt.pos + [4*(btw + 2),24])
local illum_bts = #(illum_bt0, illum_bt1, illum_bt2, illum_bt3, illum_bt4)
fn updateIllumButtons =
(
for k=1 to illumAmounts.count do
(
illum_bts[k].text = illumAmounts[k] as string
)
)
fn setIllumAmount index:1 = undo "Change Illum" undoable
(
if iskindof (mat = getOwner()) Standard do
(
mat.selfIllumAmount = illumAmounts[index]
)
)
fn getIllumAmount index:1 = undo "Store Illum" on
(
if iskindof (mat = getOwner()) Standard do
(
illumAmounts[index] = mat.selfIllumAmount
)
)
on illum_bt0 pressed do setIllumAmount index:1
on illum_bt1 pressed do setIllumAmount index:2
on illum_bt2 pressed do setIllumAmount index:3
on illum_bt3 pressed do setIllumAmount index:4
on illum_bt4 pressed do setIllumAmount index:5
on illum_bt0 rightclick do getIllumAmount index:1
on illum_bt1 rightclick do getIllumAmount index:2
on illum_bt2 rightclick do getIllumAmount index:3
on illum_bt3 rightclick do getIllumAmount index:4
on illum_bt4 rightclick do getIllumAmount index:5
on illum_loop_bt pressed do undo "Change Illum" undoable
(
if iskindof (mat = getOwner()) Standard do
(
si = mat.selfIllumAmount
if keyboard.shiftPressed then
mat.selfIllumAmount = if si <= 0 then 100 else if si <= 20 then 0 else 20
else
mat.selfIllumAmount = if si >= 100 then 0 else if si >= 20 then 100 else 20
)
)
on illum_loop_bt rightclick do undo "Change Illum" undoable
(
if iskindof (mat = getOwner()) Standard do
(
mat.selfIllumAmount = 0
)
)
on params open do
(
updateIllumButtons()
)
)
on postcreate do
(
illumAmounts = #(0,20,50,80,100)
)
on update do
(
illumAmounts = #(0,20,50,80,100)
)
)
--custattributes.add meditmaterials[1] StdMatAdvCA
Yes, the code can be modified, but you need to be very specific about what you are trying to achieve.
@PolyTools3D, thanks for your work : -0 I have many different models. All of them are built with Standard materials. Some models have multimaterials built with a list of Standard materials. Initial Illumination amount for all the models set to 0.
I want to select the model or group of models and cycle the Illumination value for every material of the selected model(s) between 0, 20 and 100.
@denisT, thanks for the script, I’m building quick tools for myself most of the time and want to keep the work with the UI as focus as possible in a particular area of the screen. The more buttons I make, the less efficient I became. I don’t like this, that’s why I just put a tooltip to a button if it’s really needed. I will try the script now
This script will cycle the materials illumination amount on the selected objects.
Notes:
The script does not track individual materials values, so all the materials on the selected objects will be set to the same illumination amount, and the “current” value will keep cycling over and over.
If what you need is to keep track of each individual illumination amount, and cycle them individually to the next value, things will get a bit more complex.
(
-- TEST SCENE FUNCTIONS -------------------------------------------------------------------------------
fn GetRandomColor =
(
clr = random black white
clr.s = 100
clr.v = 255
return clr
)
fn CreateMultiMaterial =
(
mm = multimaterial numsubs:9
for j = 1 to 9 do
(
mm[j].diffusecolor = GetRandomColor()
mm[j].selfillumamount = 0
)
return mm
)
fn CreateNodes =
(
for j = -2 to 2 do
(
for k = -2 to 2 do
(
obj = converttopoly (plane pos:[j*30, k*30, 10] lengthsegs:3 widthsegs:3 wirecolor:black)
if (random 1 3) == 1 then
(
for i = 1 to 9 do polyop.setfacematid obj i i
obj.mat = CreateMultiMaterial()
)else(
clr = GetRandomColor()
obj.mat = standard diffuse:clr selfillumamount:0
)
)
)
)
-- TEST SCENE FUNCTIONS -------------------------------------------------------------------------------
try (destroydialog ::RO_BUTTON_CYCLE) catch()
rollout RO_BUTTON_CYCLE "" width:110 height:48
(
button bt_cycle "Cycle" pos:[8,8] width:96 height:32
local list = #(0, 20, 100)
local current = 1
on bt_cycle pressed do
(
if selection.count == 0 do return (print "No objects selected")
current = if current == list.count then 1 else current+=1
illumVal = list[current]
for j in selection do
(
mat = j.mat
if iskindof mat multimaterial then
(
for k in mat do k.selfillumamount = illumVal
)
else if iskindof mat standardmaterial then
(
mat.selfillumamount = illumVal
)
else
(
format "Invalid Material: node:% material:%\n" j.name mat
)
)
)
)
createdialog RO_BUTTON_CYCLE
-- CREATE TEST SCENE
delete objects
CreateNodes()
gc()
)