Bubble Generator Script

Hey, i am currently starting too look at scripting and am starting off by trying to make a random bubble generator script.

The general idea is it creates bubbles of random size within a given constraint and then has them “float” upwards in a general random vector, but each step has a certain amount of random variation.

a few questions though, how do you “animate” the objects with script like every step is moving the object, and saving its new location in frame 2 then 3 then 4 and then say at frame 5 it creates a new bubble but both then continue to move upwards? is this possible

it wont let me use this code right after i append the mesh to the object obj it tells me there Blender Object has no attribute SetLocation but ive used it before.

obj[i].SetLocation(loc[0],loc[1],loc[2])

also, will this kind of script work with fluid sim?

here is what i have so far

import Blender
from Blender import *

import random
from random import Random

scn = Scene.GetCurrent()
start = Blender.Object.Get('Start')
loc = start.loc

num = 10

i = 0

bub = []
obj = []

for i in range(0,num,1):
    r = random.random()*2 + .5
    lx = random.random()
    ly = random.random()
    bub.append(Mesh.Primitives.UVsphere(8,8,r))
    obj.append(scn.objects.new(bub[i]))
    Blender.Redraw()

You can either make each bubble a separate object and then animate with ipos or you could make them all one object and then use script links. Given the two choices, I’d go with Ipos if you can since they offer more control/playback options.

it wont let me use this code right after i append the mesh to the object obj it tells me there Blender Object has no attribute SetLocation but ive used it before.

obj[i].SetLocation(loc[0],loc[1],loc[2])

Python is case-sensitive. Its setLocation not SetLocation.

also, will this kind of script work with fluid sim?

If they are ipo’d and have the proper settings (as obstacles), then it should (with other proper fluid settings).

Blender has several random functions built in, by the way, like Noise.random() and Mathutils.Rand() (I think there is one in BPyMathutils as well). Using these would keep people from potentially having to have a full python install to use the script if you ever feel like distributing it.

thanks a lot, each one is in fact a separate object in a list so i will look into ipose, and as for the random variables, if this script works i may go back and fix them.

thanks for the help

does pose have to be used with bones? or can it be used directly with mesh objects?

Actually, if you make the bubbles a softbody with a negative gravity, they will float upward (SVN). For the next few weeks just make them float downward,. then you can have their movement influenced by vortex forces and wind currents just like real. When 2.46 is release you can just change your gravity to negative and all else stays the same. In fact, if you just give them a 0 gravity and put a vortex above them it should suck them up nicely.

Not sure what you mean by this. Can you elaborate?

The basic way to animate would be to just iterate their movement every frame and insert ipo keys at the proper frames. Each bubble would be a separate object (they could have the same mesh, you just need to apply transforms to the objects). You wouldn’t use bones or poses (you could, but its much much messier).

thanks for the advice, but i think im still gonna look into the script. I dont wanna mess with the gravity or vortexes with fluid sim

as for the movement up im still not sure where to look for the code to make them move

I can set the location, but i dont know how to save it as a keyframe

I wrote an Ipo template (which is in SVN now) here:

http://blenderartists.org/forum/showthread.php?t=122768

Perhaps you could adapt it?

Thanks a lot for the help I’ve gotten a lot done! I struggled a bit with the python language cause i really had never looked at it before Friday but it turned out pretty well as of now.

so far it creates and animates the bubbles perfectly but i have to work out how to make all the settings correct. for fluid simulation and materials

i want to go back and make a gui with changeable variables because thats how ive set it up. I have to learn GUI first though

i have 2 videos (avi and quicktime):
1)View My Video
2)View My Video

here is the code so far, tell me what u think

#Theo Dowling
#Bubbles Script

#import Blender * and bpy, BPyMessages
import Blender
from Blender import *
import bpy, BPyMessages

#import random.Random()
import random
from random import Random

#get current sceen adnd get an object with name'Start' and get its location
scn = Scene.GetCurrent()
start = Blender.Object.Get('Start')
loc = start.loc

