[Closed] Interested in Knowing why something is failing
I made a script to read the number of particles in a scene, take the TM information, and birth a new particle there. It attempt is to simulate cells splitting apart to make two new cells. Right now, im just working on the base motion. Still have no idea how the cells should look, or any rendering issues tackled.
Another script is going to track the motion of each particle and move some geometric objects over each particleTM per key frame in the slider bar. That works so far.
There are certein error codes that are coming up in the code below, included at the bottom that I dont understand the origins of. To me, all the code should work, but i am asking if you could take a look and tell me if i am missing anything that would make it error.
This i some of my first Coding experience.
The script is in a standard flow with a script operator in the second event.
If anything is confuseing I would be happy to clarify.
on ChannelsUsed do
(
pCont.useTM = true
pCont.useTime = true
)
on Init pCont do
(
–declaring a function for random numbers
fn randstep seed:(Random 1 100) =
(
Rand = Random 5 8
)
–getting current time
oldTime = slidertime
–setting up what random step the slidertime check integrates
theStep = 0
)
on Proceed pCont do
(
/Made this check to be true at start of slidertime check, which should always start at zero. If the time is Zero, this will be 0 == 0 + 0
theTime = slidertime
If theTime == (oldTime + theStep) then
(
pMax = pCont.NumParticles()
–print pMax
–For all the paricles in the scene, add a particle using the TM of each live particle for each emitter point
for i = 1 to PMax do
(
– Get the transformation matrix from each particle
pCont.particleIndex = i
thePID = pCont.getParticleID i
PTM = pCont.getParticleTMByID thePID
–Adding particle at the Aboves TM info
pCont.AddParticle()
pCont.particleIndex = pCont.NumParticles()
pCont.particleTime = theTime
pCont.particleTM = PTM
)
–Once amm emissions done, reset theStep
theStep = RandStep()
–print theStep
)
)
on Release pCont do
(
–Always wondered what this was for…Hmmm
)
MouseTool:ScriptAction19AF4CC0
– Error occurred in anonymous codeblock; filename: B:\K\My Scripting\Birth Script_Find Position.ms; position: 19
– Type error: Call needs function or class, got: true
– Error occurred in anonymous codeblock; filename: B:\K\My Scripting\Birth Script_Find Position.ms; position: 75
– Syntax error: at on, expected while
– In line: on I
This looks like it’s breaking it:
on Init pCont do
Are you sure that function (?) is defined correctly?
The first problem is in the line
on ChannelsUsed do
which should be
on ChannelsUsed pCont do
But that’s just the beginning.
Next thing to know is that the PFlow event handlers are in the top scope and create their own local scopes, so any variables declared in the on Init() handler won’t be visible to the on Proceed() handler unless they are global. So both oldTime and theStep must be declared as explicitly global (and to avoid collisions with other scripts, their names better be more unique than that).
Defining that randStep function is quite unnecessary, and there is no need to pass a random seed to it as argument (not that is is actually doing anything – it just makes a seed local variable that has no effect on the random calls at all). You should call the SEED method just once in the On Init() handler outside of the function to ensure all your random() calls later on will always lead to the same result if you execute from the beginning with the same settings, esp. on multiple machines (if network rendering). You should NEVER call SEED() with a random value, always with a constant integer value to produce repeatable results. When you want a random step, just say theStep=random 5 8 and you are done.
In the on Proceed() handler, you are reading the SLIDERTIME. Bad Idea! The SliderTime is available only when playing back in the viewports and might jump over frames if RealTime is ON in the Time Settings, but not at render time. Even the CurrentTime global variable which is set correctly at render time might be a bad idea because the Script Operator could be evaluated several times on sub-frame steps different from the currentTime which contains the frame being rendered. Remember that the default Integration step of PFlow for Rendering is 1/2 frame, and you want THAT time. Take a look at a default Birth Script to see how the time range of an operator is accessed using pCont.getTimeStart() and pCont.getTimeEnd().
Finally, to answer your curiosity about the on Release() handler, it is rarely used, but the main idea is that if you are performing some initialization work in the on init() handler that you want to remove when the operator is reset, you can do this in the on Release() handler. For example, if you were creating temp. objects that are needed by the Script Operator but you want them gone when it is done and before the on init() is called again to create even more of them, you could delete/clean up in the on Release() handler. Personally, I have never used it for anything, but it is good to know it exists if I ever need it…
Hope this helps.
Don’t know if I am thinking too simple here, but why not using a Spawn Test?
First off, its an honor Bobo.
I will have to look over the rules of scope in PFlow again. It is a great help to have these things pointed out. The rules of some things in Maxscript seem very discretely stated in the Help File, and keeping track of them is difficult.
I have played a bit with pCont.getTimeStart() and pCont.getTimeEnd(). I was having trouble getting the values to display, and I only have partial understanding of where the values were being taken from. Time feels very difficult in Maxscript. I am aware of differences in Particle time, event time, and other time values tracked outside of PFlow, but do not understand how they affect each other.
Some very basic questions that worried me about Event Time for example, were “When is the time value initiated by the user?” Is it directly linked with the slider time? Does event and particle time mean different things? I opted to go with slider time, since it felt easier to grasp.
Piflik: This is my second Script, the First with Pflow. So my question is: What would make a spawn test simpler?
dutch_delight: I think that function is declared correctly. What makes it look wrong?
[center] [/center]
[center] [/center]
[center]General Response:I am listening to everyone who replies here, but limited internet connectivity keeps me from answering regularly. Thanks you to everyone that is trying to help. I need every bit I can get.[/center]
It is easier because it is no Script, but an integrated Operator…together with an Age Test and a recursive loop (new particles being piped back into the previous Event) it should be exactly what you want…you might want to delete particles after a certain time, else you will be overwhelmed by particles in some time
I see. I neglected to mention the purpose of the script. I am looking to spawn particles using renderable particle’s transformation matrices, but only for a random interval of time, and only for some of the particles, say, 60%.
The spawn test should go continuously per integration step of the Flow, using all available particles. I could use the split amount, now that I am thinking about it. to control a percent, or rate. I have no immediete idea for skipping certein integration steps without script.
But I guess this is also about learning, so I think I am hoping to comprehend more script vibe by using this script in place of the spawn test. I have updated the script, but I cannot post it until monday.
It took longer than I expected. I have added some of the ideas given to me.
My only idea now is getting the particles to animate the right way. My idea is to make them glob out like a fountain, sticking close together, but growing. Right now I am only doing particle flow to direct the motion, because I could not think of another way to spawn from particle locations. I realize am trying something that sounds alot like fluid simulation, but I hope to make this work with getting much more complicated than I have. Besides, I can’t afford any more toys…
--To check for the number of particles
--
on ChannelsUsed pCont do
(
pCont.useTM = true
pCont.useTime = true
)
on Init pCont do
(
--Starting Values to run Proceed loops through on first time
--
GLOBAL randStep = random 9 16
GLOBAL endOfTheRange = animationRange.end.frame
GLOBAL oldTime = animationRange.start.frame
)
on Proceed pCont do
(
--I want to deal with numbers, so the frame property is sought
newTime = (pCont.getTimeStart()).frame
--checking against the end of the time range for when to stop
If (newTime <= endOfTheRange) do
(
--Method breeaks down when there are negative numbers, should be true once
If newtime < 0.0 then newtime = 0.0
-- This will take start of integration step and check if equals Step integer + Old Slider Value
If (newTime == (oldTime + randStep)) then
(
--reassigning Globals to run through the loop in the next iteration
GLOBAL oldTime = newTime
pMax = pCont.NumParticles()
GLOBAL randStep = random 9 17
--Using Randstep to include a percentage of total particles
for i = 1 to PMax by 3 do
(
--Finds the Matrix of particle ID, assigning TM to new particle
pCont.particleIndex = i
thePID = pCont.getParticleID i
PTM = pCont.getParticleTMByID thePID
pCont.AddParticle()
pCont.particleIndex = pCont.NumParticles()
pCont.particleTime = newtime
pCont.particleTM = PTM
)
)
)
)
on Release pCont do
(
/* If isHungry == true do
(
Make_Sandwich breadSelection meatCuts isTomatoe isLettuce totalCondiments isToasted
Make_Sandwich
)
*/
)
Using the above code, I decided to go ahead with making the particle effect. I described it incompletely as a particle fountain. I need the particles to spawn, slow, them stop, but still be available for the script to spawn new particles from them. These new particles will have to be taken in by the spawn particle code after genreating, but after slowing.
Not sure how to do this, I created this Flow, to try and move the particles to each new event with a script test check is pCont.ParticleNew is true for each particle.
I have a few issues with this, and would appreciate any kind of advice.
It basically does not work. I must be missing something crucial about what particles need to exist. The particle disappears after the first event with the Birth, known to me only when all other events are turned off. Even limiting them to the second event (with the speed by surface) it stops being visible.
Everytime I replay my time slider, my custom script operator loses its ability to spawn particles. Are there special methods that work towards a good workflow when using addParticle inside a script?
Not a Question:
PFlow is very frustrating in the second hand nature of its understanding. Not all your actions have forseable consequences with so many descrete rules and dependancies. I wish there was an easier compendium for it, or that there was a lcoser community oif scripters where I lived…
instead of checking if it is ParticleNew, you could assign an arbitrary number to each particle when it is born:
you will first need to make sure you include at the top:
pCont.useInteger = true
then pick a number (such as 1) to mark particles that are new when it is cloned:
pCont.AddParticle()
pCont.particleIndex = pCont.NumParticles()
pCont.particleInteger = 1 -- means the particle is new
later you can test the integer to see if the particle is new:
if (pCont.particleInteger == 1) then
--do something
you could then reset this value to 0 or any other number later on when you no longer want the particle to be considered new. I use this sort of technique all the time to keep track of particles with different “states”
As for the particles disappearing… it’s hard to say without seeing your flow, but maybe it’s something as simple as adding a shape operator?
As for the script breaking… this happens all the time with PFlow scripts. They seem to be particularly temperamental. When I am having problems like this, I will reset the time slider and then re-evaluate all my script operators just to make sure they are current and not broken.