VolumeDocking Sample Script


The following sample is based on Laszlo Sebo's VolumeDocking01.max scene and illustrates the following MAXScript operations with Particle Flow:

Can Be Used With:

The script is self-contained and recreates all objects and Particle Flow Events and Actions on the fly:



The script creates two geometry primitives and two PF_Sources with corresponding Actions and Events.

The geometry objects are used as volumes to be filled with particles. The initial positions of the particles are dumped to the particleVector channel. Using a Find_Target action, the particles find their way from the one volume to the other and switch places after swirling around.






-- Set scene animation range to 150 frames

animationRange = interval 0f 150f

-- Create Cylinder primitive

cyl=cylinder radius:44 height:44 heightsegs:5 sides:18 pos:[-60, -55, 0]

-- Create a Torus primitive

tor=torus radius1:55 radius2:20 smooth:2 pos:[135, 120, 0]

-- Create a Vortex Space Warp

vor=vortex timeOff:33 axialStrength:22 rotationStrength:33 iconSise:40 rotation:(quat -1 0 0 0) pos:[20,35,-5]


-- PF_Flow setup

pf=PF_Source Show_Logo:off Show_Emitter:off Quantity_Viewport:100 isSelected:true



-- Action List - Appending Example --



-- Disable automatic Event Encapsulation – begin editing:


a1 = RenderParticles() --define Action 1

pf.AppendAction a1 --append the Action to PF_Source

ParticleFlow.EndEdit() --End editing, enable Auto-Encapsulation


x=y=1 --Initialize two variables

--Get the location of the PF_Source in Particle View:

pf.GetPViewLocation &x &y



-- Define First Event --


ParticleFlow.BeginEdit() --start editing

-- Create a Birth Action for Event 1

ev1_a1 = Birth Emit_Start:0 Emit_Stop:0 Amount:300


-- Create a Position Object Action for Event 1

ev1_a2 = Position_Object Location:4 Emitter_Objects:#(tor) name: "PositionObjectFirst"

-- Comment the Position Object

pf.SetComments ev1_a2 "The operator defines the destination point inside the target volume"


-- Create a Script Operator

ev1_a3 = Script_Operator()

-- Set the script operator’s script code as string.

-- The code enables Position and Vector channels,

-- the writes the particle position in the Vector channel

-- for all new particles.

ev1_a3.proceed_script = "on ChannelsUsed pCont do


  pCont.usePosition = true

  pCont.useVector = true


on Init pCont do



on Proceed pCont do


 count = pCont.NumParticles()

 for i in 1 to count do


  pCont.particleIndex = i

  if (pCont.particleNew) then

  ( pCont.particleVector = pCont.particlePosition)



on Release pCont do




-- Comment the action:

pf.SetComments ev1_a3 "The script is used to dump particle position to script vector channel"


-- Clone the Position_Object action from Event 1

-- The result of the cloning will be stored in the

-- by-reference variable dc.

maxOps.cloneNodes ev1_a2 newNodes:&dc

-- Get the clone (first element of array)

ev1_a4 = dc[1]

-- Set the name of the action

ev1_a4.name = "PositionObjectSecond"

-- Set the Cylinder as the Emitter

ev1_a4.Emitter_Objects = #(cyl)


-- Comment the action:

pf.SetComments ev1_a4 "The operator defines the initial position of a particle inside a start volume. The destination position is overwritten but the real value is kept in Script Vector channel"


-- Create some more actions needed to control the particle system

ev1_a5 = Speed Direction:3

ev1_a6 = Rotation()

ev1_a7 = ShapeStandard Shape:1

ev1_a8 = DisplayParticles Type:6 Color:(color 255 0 0)


-- Create a new empty event, then append all already created

-- actions to it:

ev1 = Event()

ev1.AppendAction ev1_a1

ev1.AppendAction ev1_a2

ev1.AppendAction ev1_a3

ev1.AppendAction ev1_a4

ev1.AppendAction ev1_a5

ev1.AppendAction ev1_a6

ev1.AppendAction ev1_a7

ev1.AppendAction ev1_a8

-- Disable editing, enable Auto-Event-Encapsulation



-- Append the event as the Initial Action List to the PF_Source.

-- This will connect the Event to the PF_Source.

pf.appendInitialActionList ev1

-- Position the Event inside the Particle View

ev1.SetPViewLocation x (y+100)



-- Action List - Inserting Example --



--Begin Editing again



ev1_a9 = Spin SpinRate:200 Variation:55 --Create a Spin action

ev1_a10 = Force Influence:111 --Create a Force

--Set the Vortex as Space Warp in the Force

ev1_a10.Force_Space_Warps = #(vor)


--Create and setup a Find_Target action:

ev1_a11 = Find_Target()

ev1_a11.name = "FindTarget"

ev1_a11.Cruise_Speed_Variation = 1000


ev1_a11.Aim_Point_Type = 2

ev1_a11.Icon_Size = 0


-- Comment the action:

pf.SetComments ev1_a11 "The destination point is defined by script vector. The script vector value was defined by the Script Operator 01 from the Position Object 01"


-- Insert the new actions into the existing Event

ev1.InsertAction ev1_a9 8

ev1.InsertAction ev1_a10 9

ev1.InsertAction ev1_a11 10



-- Create a Second Event and its actions:


ev2_a1 = Speed Speed:0

ev2 = Event()

ev2_a2 = DisplayParticles Type:6 Color:(color 0 255 0)

ev2.AppendAction ev2_a1

ev2.AppendAction ev2_a2



--Connect the second Event to the Find_Target

ev1_a11.setNextActionList ev2 ev1_a11

--Reposition the even

ev2.SetPViewLocation x (y+400)



-- Make copy of PF_Source and exchange Emitter objects

-- for Position_Object operators:


-- Clone the PF_Source and the two Emitters,

-- store the clones in a by-reference variable

maxOps.CloneNodes #(pf, ev1, ev2) newNodes:&dc


-- Get the PF_Source and Emitter clones

pfc = dc[1]

ev1c = dc[2]

ev2c = dc[3]


-- Get the current position of the Particle View...


pfc.GetPViewLocation &x &y

-- Reposition the two Events

ev1c.SetPViewLocation x (y+100)

ev2c.SetPViewLocation x (y+400)


-- Copy the emitter objects from the original Position_Objects

if $PositionObjectFirst01 != undefined then (

 $PositionObjectFirst01.Emitter_Objects = ev1_a4.Emitter_Objects


if $PositionObjectSecond01 != undefined then (

 $PositionObjectSecond01.Emitter_Objects = ev1_a2.Emitter_Objects



-- Bind the Find_Target Test output to the clone of the Second Event

if $FindTarget01 != undefined then (

 $FindTarget01.setNextActionList ev2c $FindTarget01


-- Switch to Modify Tab

max modify mode

-- Open Particle View to see what happened...



See also

particleFlow Global Interface

Particle Flow Sample Scripts

Particle Flow Classes