#set animation values and smoothnes of bubbles
num = 10
steps = 5
frame = 1
smooth = 8

#create all lists needed to keep track of each bubble
bub = []
obj = []
lx = []
ly = []
ipo = []
x = []
y = []
z = []

#animation
for i in range(0,num,1):

    #radius of bubbles as 0.5 to 2.5 float
    r = random.random()*2 + .5

    #choose + or - randomly
    getNeg = random.randint(0,1)
    neg = 1
            
    if (getNeg == 1):        
        neg = -1

        #set vector for each bubble in x direction
    lx.append(random.random()*.15*neg)

    #choose + or - randomly
    getNeg = random.randint(0,1)
    neg = 1
            
    if (getNeg == 1):        
        neg = -1

    #set vector for each bubble in y direction
    ly.append(random.random()*.15*neg)

    #create creates each bubble mesh
    bub.append(Mesh.Primitives.UVsphere(smooth,smooth,r))

    #assigns each mesh to a new object
    obj.append(scn.objects.new(bub[i]))
    obj[i].setLocation(loc[0],loc[1],loc[2])

    #creates a new ipo object for each bubble object
    ipo.append(bpy.data.ipos.new(str(i),'Object'))
    x.append(ipo[i].addCurve('LocX'))
    y.append(ipo[i].addCurve('LocY'))
    z.append(ipo[i].addCurve('LocZ'))

    #assigns the coordinates for the start frame
    x[i].append((frame, loc[0]))
    y[i].append((frame, loc[1]))
    z[i].append((frame, loc[2]))

    #animate ipo curves steps number of frames before creating a new bubble
    for j in range(0,steps,1):

        #increases the current frame
        frame += 1

        #updates the curve for each object
        for k in range(0,i+1,1):

            #choose + or - randomly
            getNeg = random.randint(0,1)
            neg = 1
            
            if (getNeg == 1):
                
                neg = -1

            #sets the random variation  in the x direction
            varrX = random.random()*.05*neg


            #choose + or - randomly
            getNeg = random.randint(0,1)
            neg = 1
            
            if (getNeg == 1):
                
                neg = -1

            #sets the random variation  in the y direction
            varrY = random.random()*.05*neg


            #gets the position of the object in the previous frame
            xLoc = x[k].evaluate(frame-1)
            yLoc = y[k].evaluate(frame-1)
            zLoc = z[k].evaluate(frame-1)

            #sets the new position in the current frame using
            #x vecter position and x varriation
            #y vector postiion and y varriation
            #z increments .25 blender units
            x[k].append((frame, xLoc+lx[k]+varrX))
            y[k].append((frame, yLoc+ly[k]+varrY))
            z[k].append((frame, zLoc+.25))

#assigns each ipo curve to each bubble
for i in range(0,num,1):

    #assigns the ipo to an object
    obj[i].setIpo(ipo[i])

#Redraws Blender
Blender.Redraw()

That looks pretty good, both the videos and the code (good job with comments, I need to be better in my code about writing them).

aight well i figure out most of the GUI, but ime having some issues one section

I am using the Draw.Slider() method to create number sliders but for some reason it wont let me adjust them (every time i move it it goes back to the initial value)

here is the code can anyone tell me why this is happening? the Draw.Slider is underlined in bold

