[Closed] My first script – Firelight reproduction
Hi guys,
I just set myself a little challenge as a means of learning a bit of maxscript. I’ve never touched it before (though I know PHP and, shudder, vb6) so I didn’t want to go for anything too advanced. Anyway, it’s just a little app that allows the user to set a min value and max value for the multiplier variable of an omni (that you select), as well as a start frame and end frame, and then every 3 frames it will key a random value between those two numbers. This roughly gives the look of a flickering light, like a flame (though the only thing it affects is the multiplier, not colour or anything).
I’m not sure, but there may well be a really easy way of doing this in Max and I’ve just made someone no one has a use for at all, but as I said, I made it to practice myself so I’m pretty happy with it. Here’s the script, the .ms and a video test:
rollout MyRoll "Fire!"
(
edittext min1 "Min Light:" pos:[10, 10]
edittext max1 "Max Light:" pos:[10, 30]
edittext sframe "Start Frame:" pos:[10, 50]
edittext eframe "End Frame:" pos:[10, 70]
button submit "Affect" pos:[30, 120]
button help "Help" pos:[90, 120]
on min1 entered txt do (
global mini
mini = (min1.Text as float)
)
on max1 entered txt do (
global maxi
maxi = (max1.Text as float)
)
on sframe entered txt do (
global sframe1
sframe1 = (sframe.Text as float)
)
on eframe entered txt do (
global eframe1
eframe1 = (eframe.Text as float)
)
on help pressed do (
messagebox "Hi folks.
Min Light: Lowest value for the light multiplier to go to.
Max Light: The Max it can go to.
Start Frame: The first frame for flickering to begin.
End Frame: The last frame for flickering to continue."
)
on submit pressed do (
animate on(
omni1 = selection
for t in sframe1 to eframe1 by 3 do
at time t
omni1.multiplier = (random mini maxi)
)
DestroyDialog MyRoll
)
)
createdialog MyRoll height:150 width:150
I hope you accept comments and suggestions
First of all, good start!
Some things you might not know about MAXScript that would help you simplify the code:
-
Instead of using text fields and converting them to floats (which would fail if the user typed in “ha!”, you could use value spinners directly.
-
No need for global variables to pass the data to your main function. They are in the same scope, so directly accessing the value from the spinner (or even the text field) would be easy. Global variables are used rarely and in special cases like interaction between two scripts, storing top-level things like rollouts and dialogs etc.
-
‘selection’ is a dynamic object set which contains all selected objects at the moment. Since many MAXScript functions including value assignments are mappable, you are assigning the random value to ALL selected objects, which of course works for a single light, too. But it does not check whether the selection contains anything else, and would crash if you select an omni and a box, for example.
-
Since the mapped assignment evaluates the right-hand side once and assigns to all objects on the left-hand side, if you selected 5 lights, they would all flicker in unison. So it is better to loop through all selected objects, make sure they are light class and assign a unique random value to each for that frame.
-
Giving the user cool preset values is a good thing if you want them to use the tool. So setting the min to 0, max to 1, start and end frames to the current range is a good idea.
rollout MyRoll "Fire!"
(
spinner min1 "Min Light:" fieldwidth:50 range:[0,1000,0]
spinner max1 "Max Light:" fieldwidth:50 range:[0,1000,1]
spinner sframe "Start Frame:" fieldwidth:50 range:[-100000,100000,animationrange.start]
spinner eframe "End Frame:" fieldwidth:50 range:[-100000,100000,animationrange.end]
button submit "Affect" across:2 align:#left width:62
button help "Help" align:#right width:62
on help pressed do (
messagebox "Hi folks.
Min Light: Lowest value for the light multiplier to go to.
Max Light: The Max it can go to.
Start Frame: The first frame for flickering to begin.
End Frame: The last frame for flickering to continue."
)
on submit pressed do (
animate on(
for t in sframe.value to eframe.value by 3 do
at time t
for o in selection where superclassof o == Light do
o.multiplier = random min1.value max1.value
)--end animate
DestroyDialog MyRoll
)--end pressed
)--end rollout
createdialog MyRoll height:120 width:150
Please accept this as a form of a tutorial and not a critique. You have done great for a first attempt at MAXScripting!
Don’t worry, i’m certainly not offended! I appreciate the time you took to reply!
-
Spinners definitely seem like a good idea. I knew they existed, so I really have no idea why I didn’t use it!
-
Ah, I wasn’t sure about the global variables. Thanks for that. I came up with a peoblem (I can’t even remember what now) and I thought that maybe I had to declare the variables for some reason, and so I just shoved in global for the hell of it. Thanks again.
3 & 4. Gotcha. I really hadn’t tested this thoroughly! I’ve never really intended this or any future scripts I make for public use, though people are more than welcome to if they wish. I figured I will always know how to use my own script
- Again, good idea, I didn’t even think about it.
One thing I’ve also noticed about your version, in reference to 3 & 4, is that this should work with all lights now, not just omnis, unlike mine!
Again, thanks very much, it’s genuinely appreciated!
Not true, your version works with any lights, and any number of them. It only requires the user to select them carefully, because selecting a target object together with a target spot would crash the script. But there is nothing in your version that prevents it from working with Direct, Spot etc. lights, as long as they have a Multiplier property (which all lights have, even the sky, sun, photometrics etc.)
Dur! Sorry, I was getting confused with an earlier version I made where it created the omni itself. Woops!
Again, thanks very much.
Bobo I’ve had a question and this seems like a good place to put it.
Is there a way to adjust the speed of the spinner. I know you can press down alt to make a spinner more fine and ctrl to make it more coarse. But I have scripts where I always want it to be fine since 90% of the time the selection is an integer between 2 and 5. In this case it would be nice if the spinners for min and max were very fine since 90% of the time 2 would probably be the maximum value and dialing in to the 100’th position would be in order.
spinner max1 "Max Light:" fieldwidth:50 range:[0,1000,1] scale:0.001
The scale: parameter controls the precision, in this case the spinner would go with 1/1000 per click.
But I’m talking about when you roll the spinner. I.E. Click and drag up/down. If it’s an integer then the scale will always be => 1.0 won’t it? Or can you trick it by declaring it as an integer and set the scale super small so that it scrolls through the integers slow? One click should still = +/- 1 but clicking and dragging is less coarse.
this is a great thread!!
thanks for the cool beginner info Bobo and cool idea for a first script Kaltagesta
-Baker