Blender 2.56 Python Script for an animation system 2D gravity/accretion simulation. I was intended to be sort of an artistic tool but the physics are correct. I still have some UI work to do but it’s on the back burner for right now. Anyway it works if you feel like playing with it.
##################################################
#
# Simple Orbital Mechanics - v.0.0.01a - 01.30.11
# GPL, Public Licence, Open-Source, Free, etc...
# 2D Gravity/Accretion Simuatior
#
# Thanks to Thanassis Tsiodras for his
#"Naive simulator of gravity, in less than 200 Python lines"
# http://users.softlab.ntua.gr/~ttsiod/gravity.html
# it got me on the right track
#
# >Physics Property Menu >Simple Orbital Mechanics
# -adjust parameters
# >createGobs, can create multiple times
# and move if desired
# >createSuns, or name other objects with prefix 'sun'
# and move if desired
#
##############################################################
#
# TODO/WISHLIST:
# - other objects
# arbitrary objects
# - impliment negative mass? repulsive matter?
# other implimentations of gravity?
# pushes at a distance,
# - variable gravity?
# ! - make 2dplane arbitrary somehow
# maybe give each object a xyz reconfig
# so you can reassing so you can have
# various systems interacting on diff
# plane 1st would just
# be to reassign axis on keyframe
# -make sure Z loc is not locked in any way
# so i can play with stacking them
# vertically, setup a sim, then
# start camera top and dolly side to reveal dist...
# - materials (PlanetTex patch?)
# - sim analysis
# run thru varions configs
# keep those with best 'stability'
# to make visually interesting sims
# ie. most mass stays inside bounds
# or most non merged mass in bounds
# and most movement in bounds?
# - other movement formulas?
# maybe impliment fractal flames somehow though
# that's probably another project
# - drive other params such as colors with loc/vel/acc
# - option for dynamic rotation?
# - color picker
# vectors or other settings as color picker wheel?
# lock to a black and use as vector?
# -smaller regular partical emitter at ever merge
# -also, maybe make all objects, attractors?#
#
# KNOWN ISSUES
# - accumulation of data - .unlink,
# need to figure something else out
# !!! have flush but crashes blender...
# - cannot rotate vectortails directly in
# 3d view, only in 'n' panel. scale works though...
# - CONSTRAINTS effecting start frame position
# running sim should not change start frame
# THE frame 1 JUMP IS ACTUALLY BECAUSE OF CONSTRANT/SOMETHING
# or updating inital velocity
# - clear animation data -FIX-
# - sun' still getting location keyframed
# - metballs don't really appear...
####################################################
###???ACRETION MERGERGLOB OFFSET ISN'T RIGHT. STILL
# ALLOWS OFFSET WAY BEYOND RADIUS
###!!!3daxis interchange - just put a cust value for XYZ -> ZYX mappting
# then adjust just before set location
###???clear animation should also clear paths?
###!!!add gloobject count to panel
###???not making very good use of the index idea...
# probably get to that when I refactor for arbitary xyz
# global scn, GI
# GIsuns, GIglobs = [], []
# GI = [GIsuns, GIglobs]
# GI(index) will help with all kinds of stuff..
# also work in more build in fxns like vector ang - xy converions for tails and whatnot
###!!!also make time of partlife relative to framerun
###!!!ADD PROPULSION???? somehow add thrust/nav controls?
# to try out different nav techniques
###???metaballs, explode into other metaballs and add into GI
# maybe newly spawned objects are only effected by parent?
# new custom value = generation... (1st, 2nd, 3rd, etc)
# OR split metaELEMTS!
# eventuallty make so metaball impacts create
# new objects and those are then calced in gravity...
###!!!also - next progream...
# dedicated script to gravitize a selection of any
# objects based on bounding box...
# ... try to make this one reletivistic
# incding lorenz... try to help visualize
# reletivity on pc
# time dilation???
# reletivistic mass? all velocities based on % of maximum (essentially c)
# then incorporate E=mc2 (somehow so harder to accelerate the faster
# it's going...
# faster to use GI index on animate
# especuially if use keep 'merged' in index...
###!!!LATER... metaball element trails...
###???option to explode at clip? <-------------- ###!!!on create mesh path verify there is anim data ###!!!lockxy rotation on tails ###???figure out subdivision... # context thing in panel? ###!!! add event to starting velocity # make vecto suns toggle withevent... so you can change bac to random ###!!! maybe instead of merging with constraints, just # seup so each loop if its merged it sets keyframe to its parents # this could make axis-remapping easier in cases of merging # #################################################### ### NEXT NEXT NEXT NEXT NEXT NEXT NEXT NEXT NEXT #################################################### ###!!!----------->figure out dist to sun relative to earth size...
###!!!----------->radial glob field create option for kieper/oort 35-55au
###!!!Voyager...speed 3.5 au/yr - exit trajectory from sol
#then ui#
#then refactor for release 00000.2 whaever
#no core refactor, just loose ends, cleanup...
#then post!!!
#then sleep?
#need some kind of collision damping
##############################################################
#-maybe some issues with significant digits at some point
# i think python floats are 28 digits?
#-something about mass from radius...
"""sun = 1M = 1.98892e30 kg
mercury
3.3010e23/1.98892e30
venus
4.1380e24/1.98892e30
mars
6.4273e23/1.98892e30
jupiter
1.89852e27/1.98892e30
saturn
5.6846e26/1.98892e30
uranus
8.6819e25/1.98892e30
neptune
1.02431e26/1.98892e30"""
#figure out what a frame = in this setup
### got a lot of stuff working
# but... accretion offset is still wonky...
# and... tmass fcurve is CURVED
# need to set curves to CONSTANT for merged, tmass, etc...
###!!! its adding constrainy to emptys?
######################### DEFAULTS/CONFIG/SETTINGS #########################
import bpy
import sys
import random
import time
from math import pi, sqrt, sin, cos, asin, acos
"""
#derived from one mercury orbit-per-sec
1.2252211349000193/framerate = AU/frame
1 simsecond = 1 mercuryyear = 0.240 earthyear
365.25*24*60*60 = 31557600 sec/yr
0.240*31557600 = 7573824.07573824.0
1 simsecond = 7573824.07573824 realseconds
--->1 simframe = 0.240*31557600/framerate realseconds
365*24*60*60 = 31536000 sec/yr (earth)
c = 63188.25au/yr
c = 63188.25/31536000 au/sec
c = 0.0020036862633181127 au/sec
G = 6.67300e-11 m**3/kg**-1/s**2
F=G(m1*m2/r**2)
"""
### I THINK I HAVE SCALE/SIZE RIGHT
###NOW NEED SOMETHING FOR KG AND SECONDS
#figure out G for this rigwith m/s/kg from mybases
scn = bpy.context.scene
#-dimensions
FRAMERUN = 300 #ui length of simulation
#AU = 1.0 #ui 1BlenderUnit = 1AU
WIDTH = 150 #ui Blender units (should I add a scale option?)
HEIGHT = 150
CLIP = 1000 #ui stop/ignore objects too far out
STARTFRAME = 1 #ui start frame of simulation
#-globs/sunholes
PARTICLES = 5 #ui number globs to add
#FRAMERATE = scn.RenderSettings.fps
FRAMERATE = 24
TIMESCALE = 1.0 #based on framerate, au, and cno idea... 1y?
#--->1 simframe = 0.240*31557600/framerate realseconds
#EdMASS = 1.0 #ui??? Earth = 1unit: to be used for mass scaling and such
#SOLMASS = 5.9736e24
A = 1.0 #astronomical unit = 149.60e6 km = 149.60e9 m
M = 1.0 #solar mass = 1.98892e30 kg
T = 365.256363 #sidereal year
#D = 1.0 #mean solar day = 86400.0025 SI seconds @ epoch J1900
#gaussian constant = 0.01720209895 A**2/3 D*-1 M*-1/2
G = sqrt((2*pi/T)*(sqrt(A**2/M)))
#GM = GRAVITY * S #(GM product)
#GRAVITY = G #ui effect of gravity
#SOLDIAM = 1.0 ###!!!should be sol diam in AU?
#SOLDIAM = 8.517493549379003e-05 #Earth's diameter constant
# 1AU = 149598000 km
# EarthDiameter = 12742.0 km
# EarthDiameter = 12742/149598000 AU
#
DSIZE = 250 # Solar unit draw size of glob mesh
# no effect on physics
AXMAP = ['X','Y','Z']#default axismapping
SIZEVAR = 1.0 #ui variation in glob size in feild generation
#SsUNRADIUS = 109.0 #ui default sun radius (same as Sol)
SUNRANDLOC = True #ui default setting for random sun loc
#SUNsDSIZE = 1.0 #ui draw size of suns
#-physics
DAMP = 1.0 #ui temp use for vel and acc (1.0 = no damp)
MAXVEL = 20.0 #ui max velocity
MAXINTERAD = CLIP #ui max dist between 2 particles too calc force
DAMPVEL = 1.0 #na damp or add velocity (1.0 = 100%)
DAMPACC = 1.0 #na damp or add acceleration (less makes more spinny animations)
DAMPVELx = DAMPVEL #na in case someone wants asymetrical damping later
DAMPVELy = DAMPVEL
DAMPACCx = DAMPACC
DAMPACCy = DAMPACC
RANDVEL = True #ui generate random starting velocity
RANDVELRANGE = .125 #ui random range for staring velocity
VECMULT = 10000 #ui multiplier for vector tails should be just display
LOOPATCLIP = False #ui option to loop at clip dist
ACCRETE = True #ui
EXPLODE = True #ui
EXTHRESH = .25 #ui total impact velocity required to explode
METABALLS = False
#-internal
GPREFIX = 'glob' #fn prefix for globjects
MOBNAME = 'mglob' #fn name of globject meshdata
SPREFIX = 'sun' #fn name of sun objects
###!!! replace the prefix system with a 'glob' variable
print('----------GEAUX!!!----------')
################### playground ######################
#-dist, size, mass, based on Earth = 1
def createSolSystem():
###!!!OortCloud 2000-50,000 au
###!!!ProximaCentauri 268000 au
###!!!add Europa, Phobos, Demos, lots o' moons to add
###!!!saturns rings?
NOZERO = 0.00000000001
print('make a mass-distance-speed / scale accurate copy of sol')
solG2V = makeMeshCube('sun-SOLG2V', scn.DSIZE)
solG2V.name = 'sun-SOLG2V'
solG2V.location = [0.0, 0.0, 0.0]
solG2V.scale = [scn.SOLDIAM*109, scn.SOLDIAM*109, scn.SOLDIAM*109]
solG2V.tmass = scn.M
solG2V.modifiers.new('sunbevel', 'BEVEL')
solG2V.show_name = True
scn.objects.link(solG2V)
mercury = createMetaBall('glob-MERCURY', scn.DSIZE)
mercury.name = 'glob-MERCURY'
mercury.location = [-0.39, NOZERO, 0.0]
mercury.scale = [scn.SOLDIAM*0.3829, scn.SOLDIAM*0.3829, scn.SOLDIAM*0.3829]
mercury.tmass = scn.M*0.055
mercury.vel = [0.0, -0.24, 0.0]
mercury.show_name = True
mercury.merged = False
scn.objects.link(mercury)
venus = createMetaBall('glob-VENUS', scn.DSIZE)
venus.name = 'glob-VENUS'
venus.location = [NOZERO, 0.72, 0.0]
venus.scale = [scn.SOLDIAM*0.949, scn.SOLDIAM*0.949, scn.SOLDIAM*0.949]
venus.tmass = scn.M*0.82
venus.vel = [-0.62, 0.0, 0.0]
venus.show_name = True
venus.merged = False
scn.objects.link(venus)
earth = createMetaBall('glob-EARTH', scn.DSIZE)
earth.name = 'glob-EARTH'
earth.location = [1.0, NOZERO, 0.0]
earth.scale = [scn.SOLDIAM, scn.SOLDIAM, scn.SOLDIAM]
earth.tmass = scn.M
earth.vel = [0.0, 1.0, 0.0]###??? EARTH BASED VELOCITY? SURE WHY NOT
earth.show_name = True
earth.merged =False
scn.objects.link(earth) ###??? wrong though, it's orbital period, not velocity...
###
luna = createMetaBall('glob-LUNA', scn.DSIZE)
luna.name = 'glob-LUNA'
luna.location = [1.026, NOZERO, 0.0]
luna.scale = [scn.SOLDIAM*0.273, scn.SOLDIAM*0.273, scn.SOLDIAM*0.273]
luna.tmass = scn.M*0.012
luna.vel = [0.0, 1.0, 0.0]
luna.show_name = True
luna.merged = False
scn.objects.link(luna)
mars = createMetaBall('glob-MARS', scn.DSIZE)
mars.name = 'glob-MARS'
mars.location = [NOZERO, -1.52, 0.0]
mars.scale = [scn.SOLDIAM*0.532, scn.SOLDIAM*0.532, scn.SOLDIAM*0.532]
mars.tmass = scn.M*0.11
mars.vel = [1.88, 0.0, 0.0]
mars.show_name = True
mars.merged = False
scn.objects.link(mars)
jupiter = createMetaBall('glob-JUPITER', scn.DSIZE)
jupiter.name = 'glob-JUPITER'
jupiter.location = [-5.204267, NOZERO, 0.0]
jupiter.scale = [scn.SOLDIAM*11.209, scn.SOLDIAM*11.209, scn.SOLDIAM*11.209]
jupiter.tmass = scn.M*317.8
jupiter.vel = [0.0, -11.86, 0.0]
jupiter.show_name = True
jupiter.merged = False
scn.objects.link(jupiter)
saturn = createMetaBall('glob-SATURN', scn.DSIZE)
saturn.name = 'glob-SATURN'
saturn.location = [NOZERO, 9.582, 0.0]
saturn.scale = [scn.SOLDIAM*9.449, scn.SOLDIAM*9.449, scn.SOLDIAM*9.449]
saturn.tmass = scn.M*95.2
saturn.vel = [-29.46, 0.0, 0.0]
saturn.show_name = True
saturn.merged = False
scn.objects.link(saturn)
uranus = createMetaBall('glob-URANUS', scn.DSIZE)
uranus.name = 'glob-URANUS'
uranus.location = [19.22, NOZERO, 0.0]
uranus.scale = [scn.SOLDIAM*4.007, scn.SOLDIAM*4.007, scn.SOLDIAM*4.007]
uranus.tmass = scn.M*14.6
uranus.vel = [0.0, 84.01, 0.0]
uranus.show_name = True
uranus.merged = False
scn.objects.link(uranus)
neptune = createMetaBall('glob-NEPTUNE', scn.DSIZE)
neptune.name = 'glob-NEPTUNE'
neptune.location = [NOZERO, -30.06, 0.0]
neptune.scale = [scn.SOLDIAM*3.883, scn.SOLDIAM*3.883, scn.SOLDIAM*3.883]
neptune.tmass = scn.M*17.2
neptune.vel = [164.8, 0.0, 0.0]
neptune.show_name = True
neptune.merged = False
scn.objects.link(neptune)
pluto = createMetaBall('glob-PLUTO', scn.DSIZE)
pluto.name = 'glob-PLUTO'
pluto.location = [-29.74, NOZERO, 0.0]
pluto.scale = [scn.SOLDIAM*0.19, scn.SOLDIAM*0.19, scn.SOLDIAM*0.19]
pluto.tmass = scn.M*0.002
pluto.vel = [0.0, -248.09, 0.0]
pluto.merged =False
pluto.show_name = True
scn.objects.link(pluto)
sedna = createMetaBall('glob-SEDNA', scn.DSIZE)
sedna.name = 'glob-SEDNA'
sedna.location = [NOZERO, 960.0, 0.0]
sedna.scale = [scn.SOLDIAM*0.2197, scn.SOLDIAM*0.2197, scn.SOLDIAM*0.2197]
sedna.tmass = scn.M*0.0004185081023168609
sedna.vel = [-118090.0, 0.0, 0.0]
sedna.show_name = True
sedna.merged = False
scn.objects.link(sedna)
voyager = makeMeshCube('glob-VOYAGER', scn.DSIZE)
voyager.name = 'glob-VOYAGER1'
voyager.location = [-115.0, NOZERO, 0.0]
voyager.scale = [scn.SOLDIAM*1.5696123057604772e-06,
scn.SOLDIAM*1.5696123057604772e-06, scn.SOLDIAM*1.5696123057604772e-06]
voyager.tmass = scn.M*1.2086513994910943e-22
voyager.vel = [0.0, -10.0, 0.0]
scn.objects.link(voyager)
voyager.show_name = True
voyager.merged = False
def makeGlobField():
for i in range(scn.PARTICLES):
gx = random.uniform(-scn.WIDTH/2, scn.WIDTH/2)
gy = random.uniform(-scn.HEIGHT/2, scn.HEIGHT/2)
gz = 0.0 #2D sim for now
#gs = random.uniform(scn.SOLDIAM-(scn.SOLDIAM*(scn.SIZEVAR/2)),
# scn.SOLDIAM+(scn.SOLDIAM*(scn.SIZEVAR/2)))
#sun diameter = 1391000 kilometers
#au = 149598000 kilometers
#sun diameter = 1391000/149598000 AU
#sun diameter = 0.009298252650436503 AU
gs = 0.009298252650436503 #-make variable? this makes default sun size our sun
if METABALLS:
newob = createMetaBall('metaglobule', scn.DSIZE)
globname = GPREFIX + 'meta-' + str(i+1000)[1:4]
else:
newob = makeMeshCube(MOBNAME, scn.DSIZE)
globname = GPREFIX + '-' + str(i+1000)[1:4]
newob.name = globname
newob.location = [gx, gy, gz]
newob.scale = [gs, gs, gs]
#add custom properties
newob.merged = False
newob.bhole = False
#newob.tmass = scn.M *random.uniform(1, SIZEVAR)
newob.tmass = scn.M # should be a random mass var
newob.vel = [0.0, 0.0, 0.0]
#newob.density = scn.STDENSITY
if scn.RANDVEL:
gvx = random.uniform(-RANDVELRANGE/2, RANDVELRANGE/2)
gvy = random.uniform(-RANDVELRANGE/2, RANDVELRANGE/2)
gvz = 0.0
newob.vel = [gvx, gvy, gvz]
scn.objects.link(newob)
def createMetaBall(mname, msize):
msize = msize/2 #-radius from diameter
#-have to go into edit mode to refesh metaobj for some reason
mball = bpy.data.metaballs.new(mname)
for m in range(1):
mel = mball.elements.new()
#mel.type = 'BALL'
mel.co = [0.0, 0.0, 0.0]
mel.size_x = msize
mel.size_y = msize
mel.size_z = msize
#mel.stiffness = 1.0
#mel.use_negative = False #could be fun
oball = bpy.data.objects.new('metaglobule', mball)
oball.data = mball
oball.glob = True
return(oball)
def makeMeshCube(mname, msize):
msize = msize/2 #-radius from diameter
mmesh = bpy.data.meshes.new(mname)
mmesh.vertices.add(8)
mmesh.vertices[0].co = [-msize, -msize, -msize]
mmesh.vertices[1].co = [-msize, msize, -msize]
mmesh.vertices[2].co = [ msize, msize, -msize]
mmesh.vertices[3].co = [ msize, -msize, -msize]
mmesh.vertices[4].co = [-msize, -msize, msize]
mmesh.vertices[5].co = [-msize, msize, msize]
mmesh.vertices[6].co = [ msize, msize, msize]
mmesh.vertices[7].co = [ msize, -msize, msize]
mmesh.faces.add(6)
mmesh.faces[0].vertices_raw = [0,1,2,3]
mmesh.faces[1].vertices_raw = [0,4,5,1]
mmesh.faces[2].vertices_raw = [2,1,5,6]
mmesh.faces[3].vertices_raw = [3,2,6,7]
mmesh.faces[4].vertices_raw = [0,3,7,4]
mmesh.faces[5].vertices_raw = [5,4,7,6]
mmesh.update(calc_edges=True)
omesh = bpy.data.objects.new(mname, mmesh)
omesh.data = mmesh
omesh.glob = True
return(omesh)
def makeSunHole():
holemass = 10
ll = []
for m in scn.objects:
if m.name[0:len(SPREFIX)] == SPREFIX:
ll.append(m.name)
gx = random.uniform(-scn.WIDTH/2, scn.WIDTH/2)
gy = random.uniform(-scn.HEIGHT/2, scn.HEIGHT/2)
gz = 0
gs = 0.009298252650436503 #-sol diam in AU
newsun = makeMeshCube('sunmesh', scn.DSIZE)
newsun.name = SPREFIX + '-' +str(len(ll)+1000)[1:4]
if scn.SUNRANDLOC:
newsun.location = [gx, gy, gz]
newsun.scale = [gs, gs, gs]
newsun.modifiers.new('sunbevel', 'BEVEL')
newsun.merged = False
newsun.bhole = True
newsun.tmass = scn.M * holemass
scn.objects.link(newsun)
def clearAnimation():
for o in scn.objects:
for f in range(scn.FRAMERUN):
scn.frame_current = f+1
if o.name[0:len(GPREFIX)] == GPREFIX
or o.name[0:len(SPREFIX)] == SPREFIX:
o.keyframe_delete('location')
o.keyframe_delete('vel')
o.keyframe_delete('tmass')
o.keyframe_delete('merged')
for c in o.constraints:
c.keyframe_delete('influence')
o.constraints.remove(c)
# QQQ remove constraints influence frames too?
def createMeshPath():
###!!! set this up to use ob.glob but not ob.bhole
#-this is UGLY, need to find how to get fcurve data easier
for ob in scn.objects:
if ob.name[0:len(GPREFIX)] == GPREFIX: #
#and len(GPREFIX)+4 == len(ob.name): #-hope avoid making path for path
locX, locY, locZ, frame = [], [], [], []
for f in range(scn.STARTFRAME, scn.FRAMERUN+1):
oanim = ob.animation_data
ocurves = oanim.action.fcurves
addframe = 0
stopvert = 5
#-some hacky bullshit to make merged blobs paths right
for ocurve in ocurves:
#-only add to array if object hasn's been merged. !!! BROKE!
if ocurve.data_path == 'merged' and ocurve.evaluate(f) == False:
addframe = 1
stopvert = 0
for ocurve in ocurves:
if addframe == 1:
if ocurve.data_path == 'location'
and ocurve.array_index == 0:
locX.append(ocurve.evaluate(f))
if ocurve.data_path == 'location'
and ocurve.array_index == 1:
locY.append(ocurve.evaluate(f))
#-dont create motion paths under a % of FRAMERUM
PATHTHRESH = 20 #%<-----make a ui variable (or setup file)
if len(locX)/scn.FRAMERUN < PATHTHRESH/scn.FRAMERUN: print(len(locX)/scn.FRAMERUN, PATHTHRESH/scn.FRAMERUN) continue mpath = bpy.data.meshes.new('meshpath') mpath.use_auto_smooth = True for p in range(len(locX)-1): if p == 0 or p == len(locX)-1: mpath.vertices.add(1) mpath.vertices[len(mpath.vertices)-1].co = [locX[p], locY[p], 0.0] if p > 0 and p < len(locX)-1-stopvert:
x2, y2 = locX[p-1], locY[p-1]
x1, y1 = locX[p+1], locY[p+1]
xM, yM = locX[p], locY[p]
dix, diy = x2 - x1, y2 - y1
hyp = sqrt(dix**2 + diy**2)
if hyp == 0: hyp = 0.000000000000000000001
ang = acos(dix/hyp)
perpL = ang + pi/4
perpR = ang - pi/4
###???maybe rotate the angle dynamically?
#-multiplying 1/hyp here makes width
# inv proportional to velocity
# because dist bt verts grow with vel, so does hyp
###???WORKS SORT OF, it's SOMETHING WITH THAT /0 hyp thing?
#velT = (1/ hyp)*2 #<====-----make a ui variable?
velT = .5
nx1 = cos(perpL)*velT
ny1 = sin(perpL)*velT
nx2 = cos(perpR)*velT
ny2 = sin(perpR)*velT
nxL = xM + nx1
nyL = yM + ny1
nxR = xM + nx2
nyR = yM + ny2
ZTIMESCALE = 50 #percent of framrun
ztime = p*(ZTIMESCALE/100) #<====-----make a ui variable
# and/or proportonal to wid/height
mpath.vertices.add(1)
mpath.vertices[len(mpath.vertices)-1].co = [
nxL, nyL, ztime]
#-centerline, same as loc...
#mpath.vertices.add(1)
#mpath.vertices[len(mpath.vertices)-1].co = [
# xM, yM, ztime]
mpath.vertices.add(1)
mpath.vertices[len(mpath.vertices)-1].co = [
nxR, nyR, ztime]
mpath.update()
#-DO NOT face last 4 verts or b will crash (last -1 one is for index
for fc in range(1, len(mpath.vertices)-5, 4):
mpath.faces.add(1)
mpath.faces[len(mpath.faces)-1].vertices_raw = [
fc, fc+2, fc+3, fc+1]
mpath.faces.add(1)
mpath.faces[len(mpath.faces)-1].vertices_raw = [
fc+3, fc+2, fc+4, fc+5]
mpath.update(calc_edges=True)
mpath.update(calc_edges=True)
opath = bpy.data.objects.new('path'+ob.name, mpath)
scn.objects.link(opath)
########################################################
def addExplosivo(obQ, vx, vy):
if len(obQ.data.faces) < 512:
#-have to subdivide cube first
scn.objects.active = obQ
cuts = len(obQ.data.faces) // 512
###???don't lnow how to do this with ops like this
#bpy.ops.mesh.subdivide(number_cuts = cuts, fractal = 0.25)
###??? maybe use fluids? or randomize settings?
obQ.modifiers.new(name = 'explosemit', type = 'PARTICLE_SYSTEM')
expart = obQ.particle_systems[0]
#expart.settings.count = 512 # 8x8x8 cube grid
expart.settings.count = 6 # for now
expart.settings.rotation_factor_random = 2.5
expart.settings.frame_start = scn.frame_current
expart.settings.frame_end = scn.frame_current + 1
expart.settings.lifetime = 120
expart.settings.lifetime_random = 1
expart.settings.use_dynamic_rotation = True
expart.settings.render_type = 'NONE'
expart.settings.draw_method = 'NONE'
expart.settings.rotation_factor_random = 1.0
expart.settings.factor_random = 10.0
expart.settings.object_align_factor = [vx*vx*vx, vy*vy*vy, 0]
#expart.settings.object_factor = 2
expart.settings.effector_weights.gravity = 0.0
expart.settings.brownian_factor = .25
#expart.settings.particle_size = 1
#expart.settings.use_multiply_size_mass = True
#expart.settings.use_size_deflect = True
#expart.settings.size_random = 2.5
###??? child particles?
exmod = obQ.modifiers.new(name = 'explosivo', type = 'EXPLODE')
exmod.show_dead = False
exmod.use_edge_split = True
#!!!bpy.ops.ptcache.bake(bake=True) now
# or bpy.ops.ptcache.bake_all() at the end of loop?
#-set all globs vectors tangent to the nearest sun
# hopefully will create more interesting sims
def setVecTangentToNearestHole():
#-trying set tan to nearest ob if no sun...
holeindex = []
for hole in scn.objects:
if hole.bhole:
holeindex.append(hole)
tempmult=35
if len(holeindex)<1:
for gobs in scn.objects:
if gobs.glob:
holeindex.append(gobs)
tempmult=10
print(holeindex)
for gob in scn.objects:
if gob.glob and gob.bhole == False:
x1, y1 = gob.location[0], gob.location[1]
nholeinit = True
for hole in holeindex:
if hole.name != gob.name:
#if sol != gob:
x2, y2 = hole.location[0], hole.location[1]
dix, diy = x2 - x1, y2 - y1
disq = dix*dix + diy*diy
dri = sqrt(disq)
# find nearest Sun
if nholeinit:
nholeinit = False
nhole = hole
nholedri = dri
nholex = dix
nholey = diy
continue
if dri < nholedri: nhole = hole nholedri = dri nholex = dix nholey = diy vang, vmag = getVectorAngle(nholex, nholey, 0.0, False) #-random if vector is clockwz/anticlock to sun and if # magnitude is proportional/invesely to dist to sun coinflip = random.uniform(0,1) coinflip = 1 #cheat for testing if coinflip >=.333:
vangNEW = vang + (pi/2)
vmagNEW = (1/nholedri)*tempmult
#-should include mass of second object in calc...
if coinflip < .333: vangNEW = vang - (pi/2) vmagNEW = vmag * nholedri / VECMULT for c in gob.children: if c.name[0:7] == 'vectail': c.rotation_euler = [0.0, 0.0, vangNEW] c.scale = [vmagNEW, vmagNEW, 0] hyp = vmagNEW / scn.VECMULT cvx = cos(vangNEW)*hyp cvy = sin(vangNEW)*hyp gob.vel = [cvx, cvy, 0.0] def updateVecFromTail(globV): kids = globV.children for c in kids: # get vx and vy back from rot, scale vecang = c.rotation_euler[2] vecmag = c.scale[0] hyp = vecmag / scn.VECMULT cvx = cos(vecang)*hyp cvy = sin(vecang)*hyp globV.vel = [cvx, cvy, 0.0] def getVectorAngle(vx, vy, vz, hyp): if hyp == False: hyp = (sqrt((vx*vx)+(vy*vy))) # avoid div-0, hacky I know... if hyp == 0: hyp = .0000000000001 if vx >= 0 and vy >= 0: # -I
vecang = asin(vy/hyp)
if vx <= 0 and vy >= 0: # -II
vecang = pi-asin(vy/hyp)
if vx <= 0 and vy <= 0: # -III vecang = -pi-asin(vy/hyp) if vx >= 0 and vy <= 0: # -IV vecang = asin(vy/hyp) vecmag = (hyp*scn.VECMULT) #this makes return value only good for tail DISPLAY return(vecang, vecmag) def flush(): killall = bpy.data.objects for deadmesh in killall: if deadmesh.glob or deadmesh.name[0:7] == "vectail": # #or deadmesh.name[0:len(SPREFIX)] == SPREFIX: if deadmesh.users == 0: bpy.data.objects.remove(deadmesh) else: print(deadmesh.name + ' is being stubborn...') scn.objects.link(deadmesh) for deadob in killall: if deadob.glob or deadob.name[0:7] == "vectail": # # or deadob.name[0:len(SPREFIX)] == SPREFIX: if deadob.users == 0: bpy.data.objects.remove(deadob) else: print(deadob.name + ' is being stubborn...') scn.objects.link(deadob) ######################### PHYSICS FXNS ######################### ######################### GLOB/SUN FXNS ######################### def updateAllVecFromTail(): for obs in scn.objects: if obs.glob: updateVecFromTail(obs) def updateTailFromVec(globV): kids = globV.children if globV.merged == False and len(kids) > 0:
vecang, vecmag = getVectorAngle(
globV.vel[0], globV.vel[1], globV.vel[2], False)
for c in kids:
c.rotation_euler = [0.0, 0.0, vecang]
c.scale = [vecmag, vecmag, 0.0]
c.keyframe_insert('rotation_euler', 2)
c.keyframe_insert('scale', 0)
c.keyframe_insert('scale', 1)
def makeVectorTail(globV):
mmesh = bpy.data.meshes.new('vectail')
mmesh.vertices.add(2)
mmesh.vertices[0].co = [0.0, 0.0, 0.0]
mmesh.vertices[1].co = [6.0, 0.0, 0.0]
mmesh.edges.add(1)
mmesh.edges[0].vertices = [0,1]
mmesh.update()
omesh = bpy.data.objects.new('vectail', mmesh)
scn.objects.link(omesh)
omesh.parent = globV
omesh.data = mmesh
omesh.hide_render = True
vecang, vecmag = getVectorAngle(
globV.vel[0], globV.vel[1], globV.vel[2], False)
omesh.rotation_euler = [0.0, 0.0, vecang]
omesh.scale = [vecmag, vecmag, 0]
def addVectorTails():
for obs in scn.objects:
if obs.glob:
if len(obs.children) > 0:
for kid in obs.children:
try: scn.objects.unlink(kid)
except: print('i dont get unlinking...')
makeVectorTail(obs)
def removeObject(xob):
xmesh = xob.data
scn.objects.unlink(xob)
try: bpy.data.objects.remove(xmesh)
except: print('---cannot remove ' + xmesh.name + '---')
try: bpy.data.objects.remove(ob)
except: print('---cannot remove ' + xob.name + '---')
def delSuns():
for xall in scn.objects:
if xall.bhole:
removeObject(xall)
#bpy.context.scene.objects.unlink(xall)
selectCheck()
def delGlobs():
for xall in scn.objects:
if xall.glob
or xall.name[0:7] == 'vectail'
or xall.name[0:8] == 'pathglob':
removeObject(xall)
selectCheck()
def selectCheck():
#-make sure there's an object active so panel doesn't disappear
if scn.objects.active: return
else:
if len(scn.objects) > 1:
scn.objects.active = scn.objects[0]
else:
newempty = bpy.ops.object.add()
newempty.hide = False
newempty.hide_select = False
newempty.hide_render = False
scn.objects.link(newempty)
scn.objects.active=newempty
"""
def makeGlobIndex():
GI = []
obs = scn.objects
for ob in obs:
if ob.glob:
#or ob.name[0:len(SPREFIX)] == SPREFIX:
GI.append(ob.name)
return GI
"""
######################### RUNLOOPS #########################
#def runit(GI):
def runit():
for globA in scn.objects:
if globA.glob:
#print(globA.name, ' is a glob')
#for i in range(0, len(GI)):
#globA = obs[GI[i]]
#globA = glob
if globA.bhole: continue #-don't calc force on blackholes (immovable)
if globA.merged: continue #-don't calc force on merged
Ax, Ay = globA.location[0], globA.location[1]
### ??? ### add option for round cliploop?
# check for CLIP (border)
if sqrt(Ax*Ax+Ay*Ay) > scn.CLIP:
if scn.LOOPATCLIP:
#-if loopatclip set, loop glob around
if abs(Ax) > scn.CLIP:
globA.location[0] = -Ax
if abs(Ay) > scn.CLIP:
globA.location[1] = -Ay
else:
#-otherwise stop and mark as merged so it'll be ignored
globA.merged = True
continue #-skip to next globA loop if globA outside CLIP
# temp loc, vel and acc vars for loop
tloc = globA.location
tvel = globA.vel
tacc = [0.0, 0.0, 0.0]
#for j in range(0, len(GI)):
for globB in scn.objects:
if globB.glob:
if globB == globA or globB.merged: continue
#globB = obs[GI[j]]
#globB = glob2
Bx, By = globB.location[0], globB.location[1]
dx, dy = Bx - Ax, By - Ay
dsq = dx*dx + dy*dy
#if dsq==0:dsq=0.0001 #-I am such a hack...
dr = sqrt(dsq)
#ignore own force
if dr > scn.MAXINTERAD: continue #ignore if beyond interaction radius
# add acceleration/force from this glob
#print(globA.name, ' has a problem with ', globB.name)
force = G * globA.tmass * globB.tmass / dsq
tacc[0] += force*dx/dr
tacc[1] += force*dy/dr
tloc[0] += tvel[0] * scn.DAMP #DAMPVELx
tloc[1] += tvel[1] * scn.DAMP #DAMPVELy
tvel[0] += tacc[0] * scn.DAMP #DAMPACCx
tvel[1] += tacc[1] * scn.DAMP #DAMPACCy
###!!!maybe add a mock relativity here by
# damping acceleration as approaches v approaches c
#-check if over max velocity, if so set to max
if tvel[0] > scn.MAXVEL: tvel[0] = scn.MAXVEL
if tvel[0] < -scn.MAXVEL: tvel[0] = -scn.MAXVEL if tvel[1] > scn.MAXVEL: tvel[1] = scn.MAXVEL
if tvel[1] < -scn.MAXVEL: tvel[1] = -scn.MAXVEL
tacc = [0.0, 0.0, 0.0]
#-merge if close enough (relative to draw size - a cheat - I know)
if dr <= (globA.scale[0]+globB.scale[0])*scn.DSIZE: if scn.ACCRETE: #-they're close, merge smaller to larger if globA.tmass >= globB.tmass:
globMerge(globB, globA)
else:
globMerge(globA, globB)
###!!!also add collision damping here based on density
if scn.EXPLODE:
vx1, vy1 = globA.vel[0], globA.vel[1]
vx2, vy2 = globB.vel[0], globB.vel[1]
vdx, vdy = vx2 = vx1, vy2 - vy1
vdsq =vdx*vdx + vdy*vdy
vdr = sqrt(vdsq)
if abs(vdr) > scn.EXTHRESH:
if globA.tmass >= globB.tmass:
if globB.type != 'META':
addExplosivo(globB, vdx, vdy)
else:
if globA.type != 'META':
addExplosivo(globA, vdx, vdy)
#update loc, vel, and insert kframes
globA.location[0] = tloc[0] #/ scn.SPACEsSCALE
globA.location[1] = tloc[1] #/ scn.SPACESsCALE
globA.vel = tvel
#if globA.name[0:len(SPREFIX)] != SPREFIX:
# ignore vectails of merged globs
if globA.merged == False:
globA.keyframe_insert('tmass')
globA.keyframe_insert('merged')
if globA.bhole == False:
globA.keyframe_insert('location', 0)
globA.keyframe_insert('location', 1)
globA.keyframe_insert('vel', 0)
globA.keyframe_insert('vel', 1)
#-check if the glob has vectails, update if they exist
for c in globA.children:
if c.name[0:7] == 'vectail':
updateTailFromVec(globA)
continue # vectail updated, so leave loop
def loopit():
t1 = time.ctime(time.time())
#GI = makeGlobIndex()
scn.frame_current = scn.STARTFRAME
#-adjust for user changes to vectails
updateAllVecFromTail()
setCurvesToConstant()
#-start on frame 2, 1st should NOT be recalculated
for f in range(scn.STARTFRAME+1, scn.STARTFRAME+scn.FRAMERUN):
scn.frame_current = f
print(scn.frame_current)
#runit(GI)
runit()
t2 = time.ctime(time.time())
# calc processing time
s1, m1 = int(t1[17:19]), int(t1[14:16])
s2, m2 = int(t2[17:19]), int(t2[14:16])
print(str(t1)[11:20], str(t2)[11:20])
print('simulation time: ' + str(abs(m2-m1)) + ':' + str(abs(s2-s1)))
###!!!ABSORB SOME IMPACT IN COLLISION!!!
### THESEARE NOT INDESTRUCTABLE...
### ALSO MAYBE ADD POTENTIAL FOR 'GLANCING BLOW'S and 'BOUNCES'
### because for now w acrete and axplode off all collisions will pass thru
def globMerge(globS, globL):
print(globL.name, globL.tmass, '+', globL.tmass, globS.name)
#if globS.bhole == 1: return
globS.merged = True
#-make merged globs vectail disappear
for cs in globS.children:
if cs.name[0:7] == 'vectail':
cs.scale = [0.0, 0.0, 0.0]
cs.keyframe_insert('scale', 0)
cs.keyframe_insert('scale', 1)
#-figure out vector between L and S to offset
# constraint of S on L as if stuck where hit
# also to direct particles/explode modifier
SLx = globS.location[0] - globL.location[0]
SLy = globS.location[1] - globL.location[1]
if SLx >= globL.scale[0]*scn.DSIZE: SLx = globL.scale[0]*scn.DSIZE
if SLy >= globL.scale[0]*scn.DSIZE: SLy = globL.scale[0]*scn.DSIZE
if SLx < -globL.scale[0]*scn.DSIZE: SLx = -globL.scale[0]*scn.DSIZE
if SLy < -globL.scale[0]*scn.DSIZE: SLy = -globL.scale[0]*scn.DSIZE
#SLx = 1 ###!!! sun merging is still weird
#SLy = 1
#-contrain smaller glob to larger
gcon = globS.constraints.new('COPY_LOCATION')
gcon.use_offset = True
gcon.target = globL
#-add constraint influence keyframe of
# pre-merge state to previous frame
ftemp = scn.frame_current
scn.frame_current = ftemp - 1
gcon.influence = 0
gcon.keyframe_insert('influence')
#-back to this frame to insert merged state keyframe
scn.frame_current = ftemp
gcon.influence = 1
gcon.keyframe_insert('influence')
globS.location = [SLx, SLy, 0.0]
#-add keyframes for post-merge
# location and constraint influence
globS.keyframe_insert('location', 0)
globS.keyframe_insert('location', 1)
# add velocity ofsmall glob to larger
### ??? ### CHECK THIS, OBJECT VELS SEEM TO GOOF ON IMPACK
newvx = (globL.vel[0] * globL.tmass +
globS.vel[0] * globS.tmass) /
(globL.tmass + globS.tmass)
newvy = (globL.vel[1] * globL.tmass +
globS.vel[1] * globS.tmass) /
(globL.tmass + globS.tmass)
#-update larger globs total mass and keyframe
globL.tmass += globS.tmass
globL.keyframe_insert('tmass')
print('mass updated : ', globL.name, globL.tmass)
globL.vel[0] = newvx
globL.vel[1] = newvy
def setCurvesToConstant():
for ob in scn.objects:
if ob.glob:
oanim = ob.animation_data
if oanim:
ocurves = oanim.action.fcurves
for ocurve in ocurves:
ocurve.extrapolation = 'CONSTANT'
###analysis fxns
def calcTotalMassRemaing():
#also how many last past 500 frames or so...
pass
######################### USER INTERFACE #########################
def initSceneProps(scn):
bpy.types.Scene.FRAMERUN = bpy.props.IntProperty(
name = "framerun")
bpy.types.Scene.PARTICLES = bpy.props.IntProperty(
name = "particles")
bpy.types.Scene.M = bpy.props.FloatProperty(
name = "earthmass")
bpy.types.Scene.T = bpy.props.FloatProperty(
name = "siderealyear")
bpy.types.Scene.WIDTH = bpy.props.IntProperty(
name = "width")
bpy.types.Scene.HEIGHT = bpy.props.IntProperty(
name = "height")
bpy.types.Scene.CLIP = bpy.props.IntProperty(
name = "clip")
bpy.types.Scene.DSIZE = bpy.props.FloatProperty(
name = "drawsize")
#bpy.types.Scene.SOLDIAM = bpy.props.FloatProperty(
# name = "earthdiameter")
bpy.types.Scene.A = bpy.props.FloatProperty(
name = "spacespace")
bpy.types.Scene.SIZEVAR = bpy.props.FloatProperty(
name = "sizevar")
bpy.types.Scene.DAMP = bpy.props.FloatProperty(
name = "damp")
bpy.types.Scene.LOOPATCLIP = bpy.props.BoolProperty(
name = "loopatclip")
bpy.types.Scene.MAXVEL = bpy.props.FloatProperty(
name = "maxiumum velocity")
bpy.types.Scene.SOLDIAM = bpy.props.FloatProperty(
name = "sun radius")
bpy.types.Scene.SUNRANDLOC = bpy.props.BoolProperty(
name = "random sun location")
bpy.types.Scene.RANDVEL = bpy.props.BoolProperty(
name = "random starting velocity")
bpy.types.Scene.STARTFRAME = bpy.props.IntProperty(
name = "startframe")
bpy.types.Scene.VECMULT = bpy.props.FloatProperty(
name = "vectordisplaymult")
bpy.types.Scene.MAXINTERAD = bpy.props.FloatProperty(
name = "maxinteractionradius")
bpy.types.Scene.RANDVELRANGE = bpy.props.FloatProperty(
name = "rendvelrange")
bpy.types.Scene.EXPLODE = bpy.props.BoolProperty(
name = "explode on impact")
bpy.types.Scene.ACCRETE = bpy.props.BoolProperty(
name = "accrete or not")
bpy.types.Scene.METABALLS = bpy.props.BoolProperty(
name = "accrete or not")
bpy.types.Scene.EXTHRESH = bpy.props.FloatProperty(
name = "explodeimpacethreshold")
scn.LOOPATCLIP = LOOPATCLIP
scn.FRAMERUN = FRAMERUN
scn.PARTICLES = PARTICLES
scn.M = M
scn.T = T
scn.WIDTH = WIDTH
scn.HEIGHT = HEIGHT
scn.CLIP = CLIP
scn.DSIZE = DSIZE
#scn.SOLDIAM = SOLDIAM
scn.SIZEVAR = SIZEVAR
scn.DAMP = DAMP
scn.MAXVEL = MAXVEL
#scn.SOLDIAM = SOLDIAM
scn.SUNRANDLOC = SUNRANDLOC
scn.RANDVEL = RANDVEL
scn.STARTFRAME = STARTFRAME
scn.RANDVELRANGE = RANDVELRANGE
scn.MAXINTERAD = MAXINTERAD
scn.EXTHRESH = EXTHRESH
scn.A = A
scn.VECMULT = VECMULT
scn.ACCRETE = ACCRETE
scn.EXPLODE = EXPLODE
scn.METABALLS = METABALLS
initSceneProps(scn)
bpy.types.Object.glob = bpy.props.BoolProperty(
name = 'glob',
default = False)
bpy.types.Object.tmass = bpy.props.FloatProperty(
name = 'total mass of object including others merged to it.',
default = 0.0)
bpy.types.Object.vel = bpy.props.FloatVectorProperty(
name = 'velocity',
default = (0.0, 0.0, 0.0))
bpy.types.Object.merged = bpy.props.BoolProperty(
name = 'merged',
default = False)
bpy.types.Object.bhole = bpy.props.BoolProperty(
name = 'blackhole',
default = False)
class OBJECT_PT_SOMPanel(bpy.types.Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "physics"
bl_label = "Simple Orbital Mechanics"
def draw_header(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
scene = scn
row1 = layout.row(align=True)
row2 = layout.row(align=True)
split1 = row1.split(percentage=0.5)
colX = split1.column()
colY = split1.column()
split2 = row2.split(percentage=0.33)
colL = split2.column()
colM = split2.column()
colR = split2.column()
colX.label(text="2D Gravity/Accretion Simulator", icon='WORLD_DATA')
ltext1 = 'vx: ' + str(scn.objects.active.vel[0])[0:9] +
' | ' +
'vy: ' + str(scn.objects.active.vel[1])[0:9]
colY.label(text=ltext1)
colX.label(text=scn.objects.active.name)
colY.label(text='scale: ' + str(scn.objects.active.scale[0]))
ltext2 = 'tmass: ' + str(scn.objects.active.tmass)[0:7]
ltext3 = 'merged: ' + str(scn.objects.active.merged)
colX.label(text=ltext3)
colY.label(text=ltext2)
colX.label(text='bhole: ' + str(scn.objects.active.bhole))
colY.label(text='')
colX.operator("create_globfield")
colY.operator("delete_globfield")
colX.label(text = '')
colY.operator("clear_animation")
colX.operator("addVecTails")
colY.operator("setVecTanToNearestSun")
colX.prop(scene, 'RANDVEL', icon='BLENDER', toggle=True)
colY.prop(scene, 'LOOPATCLIP', icon='BLENDER', toggle=True)
colX.prop(scene, 'RANDVELRANGE', icon='BLENDER')#, toggle=True)
colY.prop(scene, 'VECMULT', icon='BLENDER')#, toggle=True)
colL.operator("animate_globfield")
colM.prop(scene, 'FRAMERUN')
colR.prop(scene, 'STARTFRAME')
colL.prop(scene, 'WIDTH', icon='BLENDER')#, toggle=True)
colM.prop(scene, 'HEIGHT', icon='BLENDER')#, toggle=True)
colR.prop(scene, 'CLIP', icon='BLENDER')#, toggle=True)
colL.separator()
colM.separator()
colR.separator()
colL.prop(scene, 'PARTICLES', icon='BLENDER')#, toggle=True)
colM.prop(scene, 'MAXINTERAD', icon='BLENDER')#, toggle=True)
colR.prop(scene, 'SIZEVAR', icon='BLENDER')#, toggle=True)
colL.label(text='')
colM.prop(scene, 'DSIZE', icon='BLENDER')#, toggle=True)
#colR.prop(scene, 'SOLDIAM', icon='BLENDER')#, toggle=True)
colL.separator()
colM.separator()
colR.separator()
colL.prop(scene, 'DAMP', icon='BLENDER')#, toggle=True, expand=False)
#colM.prop(scene, 'GRAVITY', icon='BLENDER')#, toggle=True)
colR.prop(scene, 'MAXVEL', icon='BLENDER')#, toggle=True)
sunBox = colL.box()
sunBox.label(text = "Sun/Blackhole")
sunBox.operator("create_sunhole")
sunBox.operator("delete_sunholes")
sunBox.prop(scene, 'SOLDIAM', icon='BLENDER')#, toggle=True)
sunBox.prop(scene, 'SUNRANDLOC', icon='BLENDER', toggle=True)
#sunBox.prop(scene, 'SUNsDSIZE', icon='BLENDER')#, toggle=True)
#colM.template_curve_mapping(scene, 'mycurve', type='VECTOR')
#colR.template_reports_banner()
# these would be nice, also remember to useevent = true on props
colM.prop(scene, 'EXTHRESH', icon='BLENDER', toggle=True)
colR.prop(scene, 'A', icon='BLENDER')#, toggle=True)
colM.operator('createMeshPath')
colM.operator('testit3')
#colR.label(text='')
colM.label(text='')
colR.label(text='')
colM.operator('testit')
colR.operator('testit2')
colM.prop(scene, 'EXPLODE', icon='BLENDER', toggle=True)
colR.prop(scene, 'ACCRETE', icon='BLENDER', toggle=True)
#colM.prop(scene, 'TESTCOLLECT', icon='BLENDER', toggle=True)
#colR.menu('amenu', 'irmanu')
#colM.prop_enum(scene, 'TESTMENU', 't')
#colM.prop_enum(scene, 'TESTMENU', 't')
class SCENE_OT_testit3(bpy.types.Operator):
bl_idname = "testit3"
bl_label = "testit3"
bl_options = {'REGISTER'}
bl_description = "testit3"
def invoke(self, context, event):
print('---trying blah---')
#tob = scn.objects.active
#print(tob.name)
#createMetaBall()
setCurvesToConstant()
return("FINISHED")
class SCENE_OT_testit(bpy.types.Operator):
bl_idname = "testit"
bl_label = "testit"
bl_options = {'REGISTER'}
bl_description = "testit"
def invoke(self, context, event):
print('---trying to create a metaglob---')
createSolSystem()
return("FINISHED")
class SCENE_OT_testit2(bpy.types.Operator):
bl_idname = "testit2"
bl_label = "testit2FLUSH"
bl_options = {'REGISTER'}
bl_description = "testit2"
def invoke(self, context, event):
print('---testit2---')
flush()
#tob = scn.objects.active
#print(tob.name)
#createMetaBall()
return("FINISHED")
class SCENE_OT_createMeshPath(bpy.types.Operator):
bl_idname = "createMeshPath"
bl_label = "createMeshPath"
bl_options = {'REGISTER'}
bl_description = "create mesh ribbon from glob paths"
def invoke(self, context, event):
print('---watch it grow---')
createMeshPath()
return("FINISHED")
class SCENE_OT_setVecTanToNearestSun(bpy.types.Operator):
bl_idname = "setVecTanToNearestSun"
bl_label = "setVectorTangentToSuns"
bl_options = {'REGISTER'}
bl_description = "set vectors tangent to their nearest sun"
def invoke(self, context, event):
print('---turn away from the light---')
setVecTangentToNearestHole()
return("FINISHED")
class SCENE_OT_addVecTails(bpy.types.Operator):
bl_idname = "addVecTails"
bl_label = "addVectorTails"
bl_options = {'REGISTER'}
bl_description = "add/update vector tails to globs"
def invoke(self, context, event):
print('---youve got tails!---')
addVectorTails()
return("FINISHED")
class SCENE_OT_delete_sunholes(bpy.types.Operator):
bl_idname = "delete_sunholes"
bl_label = "deleteSunHoles"
bl_options = {'REGISTER'}
bl_description = "remove all suns"
def invoke(self, context, event):
print('---goodbye norma jean---')
delSuns()
return("FINISHED")
class SCENE_OT_create_globfield(bpy.types.Operator):
bl_idname = "clear_animation"
bl_label = "clearAnimation"
bl_options = {'REGISTER'}
bl_description = "clear all animation data"
def invoke(self, context, event):
print('---be gone animation data!---')
clearAnimation()
return("FINISHED")
class SCENE_OT_create_sunhole(bpy.types.Operator):
bl_idname = "create_sunhole"
bl_label = "createSunHole"
bl_options = {'REGISTER'}
bl_description = "create a Sun/Blackhole type stationary gravity well"
def invoke(self, context, event):
print('---mmm... matter---')
makeSunHole()
return("FINISHED")
class SCENE_OT_create_globfield(bpy.types.Operator):
bl_idname = "create_globfield"
bl_label = "createGlobs"
bl_options = {'REGISTER'}
bl_description = "create a field of globs based on parameters"
def invoke(self, context, event):
print('---let there be globs---')
makeGlobField()
return("FINISHED")
class SCENE_OT_delete_globfield(bpy.types.Operator):
bl_idname = "delete_globfield"
bl_label = "deleteGlobs"
bl_description = "delete all globs"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
print('---destroy all globs---')
delGlobs()
return{'FINISHED'}
class SCENE_OT_animate_globfield(bpy.types.Operator):
bl_idname = "animate_globfield"
bl_label = "animateGlobs"
bl_description = "gravitometicically animateify globjects"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
print('---i am busy calculating glob animations---')
loopit()
bpy.context.scene.frame_current = STARTFRAME
return{'FINISHED'}
def register():
bpy.types.Scene.some_strvar = bpy.props.StringProperty(
name='some_strvar',
description='a string variable i might need')
def unregister():
del bpy.types.Scene.some_strvar
if __name__ == "__main__":
register()
########## DROPDOWN BOX / MENU
"""
class RENDER_PT_matdropdown(bpy.types.Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_label = "Material Dropdown lists"
def draw(self, context):
rd = context.scene
layout = self.layout
layout.prop(rd, "mat_list_old", text="Replace")
layout.prop(rd, "mat_list_new", text="by")
layout.separator()
row = layout.row()
row.operator("custom.update_materiallists")
row.operator("custom.print_materials")
def replace():
MATERIALS = []
for i in range(len(bpy.data.materials)):
MATERIALS.append((str(i), bpy.data.materials[i].name, str(i)))
bpy.types.Scene.EnumProperty( attr="mat_list_old",
name="Replace",
description="Choose a material to be replaced",
items = MATERIALS, default = '0')
bpy.types.Scene.EnumProperty( attr="mat_list_new",
name="Replace by",
description="Choose a replacement material",
items = MATERIALS, default = '1')
class CUSTOM_OT_update_materiallists(bpy.types.Operator):
bl_idname = "CUSTOM_OT_update_materiallists"
bl_label = "Update"
bl_description = "Update the dropdown boxes. Necessary if you added or deleted materials in the scene."
def invoke(self, context, event):
replace()
return{'FINISHED'}
class CUSTOM_OT_print_materials(bpy.types.Operator):
bl_idname = "CUSTOM_OT_print_materials"
bl_label = "Print"
bl_description = "Print the selections of the dropdown boxes."
def invoke(self, context, event):
old = bpy.data.materials[int(bpy.context.scene.mat_list_old)]
new = bpy.data.materials[int(bpy.context.scene.mat_list_new)]
print("Replace",old.name,"by",new.name)
return{'FINISHED'}
if __name__ == '__main__':
bpy.types.register(CUSTOM_OT_update_materiallists)
bpy.types.register(CUSTOM_OT_print_materials)
replace()
bpy.types.register(RENDER_PT_matdropdown)
"""