#draw text, buttons, sliders, and number incrementers
def draw_gui():
    
    #make global variables
    global num, steps, frame, smooth, minS, maxS, varr
    
    #draw text
    BGL.glRasterPos2i(x, line[10])
    Draw.Text("choose the # of frames before a new bubble and the start frame")
    BGL.glRasterPos2i(x, line[8])
    Draw.Text("choose the # of bubbles to be made")
    BGL.glRasterPos2i(x, line[6])
    Draw.Text("choose the # of segments and rigns for each bubble")
    BGL.glRasterPos2i(x, line[4])
    Draw.Text("choose the min and max size of the bubbles")
    BGL.glRasterPos2i(x, line[2])
    Draw.Text("choose the ammount of variation of the bubbles path")
    
    #draw buttons
    Draw.PushButton("OK", OK, x, line[0], 60, 25, "Create")
    Draw.PushButton("CANCEL", CANCEL, 80, line[0], 60, 25, "Cancel")
    
    <i><b>#draw sliders
    minS = Draw.Slider("Min", MIN, 5, line[3], 150, 25, 1.00, .10, 10.00, 1, "Minimum bubble size")
    maxS = Draw.Slider("Max", MAX, 160, line[3], 150, 25, 2.00, .10, 10.00, 1, "Maximum bubble size")
    varr = Draw.Slider("Varr", VARR, 5, line[1], 310, 25, .1500, .0001, 1.0000, 1, "Amount of variation of bubbles movement")</b></i>
    
    #draw number incrementers
    num = Draw.Number("Num", NUM, 5, line[7], 210, 25, 10, 1, 1000, "Total number of bubbles created")
    steps = Draw.Number("Steps", STEPS, 5, line[9], 100, 25, 5, 1, 100, "Number of frames between each bubble")
    frame = Draw.Number("Frame", FRAME, 110, line[9], 100, 25, 1, 1, 100, "The inital frame of the animation")
    smooth = Draw.Number("Smooth", SMOOTH, 5, line[5], 210, 25, 8, 3, 50, "Number of rings and segments per bubble")


#get keyboard events
def event (event, val):
    if event == Draw.ESCKEY or event == Draw.QKEY:
        Draw.Exit()

#get button events
def button_event(evt):    
    if evt == OK:
        Bubble()
        Draw.Exit()
    if evt == CANCEL:
        Draw.Exit()


#call methods
Draw.Register(draw_gui, event, button_event)

everything else works
here is the entire code so far

#Theo Dowling
#Bubbles Script

#import Blender * and bpy, BPyMessages
import Blender
from Blender import *
import bpy, BPyMessages

#import random.Random()
import random
from random import Random

#initialize global variables
num = Draw.Create(10)
steps = Draw.Create(5)
frame = Draw.Create(1)
smooth = Draw.Create(8)
minS = Draw.Create(1.00)
maxS = Draw.Create(2.00)
varr = Draw.Create(.1500)

#create bubbles
def Bubble():
    
    #sets frame
    currFrame = frame.val
    
    #get current sceen adnd get an object with name'Start' and get its location
    scn = Scene.GetCurrent()
    start = Blender.Object.Get('Start')
    loc = start.loc
    
    #set animation values and smoothnes of bubbles
    
    
    #create all lists needed to keep track of each bubble
    bub = []
    obj = []
    lx = []
    ly = []
    ipo = []
    x = []
    y = []
    z = []
    
    #animation
    for i in range(0,num.val,1):
    
        #radius of bubbles
        r = random.random()*(maxS.val-minS.val) + minS.val
    
        #choose + or - randomly
        getNeg = random.randint(0,1)
        neg = 1
                
        if (getNeg == 1):        
            neg = -1
    
            #set vector for each bubble in x direction
        lx.append(random.random()*varr.val*neg)
    
        #choose + or - randomly
        getNeg = random.randint(0,1)
        neg = 1
                
        if (getNeg == 1):        
            neg = -1
    
        #set vector for each bubble in y direction
        ly.append(random.random()*varr.val*neg)
    
        #create creates each bubble mesh
        bub.append(Mesh.Primitives.UVsphere(smooth.val,smooth.val,r))
    
        #assigns each mesh to a new object
        obj.append(scn.objects.new(bub[i]))
        obj[i].setLocation(loc[0],loc[1],loc[2])
    
        #creates a new ipo object for each bubble object
        ipo.append(bpy.data.ipos.new(str(i),'Object'))
        x.append(ipo[i].addCurve('LocX'))
        y.append(ipo[i].addCurve('LocY'))
        z.append(ipo[i].addCurve('LocZ'))
    
        #assigns the coordinates for the start frame
        x[i].append((currFrame, loc[0]))
        y[i].append((currFrame, loc[1]))
        z[i].append((currFrame, loc[2]))
    
        #animate ipo curves steps number of frames before creating a new bubble
        for j in range(0,steps.val,1):
    
            #increases the current frame
            currFrame += 1
    
            #updates the curve for each object
            for k in range(0,i+1,1):
    
                #choose + or - randomly
                getNeg = random.randint(0,1)
                neg = 1
                
                if (getNeg == 1):
                    neg = -1
    
                #sets the random variation  in the x direction
                varrX = random.random()*(varr.val/4)*neg
    
    
                #choose + or - randomly
                getNeg = random.randint(0,1)
                neg = 1
                
                if (getNeg == 1):
                    neg = -1
    
                #sets the random variation  in the y direction
                varrY = random.random()*(varr.val/4)*neg
    
    
                #gets the position of the object in the previous frame
                xLoc = x[k].evaluate(currFrame-1)
                yLoc = y[k].evaluate(currFrame-1)
                zLoc = z[k].evaluate(currFrame-1)
    
                #sets the new position in the current frame using
                #x vecter position and x varriation
                #y vector postiion and y varriation
                #z increments .25 blender units
                x[k].append((currFrame, xLoc+lx[k]+varrX))
                y[k].append((currFrame, yLoc+ly[k]+varrY))
                z[k].append((currFrame, zLoc+.25))
    
    #assigns each ipo curve to each bubble
    for i in range(0,num.val,1):
    
        #assigns the ipo to an object
        obj[i].setIpo(ipo[i])
    
    #Redraws Blender
    Blender.Redraw()


#set up line numbers
line = [5,35,65,95,125,155,185,215,245,275,305]
x = 5

#create event numbers
OK = 1
CANCEL = 2
NUM = 3
STEPS = 4
FRAME = 5
SMOOTH = 6
MIN = 7
MAX = 8
VARR = 9


#draw text, buttons, sliders, and number incrementers
def draw_gui():
    
    #make global variables
    global num, steps, frame, smooth, minS, maxS, varr
    
    #draw text
    BGL.glRasterPos2i(x, line[10])
    Draw.Text("choose the # of frames before a new bubble and the start frame")
    BGL.glRasterPos2i(x, line[8])
    Draw.Text("choose the # of bubbles to be made")
    BGL.glRasterPos2i(x, line[6])
    Draw.Text("choose the # of segments and rigns for each bubble")
    BGL.glRasterPos2i(x, line[4])
    Draw.Text("choose the min and max size of the bubbles")
    BGL.glRasterPos2i(x, line[2])
    Draw.Text("choose the ammount of variation of the bubbles path")
    
    #draw buttons
    Draw.PushButton("OK", OK, x, line[0], 60, 25, "Create")
    Draw.PushButton("CANCEL", CANCEL, 80, line[0], 60, 25, "Cancel")
    
    #draw sliders
    minS = Draw.Slider("Min", MIN, 5, line[3], 150, 25, 1.00, .10, 10.00, 1, "Minimum bubble size")
    maxS = Draw.Slider("Max", MAX, 160, line[3], 150, 25, 2.00, .10, 10.00, 1, "Maximum bubble size")
    varr = Draw.Slider("Varr", VARR, 5, line[1], 310, 25, .1500, .0001, 1.0000, 1, "Amount of variation of bubbles movement")
    
    #draw number incrementers
    num = Draw.Number("Num", NUM, 5, line[7], 210, 25, 10, 1, 1000, "Total number of bubbles created")
    steps = Draw.Number("Steps", STEPS, 5, line[9], 100, 25, 5, 1, 100, "Number of frames between each bubble")
    frame = Draw.Number("Frame", FRAME, 110, line[9], 100, 25, 1, 1, 100, "The inital frame of the animation")
    smooth = Draw.Number("Smooth", SMOOTH, 5, line[5], 210, 25, 8, 3, 50, "Number of rings and segments per bubble")


#get keyboard events
def event (event, val):
    if event == Draw.ESCKEY or event == Draw.QKEY:
        Draw.Exit()

#get button events
def button_event(evt):    
    if evt == OK:
        Bubble()
        Draw.Exit()
    if evt == CANCEL:
        Draw.Exit()


#call methods
Draw.Register(draw_gui, event, button_event)

is it possible to make little air bubles in an aquarium fill with water with this script?

Salutations

I assume this happens when you move outside the script window correct (or you trigger a redraw)?

This is because at that point its returning to the original value you create the button with. What you need to is initially declare all of your buttons with:

but = Draw.Create(value) #your initial value

Then later you can do the following:

but = Slider(All your stuff, initial = but.val, continue your call)

That should preserve the value.

well i have done that, its done globally outside the draw_gui() method. If you look at the whole code its in the first few lines for all variables

does it matter that i then declare global … inside the draw_gui() method?

or maby that i use numerical values instead of say minS.val?

to the best of my knowledge there aren’t any Redraw calls until the end of the Bubble() method so no it shouldn’t be calling a Redraw and it happens as soon as the slider is let go even if i don’t go outside of the text window. I will recheck this because it makes sense

as for weather this will work say in an aquarium, yes by the time its done thats generally what i am trying to do. I just have to set all of the materials and fluid simulation properties once i know how.

Oops, missed those lines. All you need to do is set the initial value of the button you create (in this case a slider) to but.val, for instance:


minS = Draw.Slider("Min", MIN, 5, line[3], 150, 25, minS.val, .10, 10.00, 1, "Minimum bubble size")

yup, that did it

thanks so much for all the help. Its almost done. Now i just have to figure out how to set fluid sim properties and i can finish up

I’ll head you off at the pass and tell you that fluid sim settings have not been exposed to the Python API yet (not sure why, though, especially considering how long the fluid sim has been around).

A viable workaround, however, is to have a “dummy” object with the proper fluid settings set up manually and then duplicate that object, since fluid settings seem to persist with object duplication. You could then have your script duplicate them to generate bubbles. While putting a little more burden on the user, it also offers more control, since they could theoretically control the shape of the bubbles.

hm that does indeed provide an interesting complication

that sounds like a great idea though, il look into that

also, i feel like it may be simpler to instead of using a preexisting object and mesh, retrieve a specific object, then duplicate it into the list of objects i already have. Then the mesh could be added to that object allowing for all of the fluid simulation properties to remain, but at the same time not having to modify a lot of code

ok, so this is proving to be a bit of a problem. After manualy setting fluid sim settings it worked fairly well (still needs some tweaking) but i cant get it to work via script

so, say i create an object called ‘obs’ and give it the proper fluid simulation properties (meaning it has some sort of mesh, even if it is 1 vert)

now, how to i take that object, create a list of that object, add a new mesh to each of those objects in the list, and then be able to set its location and animate it

if someone could tell me just how to create a new object the same as obs and then add the new mesh to it, im sure i could figure it out for a list.

Unselect all the objects in the scene. Then set the obs.selected = 1.

Then use Object.Duplicate() and get the newly duplicated object. Then call the link method on the new object with a mesh data block as an argument. Note that obs should be a Mesh type object for the linking to a mesh object to work. Otherwise this won’t work (for that reason, there may be others it won’t work):


import Blender.Object #needed for this code, but your code already imports it

scn.objects.selected = []

fluidBaseOb = bpy.data.objects['obs']
fluidBaseOb.sel = 1

Object.Duplicate()
newFluidOb = scn.objects.active
newFluidOb.link(mymeshdata)

ok thanks yeah, i couldnt figure out teh Duplicate() method

i was trying to use it like

obs.Duplicate() but that did it.

Made a few adjustments so you can set the start location with GUI instead of finding an object, and did a few tests with fluid simulation. So for its working out ok but it needs refining the watter seems to stay on top of the bubble in a weird way but it may be due to low fluid resolution. here is a quick clip (sry its kinda dark)

View My Video

heres the code, just a bit more tests when i have time to do a lot of baking and animating. My computer normally works pretty fast but the fluid simulation can get relay processor intensive. It took half and hour to bake this video and another hour to render it in yafray.

#Theo Dowling
#Bubbles Script

#import Blender * and bpy, BPyMessages
import Blender
from Blender import *
import bpy, BPyMessages

#import random.Random()
import random
from random import Random

#initialize global variables
num = Draw.Create(10)
steps = Draw.Create(5)
frame = Draw.Create(1)
smooth = Draw.Create(8)
minS = Draw.Create(1.00)
maxS = Draw.Create(2.00)
varr = Draw.Create(.1500)
locX = Draw.Create(0.0)
locY = Draw.Create(0.0)
locZ = Draw.Create(0.0)

#create bubbles
def Bubble():
    
    #sets frame
    currFrame = frame.val
    
    #get current scene
    scn = Scene.GetCurrent()
    
    #create all lists needed to keep track of each bubble
    bub = []
    obj = []
    lx = []
    ly = []
    ipo = []
    x = []
    y = []
    z = []
    
    #animation
    for i in range(0,num.val,1):
        
        #radius of bubbles
        r = random.random()*(maxS.val-minS.val) + minS.val
    
        #choose + or - randomly
        getNeg = random.randint(0,1)
        neg = 1
                
        if (getNeg == 1):        
            neg = -1
    
            #set vector for each bubble in x direction
        lx.append(random.random()*varr.val*neg)
    
        #choose + or - randomly
        getNeg = random.randint(0,1)
        neg = 1
        
        if (getNeg == 1):        
            neg = -1
    
        #set vector for each bubble in y direction
        ly.append(random.random()*varr.val*neg)
    
        #create creates each bubble mesh
        bub.append(Mesh.Primitives.UVsphere(smooth.val,smooth.val,r))
        
        #gets selected
        scn.objects.selected = []
        
        #gets dummy object with dluid simulation settings
        obs = bpy.data.objects['obs']
        obs.sel = 1
        
        #duplicates dummy object
        Object.Duplicate()
    
        #sets new objects equal to duplicated dummy and assigns each mesh to a new object
        obj.append(scn.objects.active)
        obj[i].link(bub[i])
        obj[i].setLocation(locX.val,locY.val,locZ.val)
    
        #creates a new ipo object for each bubble object
        ipo.append(bpy.data.ipos.new(str(i),'Object'))
        x.append(ipo[i].addCurve('LocX'))
        y.append(ipo[i].addCurve('LocY'))
        z.append(ipo[i].addCurve('LocZ'))
    
        #assigns the coordinates for the start frame
        x[i].append((currFrame, locX.val))
        y[i].append((currFrame, locY.val))
        z[i].append((currFrame, locZ.val))
    
        #animate ipo curves steps number of frames before creating a new bubble
        for j in range(0,steps.val,1):
    
            #increases the current frame
            currFrame += 1
    
            #updates the curve for each object
            for k in range(0,i+1,1):
    
                #choose + or - randomly
                getNeg = random.randint(0,1)
                neg = 1
                
                if (getNeg == 1):
                    neg = -1
    
                #sets the random variation  in the x direction
                varrX = random.random()*(varr.val/4)*neg
    
    
                #choose + or - randomly
                getNeg = random.randint(0,1)
                neg = 1
                
                if (getNeg == 1):
                    neg = -1
    
                #sets the random variation  in the y direction
                varrY = random.random()*(varr.val/4)*neg
    
    
                #gets the position of the object in the previous frame
                xLoc = x[k].evaluate(currFrame-1)
                yLoc = y[k].evaluate(currFrame-1)
                zLoc = z[k].evaluate(currFrame-1)
    
                #sets the new position in the current frame using
                #x vecter position and x varriation
                #y vector postiion and y varriation
                #z increments .25 blender units
                x[k].append((currFrame, xLoc+lx[k]+varrX))
                y[k].append((currFrame, yLoc+ly[k]+varrY))
                z[k].append((currFrame, zLoc+.25))
    
    #assigns each ipo curve to each bubble
    for i in range(0,num.val,1):
    
        #assigns the ipo to an object
        obj[i].setIpo(ipo[i])
    
    #Redraws Blender
    Blender.Redraw()


#set up line numbers
line = [5,35,65,95,125,155,185,215,245,275,305,335,365]
x = 5

#create event numbers
OK = 1
CANCEL = 2
NUM = 3
STEPS = 4
FRAME = 5
SMOOTH = 6
MIN = 7
MAX = 8
VARR = 9
LOC0 = 10
LOC1 = 11
LOC2 = 12


#draw text, buttons, sliders, and number incrementers
def draw_gui():
    
    #make global variables
    global num, steps, frame, smooth, minS, maxS, varr, locX, locY, locZ
    
    #draw text
    BGL.glRasterPos2i(x,line[12])
    Draw.Text("choose the starting location for the bubbles")
    BGL.glRasterPos2i(x, line[10])
    Draw.Text("choose the # of frames before a new bubble and the start frame")
    BGL.glRasterPos2i(x, line[8])
    Draw.Text("choose the # of bubbles to be made")
    BGL.glRasterPos2i(x, line[6])
    Draw.Text("choose the # of segments and rigns for each bubble")
    BGL.glRasterPos2i(x, line[4])
    Draw.Text("choose the min and max size of the bubbles")
    BGL.glRasterPos2i(x, line[2])
    Draw.Text("choose the ammount of variation of the bubbles path")
    
    #draw buttons
    Draw.PushButton("OK", OK, x, line[0], 60, 25, "Create")
    Draw.PushButton("CANCEL", CANCEL, 80, line[0], 60, 25, "Cancel")
    
    #draw sliders
    minS = Draw.Slider("Min", MIN, 5, line[3], 150, 25, minS.val, .10, 10.00, 1, "Minimum bubble size")
    maxS = Draw.Slider("Max", MAX, 160, line[3], 150, 25, maxS.val, .10, 10.00, 1, "Maximum bubble size")
    varr = Draw.Slider("Varr", VARR, 5, line[1], 310, 25, varr.val, .0001, 1.0000, 1, "Amount of variation of bubbles movement")
    
    #draw number incrementers
    locX = Draw.Number("X", LOC0, 5, line[11], 65, 25, locX.val, -10000.0, 10000.0, "Location on the X axis")
    locY = Draw.Number("Y", LOC1, 75, line[11], 65, 25, locY.val, -10000.0, 10000.0, "Location on the Y axis")
    locZ = Draw.Number("Z", LOC2, 145, line[11], 65, 25, locZ.val, -10000.0, 10000.0, "Location on the Z axis")
    num = Draw.Number("Num", NUM, 5, line[7], 210, 25, num.val, 1, 1000, "Total number of bubbles created")
    steps = Draw.Number("Steps", STEPS, 5, line[9], 100, 25, steps.val, 1, 100, "Number of frames between each bubble")
    frame = Draw.Number("Frame", FRAME, 110, line[9], 100, 25, frame.val, 1, 100, "The inital frame of the animation")
    smooth = Draw.Number("Smooth", SMOOTH, 5, line[5], 210, 25, smooth.val, 3, 50, "Number of rings and segments per bubble")


#get keyboard events
def event (event, val):
    if event == Draw.ESCKEY or event == Draw.QKEY:
        Draw.Exit()

#get button events
def button_event(evt):    
    if evt == OK:
        Bubble()
        Draw.Exit()
    if evt == CANCEL:
        Draw.Exit()


#call methods
Draw.Register(draw_gui, event, button_event)