{"id":41,"date":"2011-02-18T03:41:37","date_gmt":"2011-02-18T03:41:37","guid":{"rendered":"http:\/\/www.funkboxing.com\/wordpress\/?p=41"},"modified":"2021-08-26T19:50:04","modified_gmt":"2021-08-26T19:50:04","slug":"code-2","status":"publish","type":"post","link":"http:\/\/funkboxing.com\/wordpress\/?p=41","title":{"rendered":"Blender 2D Simple Gravity Simulator"},"content":{"rendered":"<p>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&#8217;s on the back burner for right now. Anyway it works if you feel like playing with it.<\/p>\n<div id=\"attachment_113\" style=\"width: 330px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity1.jpg\"><img aria-describedby=\"caption-attachment-113\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-113\" title=\"blendergravity1\" src=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity1.jpg\" alt=\"\" width=\"320\" height=\"240\" \/><\/a><p id=\"caption-attachment-113\" class=\"wp-caption-text\">create meshes from motion paths<\/p><\/div>\n<div id=\"attachment_114\" style=\"width: 330px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity2.jpg\"><img aria-describedby=\"caption-attachment-114\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-114\" title=\"blendergravity2\" src=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity2.jpg\" alt=\"\" width=\"320\" height=\"240\" \/><\/a><p id=\"caption-attachment-114\" class=\"wp-caption-text\">optional explosion if impact velocity over threshold<\/p><\/div>\n<div id=\"attachment_114\" style=\"width: 330px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity2.jpg\"><img aria-describedby=\"caption-attachment-114\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-114\" title=\"blendergravity2\" src=\"http:\/\/www.funkboxing.com\/wordpress\/wp-content\/uploads\/2011\/02\/blendergravity2.jpg\" alt=\"\" width=\"320\" height=\"240\" \/><\/a><p id=\"caption-attachment-114\" class=\"wp-caption-text\">optional explosion if impact velocity over threshold<\/p><\/div>\n<p>Features:<br \/>\n-2d gravity\/accretion of &#8216;glob&#8217; objects<br \/>\n-adjustable (G)ravitational constant (not in UI)<br \/>\n1 blender unit = a(AU)<br \/>\n1 mass unit = m(Solar Mass)<br \/>\n24frames = t(sidereal year)<br \/>\nG = sqrt((2*pi\/t)*(sqrt(a**2\/m)))<\/p>\n<p>Instructions:<br \/>\n-open Blender2.56b<br \/>\n-copy or load the script into the text editor and run script<br \/>\n-ui will be in physics panel<br \/>\n-adjust parameters<br \/>\n-create globs and\/or sun\/holes and\/or add\/adjust vector tails<br \/>\n-animate globs<\/p>\n<div style=\"height: 300px; width: 800px; font: 12px\/16px Georgia,Garamond,Serif; overflow: scroll;\">\n<pre class=\"brush:py\">##################################################\n#\n#\tSimple Orbital Mechanics - v.0.0.01a - 01.30.11\n#\tGPL, Public Licence, Open-Source, Free, etc...\n#\t2D Gravity\/Accretion Simuatior\n#\n#\t\tThanks to Thanassis Tsiodras for his\n#\"Naive simulator of gravity, in less than 200 Python lines\"\n#\t\thttp:\/\/users.softlab.ntua.gr\/~ttsiod\/gravity.html\n#\t\tit got me on the right track\n#\n#\t&gt;Physics Property Menu &gt;Simple Orbital Mechanics\n#\t-adjust parameters\n#\t&gt;createGobs, can create multiple times\n#\t\tand move if desired\n#\t&gt;createSuns, or name other objects with prefix 'sun'\n#\t\tand move if desired\n#\n##############################################################\n#\n#\t\tTODO\/WISHLIST:\n#\t\t- other objects\n#\t\t\t\tarbitrary objects\n#\t\t\t- impliment negative mass? repulsive matter?\n#\t\t\t\t\tother implimentations of gravity?\n#\t\t\t\t\tpushes at a distance,\n#\t\t\t- variable gravity?\n#\t  !\t- make 2dplane arbitrary somehow\n#\t\t\t\t\tmaybe give each object a xyz reconfig\n#\t\t\t\t\tso you can reassing so you can have\n#\t\t\t\t\tvarious systems interacting on diff\n#\t\t\t\t\tplane 1st would just\n#\t\t\t\t\tbe to reassign axis on keyframe\n#\t\t\t\t\t-make sure Z loc is not locked in any way\n#\t\t\t\t\tso i can play with stacking them\n#\t\t\t\t\tvertically, setup a sim, then\n#\t\t\t\t\tstart camera top and dolly side to reveal dist...\n#\t\t- materials (PlanetTex patch?)\n#\t\t- sim analysis\n#\t\t\trun thru varions configs\n#\t\t\tkeep those with best 'stability'\n#\t\t\t\tto make visually interesting sims\n#\t\t\t\tie. most mass stays inside bounds\n#\t\t\t\tor most non merged mass in bounds\n#\t\t\t\tand most movement in bounds?\n#\t\t- other movement formulas?\n#\t\t\t\tmaybe impliment fractal flames somehow though\n#\t\t\t\tthat's probably another project\n#\t\t- drive other params such as colors with loc\/vel\/acc\n#\t\t- option for dynamic rotation?\n#\t\t-\tcolor picker\n#\t\t\t\tvectors or other settings as color picker wheel?\n#\t\t\t\tlock to a black and use as vector?\n#\t\t-smaller regular partical emitter at ever merge\n#\t\t-also, maybe make all objects, attractors?#\n#\n#\t\tKNOWN ISSUES\n#\t\t- accumulation of data - .unlink,\n#\t\t\t\tneed to figure something else out\n#\t\t\t\t!!! have flush but crashes blender...\n#\t\t- cannot rotate vectortails directly in\n#\t\t\t\t3d view, only in 'n' panel. scale works though...\n#\t\t- CONSTRAINTS effecting start frame position\n#\t\t\t\trunning sim should not change start frame\n#\t\t\t\tTHE frame 1 JUMP IS ACTUALLY BECAUSE OF CONSTRANT\/SOMETHING\n#  \t\t\t or updating inital velocity\n#\t\t- clear animation data -FIX-\n#\t\t- sun' still getting location keyframed\n#\t\t- metballs don't really appear...\n####################################################\n\n###???ACRETION MERGERGLOB OFFSET ISN'T RIGHT. STILL\n#\t\tALLOWS OFFSET WAY BEYOND RADIUS\n\n###!!!3daxis interchange - just put a cust value for XYZ -&gt; ZYX mappting\n#\t\t\tthen adjust just before set location\n\n###???clear animation should also clear paths?\n\n###!!!add gloobject count to panel\n\n###???not making very good use of the index idea...\n#\t\tprobably get to that when I refactor for arbitary xyz\n#\t\tglobal scn, GI\n#\t\tGIsuns, GIglobs = [], []\n#\t\tGI = [GIsuns, GIglobs]\n#\t\tGI(index) will help with all kinds of stuff..\n# \t\talso work in more build in fxns like vector ang - xy converions for tails and whatnot\n\n###!!!also make time of partlife relative to framerun\n\n###!!!ADD PROPULSION???? somehow add thrust\/nav controls?\n#\t\tto try out different nav techniques\n\n###???metaballs, explode into other metaballs and add into GI\n#\t\tmaybe newly spawned objects are only effected by parent?\n#\t\tnew custom value = generation... (1st, 2nd, 3rd, etc)\n#\t\tOR split metaELEMTS!\n#\t\teventuallty make so metaball impacts create\n#\t\tnew objects and those are then calced in gravity...\n\n###!!!also - next progream...\n#\t\tdedicated script to gravitize a selection of any\n#\t\tobjects based on bounding box...\n#\t\t... try to make this one reletivistic\n#\t\tincding lorenz... try to help visualize\n# \t\treletivity on pc\n#\t\ttime dilation???\n#\t\treletivistic mass? all velocities based on % of maximum (essentially c)\n#\t\tthen incorporate E=mc2\t(somehow so harder to accelerate the faster\n# \t\tit's going...\n#\t\tfaster to use GI index on animate\n#\t\tespecuially if use keep 'merged' in index...\n\n###!!!LATER... metaball element trails...\n\n###???option to explode at clip? &lt;-------------- ###!!!on create mesh path verify there is anim data\t\t\t ###!!!lockxy rotation on tails ###???figure out subdivision... #\t\tcontext thing in panel? ###!!! add event to starting velocity #\t\tmake vecto suns toggle withevent... so you can change bac to random ###!!! maybe instead of merging with constraints, just  #\t\tseup so each loop if its merged it sets keyframe to its parents #\t\tthis could make axis-remapping easier in cases of merging #\t\t #################################################### ### NEXT NEXT NEXT NEXT NEXT NEXT NEXT NEXT NEXT  #################################################### ###!!!-----------&gt;figure out dist to sun relative to earth size...\n###!!!-----------&gt;radial glob field create option for kieper\/oort  35-55au\n###!!!Voyager...speed 3.5 au\/yr - exit trajectory from sol\t\n\n#then ui#\n#then refactor for release 00000.2 whaever\n#no core refactor, just loose ends, cleanup...\n#then post!!!\n#then sleep?\n\n#need some kind of collision damping\n\n##############################################################\n#-maybe some issues with significant digits at some point\n#\t\ti think python floats are 28 digits?\n\n#-something about mass from radius...\n\n\"\"\"sun = 1M = 1.98892e30 kg\nmercury\n3.3010e23\/1.98892e30\nvenus\n4.1380e24\/1.98892e30\nmars\n6.4273e23\/1.98892e30\njupiter\n1.89852e27\/1.98892e30\nsaturn\n5.6846e26\/1.98892e30\nuranus\n8.6819e25\/1.98892e30\nneptune\n1.02431e26\/1.98892e30\"\"\"\n\n#figure out what a frame = in this setup\n\n### got a lot of stuff working\n#\tbut... accretion offset is still wonky...\n#\tand... tmass fcurve is CURVED\n#\tneed to set curves to CONSTANT for merged, tmass, etc...\n\n\t###!!! its adding constrainy to emptys?\n\n######################### DEFAULTS\/CONFIG\/SETTINGS #########################\nimport bpy\nimport sys\nimport random\nimport time\nfrom math import pi, sqrt, sin, cos, asin, acos\n\n\"\"\"\n#derived from one mercury orbit-per-sec\n1.2252211349000193\/framerate = AU\/frame\n\n1 simsecond = 1 mercuryyear = 0.240 earthyear\n365.25*24*60*60 = 31557600 sec\/yr\n\n0.240*31557600 = 7573824.07573824.0\n1 simsecond = 7573824.07573824 realseconds\n\n---&gt;1 simframe = 0.240*31557600\/framerate realseconds\n\n365*24*60*60 = 31536000 sec\/yr (earth)\nc = 63188.25au\/yr\nc = 63188.25\/31536000 au\/sec\nc = 0.0020036862633181127 au\/sec\nG = 6.67300e-11 m**3\/kg**-1\/s**2\nF=G(m1*m2\/r**2)\n\t\t\"\"\"\n\n\t### I THINK I HAVE SCALE\/SIZE RIGHT\n\t###NOW NEED SOMETHING FOR KG AND SECONDS\n\n#figure out G for this rigwith m\/s\/kg from mybases\nscn = bpy.context.scene\n#-dimensions\nFRAMERUN = 300\t\t\t#ui length of simulation\n#AU = 1.0\t\t\t\t\t#ui 1BlenderUnit = 1AU\n\nWIDTH = 150\t\t\t\t#ui Blender units (should I add a scale option?)\nHEIGHT = 150\nCLIP = 1000\t\t\t#ui stop\/ignore objects too far out\nSTARTFRAME = 1\t\t\t#ui start frame of simulation\n\n#-globs\/sunholes\nPARTICLES = 5\t\t\t#ui number globs to add\n\n#FRAMERATE = scn.RenderSettings.fps\nFRAMERATE = 24\nTIMESCALE = 1.0\t\t#based on framerate, au, and cno idea... 1y?\n#---&gt;1 simframe = 0.240*31557600\/framerate realseconds\n\n#EdMASS = 1.0\t\t\t#ui??? Earth = 1unit: to be used for mass scaling and such\n#SOLMASS = 5.9736e24\n\nA = 1.0\t\t#astronomical unit = 149.60e6 km = 149.60e9 m\nM = 1.0\t\t#solar mass = 1.98892e30 kg\nT = 365.256363\t#sidereal year\n#D = 1.0\t\t#mean solar day = 86400.0025 SI seconds @ epoch J1900\n#gaussian constant = 0.01720209895 A**2\/3 D*-1 M*-1\/2\nG = sqrt((2*pi\/T)*(sqrt(A**2\/M)))\n\n#GM = GRAVITY * S\t\t#(GM product)\n#GRAVITY = G\t\t\t\t#ui effect of gravity \n\n#SOLDIAM = 1.0   ###!!!should be sol diam in AU?\n#SOLDIAM = 8.517493549379003e-05\t#Earth's diameter constant\n\t\t\t\t\t\t\t#\t\t1AU = 149598000 km\n\t\t\t\t\t\t\t#\t\tEarthDiameter = 12742.0 km\n\t\t\t\t\t\t\t#\t\tEarthDiameter = 12742\/149598000 AU\n\n\t\t\t\t\t\t\t#\nDSIZE = 250\t\t\t\t#\t\tSolar unit draw size of glob mesh\n\t\t\t\t\t\t\t#\t\tno effect on physics\n\nAXMAP = ['X','Y','Z']#default axismapping\n\nSIZEVAR = 1.0\t\t  \t#ui variation in glob size in feild generation\n\n#SsUNRADIUS = 109.0\t\t#ui default sun radius (same as Sol)\nSUNRANDLOC = True\t\t#ui default setting for random sun loc\n#SUNsDSIZE = 1.0\t\t\t#ui draw size of suns\n\n#-physics\nDAMP = 1.0\t\t\t\t#ui temp use for vel and acc (1.0 = no damp)\nMAXVEL = 20.0\t\t\t#ui max velocity\nMAXINTERAD = CLIP\t\t#ui max dist between 2 particles too calc force\nDAMPVEL = 1.0\t\t\t#na damp or add velocity (1.0 = 100%)\nDAMPACC = 1.0\t\t\t#na damp or add acceleration (less makes more spinny animations)\nDAMPVELx = DAMPVEL\t#na in case someone wants asymetrical damping later\nDAMPVELy = DAMPVEL\nDAMPACCx = DAMPACC\nDAMPACCy = DAMPACC\nRANDVEL = True     \t#ui generate random starting velocity\n\nRANDVELRANGE = .125\t#ui random range for staring velocity\nVECMULT = 10000\t\t#ui multiplier for vector tails should be just display\n\nLOOPATCLIP = False\t#ui option to loop at clip dist\n\nACCRETE = True\t\t\t#ui\nEXPLODE = True\t\t\t#ui\nEXTHRESH = .25\t\t\t#ui total impact velocity required to explode\nMETABALLS = False\n\n#-internal\nGPREFIX = 'glob'\t \t#fn prefix for globjects\nMOBNAME = 'mglob'\t \t#fn name of globject meshdata\nSPREFIX = 'sun'\t\t#fn name of sun objects\n\n###!!! replace the prefix system with a 'glob' variable\n\nprint('----------GEAUX!!!----------')\n\n################### playground ######################\n\n#-dist, size, mass,  based on Earth = 1\ndef createSolSystem():\n\t###!!!OortCloud\t\t2000-50,000 au\n\t###!!!ProximaCentauri\t268000\tau\n\t###!!!add Europa, Phobos, Demos, lots o' moons to add\n\t###!!!saturns rings?\n\tNOZERO = 0.00000000001\n\tprint('make a mass-distance-speed \/ scale accurate copy of sol')\n\tsolG2V = makeMeshCube('sun-SOLG2V', scn.DSIZE)\n\tsolG2V.name = 'sun-SOLG2V'\n\tsolG2V.location = [0.0, 0.0, 0.0]\n\tsolG2V.scale = [scn.SOLDIAM*109, scn.SOLDIAM*109, scn.SOLDIAM*109]\n\tsolG2V.tmass = scn.M\n\tsolG2V.modifiers.new('sunbevel', 'BEVEL')\n\tsolG2V.show_name = True\n\tscn.objects.link(solG2V)\n\n\tmercury = createMetaBall('glob-MERCURY', scn.DSIZE)\n\tmercury.name = 'glob-MERCURY'\n\tmercury.location = [-0.39, NOZERO, 0.0]\n\tmercury.scale = [scn.SOLDIAM*0.3829, scn.SOLDIAM*0.3829, scn.SOLDIAM*0.3829]\n\tmercury.tmass = scn.M*0.055\n\tmercury.vel = [0.0, -0.24, 0.0]\n\tmercury.show_name = True\n\tmercury.merged = False\n\tscn.objects.link(mercury)\n\n\tvenus = createMetaBall('glob-VENUS', scn.DSIZE)\n\tvenus.name = 'glob-VENUS'\n\tvenus.location = [NOZERO, 0.72, 0.0]\n\tvenus.scale = [scn.SOLDIAM*0.949, scn.SOLDIAM*0.949, scn.SOLDIAM*0.949]\n\tvenus.tmass = scn.M*0.82\n\tvenus.vel = [-0.62, 0.0, 0.0]\n\tvenus.show_name = True\n\tvenus.merged = False\n\tscn.objects.link(venus)\n\n\tearth = createMetaBall('glob-EARTH', scn.DSIZE)\n\tearth.name = 'glob-EARTH'\n\tearth.location = [1.0, NOZERO, 0.0]\n\tearth.scale = [scn.SOLDIAM, scn.SOLDIAM, scn.SOLDIAM]\n\tearth.tmass = scn.M\n\tearth.vel = [0.0, 1.0, 0.0]###??? EARTH BASED VELOCITY? SURE WHY NOT\n\tearth.show_name = True\n\tearth.merged =False\n\tscn.objects.link(earth)\t\t###??? wrong though, it's orbital period, not velocity...\n\n###\n\tluna = createMetaBall('glob-LUNA', scn.DSIZE)\n\tluna.name = 'glob-LUNA'\n\tluna.location = [1.026, NOZERO, 0.0]\n\tluna.scale = [scn.SOLDIAM*0.273, scn.SOLDIAM*0.273, scn.SOLDIAM*0.273]\n\tluna.tmass = scn.M*0.012\n\tluna.vel = [0.0, 1.0, 0.0]\n\tluna.show_name = True\n\tluna.merged = False\n\tscn.objects.link(luna)\n\n\tmars = createMetaBall('glob-MARS', scn.DSIZE)\n\tmars.name = 'glob-MARS'\n\tmars.location = [NOZERO, -1.52, 0.0]\n\tmars.scale = [scn.SOLDIAM*0.532, scn.SOLDIAM*0.532, scn.SOLDIAM*0.532]\n\tmars.tmass = scn.M*0.11\n\tmars.vel = [1.88, 0.0, 0.0]\n\tmars.show_name = True\n\tmars.merged = False\n\tscn.objects.link(mars)\t\t\n\n\tjupiter = createMetaBall('glob-JUPITER', scn.DSIZE)\n\tjupiter.name = 'glob-JUPITER'\n\tjupiter.location = [-5.204267, NOZERO, 0.0]\n\tjupiter.scale = [scn.SOLDIAM*11.209, scn.SOLDIAM*11.209, scn.SOLDIAM*11.209]\n\tjupiter.tmass = scn.M*317.8\n\tjupiter.vel = [0.0, -11.86, 0.0]\n\tjupiter.show_name = True\n\tjupiter.merged = False\n\tscn.objects.link(jupiter)\n\n\tsaturn = createMetaBall('glob-SATURN', scn.DSIZE)\n\tsaturn.name = 'glob-SATURN'\n\tsaturn.location = [NOZERO, 9.582, 0.0]\n\tsaturn.scale = [scn.SOLDIAM*9.449, scn.SOLDIAM*9.449, scn.SOLDIAM*9.449]\n\tsaturn.tmass = scn.M*95.2\n\tsaturn.vel = [-29.46, 0.0, 0.0]\n\tsaturn.show_name = True\n\tsaturn.merged = False\n\tscn.objects.link(saturn)\t\t\n\n\turanus = createMetaBall('glob-URANUS', scn.DSIZE)\n\turanus.name = 'glob-URANUS'\n\turanus.location = [19.22, NOZERO, 0.0]\n\turanus.scale = [scn.SOLDIAM*4.007, scn.SOLDIAM*4.007, scn.SOLDIAM*4.007]\n\turanus.tmass = scn.M*14.6\n\turanus.vel = [0.0, 84.01, 0.0]\n\turanus.show_name = True\n\turanus.merged = False\n\tscn.objects.link(uranus)\t\t\n\n\tneptune = createMetaBall('glob-NEPTUNE', scn.DSIZE)\n\tneptune.name = 'glob-NEPTUNE'\n\tneptune.location = [NOZERO, -30.06, 0.0]\n\tneptune.scale = [scn.SOLDIAM*3.883, scn.SOLDIAM*3.883, scn.SOLDIAM*3.883]\n\tneptune.tmass = scn.M*17.2\n\tneptune.vel = [164.8, 0.0, 0.0]\n\tneptune.show_name = True\n\tneptune.merged = False\n\tscn.objects.link(neptune)\t\t\n\n\tpluto = createMetaBall('glob-PLUTO', scn.DSIZE)\n\tpluto.name = 'glob-PLUTO'\n\tpluto.location = [-29.74, NOZERO, 0.0]\n\tpluto.scale = [scn.SOLDIAM*0.19, scn.SOLDIAM*0.19, scn.SOLDIAM*0.19]\n\tpluto.tmass = scn.M*0.002\n\tpluto.vel = [0.0, -248.09, 0.0]\n\tpluto.merged =False\n\tpluto.show_name = True\n\tscn.objects.link(pluto)\n\n\tsedna = createMetaBall('glob-SEDNA', scn.DSIZE)\n\tsedna.name = 'glob-SEDNA'\n\tsedna.location = [NOZERO, 960.0, 0.0]\n\tsedna.scale = [scn.SOLDIAM*0.2197, scn.SOLDIAM*0.2197, scn.SOLDIAM*0.2197]\n\tsedna.tmass = scn.M*0.0004185081023168609\n\tsedna.vel = [-118090.0, 0.0, 0.0]\n\tsedna.show_name = True\n\tsedna.merged = False\n\tscn.objects.link(sedna)\n\n\tvoyager = makeMeshCube('glob-VOYAGER', scn.DSIZE)\n\tvoyager.name = 'glob-VOYAGER1'\n\tvoyager.location = [-115.0, NOZERO, 0.0]\n\tvoyager.scale = [scn.SOLDIAM*1.5696123057604772e-06, \n\t\tscn.SOLDIAM*1.5696123057604772e-06, scn.SOLDIAM*1.5696123057604772e-06]\n\tvoyager.tmass = scn.M*1.2086513994910943e-22\n\tvoyager.vel = [0.0, -10.0, 0.0]\n\tscn.objects.link(voyager)\n\tvoyager.show_name = True\n\tvoyager.merged = False\t\n\ndef makeGlobField():\n\tfor i in range(scn.PARTICLES):\n\t\tgx = random.uniform(-scn.WIDTH\/2, scn.WIDTH\/2)\n\t\tgy = random.uniform(-scn.HEIGHT\/2, scn.HEIGHT\/2)\n\t\tgz = 0.0\t\t\t\t\t\t\t\t\t\t\t\t  #2D sim for now\n\n\t\t#gs = random.uniform(scn.SOLDIAM-(scn.SOLDIAM*(scn.SIZEVAR\/2)), \n\t\t#\tscn.SOLDIAM+(scn.SOLDIAM*(scn.SIZEVAR\/2)))\n\t\t#sun diameter = 1391000 kilometers\n\t\t#au = 149598000 kilometers\n\t\t#sun diameter = 1391000\/149598000 AU\n\t\t#sun diameter = 0.009298252650436503 AU\n\t\tgs = 0.009298252650436503  #-make variable? this makes default sun size our sun\n\n\t\tif METABALLS:\n\t\t\tnewob = createMetaBall('metaglobule', scn.DSIZE)\n\t\t\tglobname = GPREFIX + 'meta-' + str(i+1000)[1:4]\n\n\t\telse:\n\t\t\tnewob = makeMeshCube(MOBNAME, scn.DSIZE)\n\t\t\tglobname = GPREFIX + '-' + str(i+1000)[1:4]\n\n\t\tnewob.name = globname\n\t\tnewob.location = [gx, gy, gz]\n\t\tnewob.scale = [gs, gs, gs]\t\t  \n\n\t\t\t#add custom properties\n\t\tnewob.merged = False\n\t\tnewob.bhole = False\n\t\t#newob.tmass = scn.M *random.uniform(1, SIZEVAR)\n\t\tnewob.tmass = scn.M # should be a random mass var\n\t\tnewob.vel = [0.0, 0.0, 0.0]\n\t\t#newob.density = scn.STDENSITY\n\t\tif scn.RANDVEL:\n\t\t\tgvx = random.uniform(-RANDVELRANGE\/2, RANDVELRANGE\/2)\n\t\t\tgvy = random.uniform(-RANDVELRANGE\/2, RANDVELRANGE\/2)\n\t\t\tgvz = 0.0\n\t\t\tnewob.vel = [gvx, gvy, gvz]\n\n\t\tscn.objects.link(newob)\n\ndef createMetaBall(mname, msize):\n\tmsize = msize\/2 #-radius from diameter\n\t#-have to go into edit mode to refesh metaobj for some reason\n\tmball = bpy.data.metaballs.new(mname)\n\tfor m in range(1):\n\t\tmel = mball.elements.new()\n\t\t#mel.type = 'BALL'\n\t\tmel.co = [0.0, 0.0, 0.0]\n\t\tmel.size_x = msize\n\t\tmel.size_y = msize\n\t\tmel.size_z = msize\n\t\t#mel.stiffness = 1.0\n\t\t#mel.use_negative = False\t\t#could be fun\n\toball = bpy.data.objects.new('metaglobule', mball)\n\toball.data = mball\n\toball.glob = True\n\treturn(oball)\n\ndef makeMeshCube(mname, msize):\n\tmsize = msize\/2 #-radius from diameter\n\tmmesh = bpy.data.meshes.new(mname)\n\tmmesh.vertices.add(8)\n\tmmesh.vertices[0].co = [-msize, -msize, -msize]\n\tmmesh.vertices[1].co = [-msize,  msize, -msize]\n\tmmesh.vertices[2].co = [ msize,  msize, -msize]\n\tmmesh.vertices[3].co = [ msize, -msize, -msize]\n\tmmesh.vertices[4].co = [-msize, -msize,  msize]\n\tmmesh.vertices[5].co = [-msize,  msize,  msize]\n\tmmesh.vertices[6].co = [ msize,  msize,  msize]\n\tmmesh.vertices[7].co = [ msize, -msize,  msize]\n\n\tmmesh.faces.add(6)\n\tmmesh.faces[0].vertices_raw = [0,1,2,3]\n\tmmesh.faces[1].vertices_raw = [0,4,5,1]\n\tmmesh.faces[2].vertices_raw = [2,1,5,6]\n\tmmesh.faces[3].vertices_raw = [3,2,6,7]\n\tmmesh.faces[4].vertices_raw = [0,3,7,4]\n\tmmesh.faces[5].vertices_raw = [5,4,7,6]\n\tmmesh.update(calc_edges=True)\n\n\tomesh = bpy.data.objects.new(mname, mmesh)\n\tomesh.data = mmesh\n\tomesh.glob = True\n\treturn(omesh)\n\ndef makeSunHole():\n\tholemass = 10\n\tll = []\n\tfor m in scn.objects:\n\t\tif m.name[0:len(SPREFIX)] == SPREFIX:\n\t\t\tll.append(m.name)\n\tgx = random.uniform(-scn.WIDTH\/2, scn.WIDTH\/2)\n\tgy = random.uniform(-scn.HEIGHT\/2, scn.HEIGHT\/2)\n\tgz = 0\n\tgs = 0.009298252650436503 #-sol diam in AU\n\tnewsun = makeMeshCube('sunmesh', scn.DSIZE)\n\tnewsun.name = SPREFIX + '-' +str(len(ll)+1000)[1:4]\n\tif scn.SUNRANDLOC:\n\t\tnewsun.location = [gx, gy, gz]\n\tnewsun.scale = [gs, gs, gs]\n\tnewsun.modifiers.new('sunbevel', 'BEVEL')\n\tnewsun.merged = False\n\tnewsun.bhole = True\n\tnewsun.tmass = scn.M * holemass\n\tscn.objects.link(newsun)\n\ndef clearAnimation():\n\tfor o in scn.objects:\n\t\tfor f in range(scn.FRAMERUN):\n\t\t\tscn.frame_current = f+1\n\t\t\tif o.name[0:len(GPREFIX)] == GPREFIX \n\t\t\tor o.name[0:len(SPREFIX)] == SPREFIX:\n\t\t\t\to.keyframe_delete('location')\n\t\t\t\to.keyframe_delete('vel')\n\t\t\t\to.keyframe_delete('tmass')\n\t\t\t\to.keyframe_delete('merged')\n\t\tfor c in o.constraints:\n\t\t\tc.keyframe_delete('influence')\n\t\t\to.constraints.remove(c)\n\n\t\t# QQQ remove constraints influence frames too?\n\ndef createMeshPath():\n\t###!!! set this up to use ob.glob but not ob.bhole\n\t#-this is UGLY, need to find how to get fcurve data easier\n\tfor ob in scn.objects:\n\t\tif ob.name[0:len(GPREFIX)] == GPREFIX: # \n\t\t#and len(GPREFIX)+4 == len(ob.name):\t#-hope avoid making path for path\n\t\t\tlocX, locY, locZ, frame = [], [], [], []\n\t\t\tfor f in range(scn.STARTFRAME, scn.FRAMERUN+1):\n\t\t\t\toanim = ob.animation_data\n\t\t\t\tocurves = oanim.action.fcurves\n\t\t\t\taddframe = 0\n\t\t\t\tstopvert = 5\n\t\t\t\t#-some hacky bullshit to make merged blobs paths right\n\t\t\t\tfor ocurve in ocurves:\n\t\t\t\t\t#-only add to array if object hasn's been merged. !!! BROKE!\n\t\t\t\t\tif ocurve.data_path == 'merged' and ocurve.evaluate(f) == False:\n\t\t\t\t\t\taddframe = 1\n\t\t\t\t\t\tstopvert = 0\n\t\t\t\tfor ocurve in ocurves:\n\t\t\t\t\tif addframe == 1:\n\t\t\t\t\t\tif ocurve.data_path == 'location' \n\t\t\t\t\t\tand ocurve.array_index == 0:\n\t\t\t\t\t\t\tlocX.append(ocurve.evaluate(f))\n\t\t\t\t\t\tif ocurve.data_path == 'location' \n\t\t\t\t\t\tand ocurve.array_index == 1:\n\t\t\t\t\t\t\tlocY.append(ocurve.evaluate(f))\n\n\t\t\t#-dont create motion paths under a % of FRAMERUM\n\t\t\tPATHTHRESH = 20 #%&lt;-----make a ui variable (or setup file)\n\t\t\tif len(locX)\/scn.FRAMERUN &lt; PATHTHRESH\/scn.FRAMERUN: \t\t\t\tprint(len(locX)\/scn.FRAMERUN, PATHTHRESH\/scn.FRAMERUN) \t\t\t\tcontinue\t\t\t\t\t\t\t\t\t\t\t \t\t\tmpath = bpy.data.meshes.new('meshpath') \t\t\tmpath.use_auto_smooth = True \t\t\tfor p in range(len(locX)-1): \t\t\t\tif p == 0 or p == len(locX)-1: \t\t\t\t\tmpath.vertices.add(1) \t\t\t\t\tmpath.vertices[len(mpath.vertices)-1].co = [locX[p], locY[p], 0.0] \t\t\t\tif p &gt; 0 and p &lt; len(locX)-1-stopvert:\n\t\t\t\t\tx2, y2 = locX[p-1], locY[p-1]\n\t\t\t\t\tx1, y1 = locX[p+1], locY[p+1]\n\t\t\t\t\txM, yM = locX[p], locY[p]\n\t\t\t\t\tdix, diy = x2 - x1, y2 - y1\n\t\t\t\t\thyp = sqrt(dix**2 + diy**2)\n\t\t\t\t\tif hyp == 0: hyp = 0.000000000000000000001\n\t\t\t\t\tang = acos(dix\/hyp)\n\t\t\t\t\tperpL = ang + pi\/4\n\t\t\t\t\tperpR = ang - pi\/4\n\t\t\t\t\t###???maybe rotate the angle dynamically?\n\n\t\t\t\t\t#-multiplying 1\/hyp here makes width\n\t\t\t\t\t#\t\tinv proportional to velocity\n\t\t\t\t\t#\t\tbecause dist bt verts grow with vel, so does hyp\n\t\t\t\t\t###???WORKS SORT OF, it's SOMETHING WITH THAT \/0 hyp thing?\n\t\t\t\t\t#velT = (1\/ hyp)*2 #&lt;====-----make a ui variable?\n\t\t\t\t\tvelT = .5\n\t\t\t\t\tnx1 = cos(perpL)*velT\n\t\t\t\t\tny1 = sin(perpL)*velT\n\t\t\t\t\tnx2 = cos(perpR)*velT\n\t\t\t\t\tny2 = sin(perpR)*velT\n\t\t\t\t\tnxL = xM + nx1\n\t\t\t\t\tnyL = yM + ny1\n\t\t\t\t\tnxR = xM + nx2\n\t\t\t\t\tnyR = yM + ny2\n\t\t\t\t\tZTIMESCALE = 50\t#percent of framrun\n\t\t\t\t\tztime = p*(ZTIMESCALE\/100)\t#&lt;====-----make a ui variable\n\t\t\t\t\t\t\t\t\t\t#\t\t\t\tand\/or proportonal to wid\/height\n\n\t\t\t\t\tmpath.vertices.add(1)\n\t\t\t\t\tmpath.vertices[len(mpath.vertices)-1].co = [ \n\t\t\t\t\t\t\tnxL, nyL, ztime]\n\t\t\t\t\t#-centerline, same as loc...\n\t\t\t\t\t#mpath.vertices.add(1)\n\t\t\t\t\t#mpath.vertices[len(mpath.vertices)-1].co = [ \n\t\t\t\t\t#\t\txM, yM, ztime]\n\t\t\t\t\tmpath.vertices.add(1)\n\t\t\t\t\tmpath.vertices[len(mpath.vertices)-1].co = [ \n\t\t\t\t\t\t\tnxR, nyR, ztime]\n\n\t\t\tmpath.update()\n\t\t\t#-DO NOT face last 4 verts or b will crash (last -1 one is for index\n\t\t\tfor fc in range(1, len(mpath.vertices)-5, 4):\n\t\t\t\tmpath.faces.add(1)\n\t\t\t\tmpath.faces[len(mpath.faces)-1].vertices_raw = [ \n\t\t\t\t\tfc, fc+2, fc+3, fc+1]\n\t\t\t\tmpath.faces.add(1)\n\t\t\t\tmpath.faces[len(mpath.faces)-1].vertices_raw = [ \n\t\t\t\t\tfc+3, fc+2, fc+4, fc+5]\n\t\t\t\tmpath.update(calc_edges=True)\t\t\t\t\t\t\t\t\t\n\n\t\t\tmpath.update(calc_edges=True)\n\t\t\topath = bpy.data.objects.new('path'+ob.name, mpath)\n\t\t\tscn.objects.link(opath)\n\n########################################################\n\ndef addExplosivo(obQ, vx, vy):\n\tif len(obQ.data.faces) &lt; 512:\n\t\t#-have to subdivide cube first\n\t\tscn.objects.active = obQ\n\t\tcuts = len(obQ.data.faces) \/\/ 512\n\t\t###???don't lnow how to do this with ops like this\n\t\t#bpy.ops.mesh.subdivide(number_cuts = cuts, fractal = 0.25)\n\n\t###??? maybe use fluids? or randomize settings?\n\tobQ.modifiers.new(name = 'explosemit', type = 'PARTICLE_SYSTEM')\n\texpart = obQ.particle_systems[0]\n\t#expart.settings.count = 512 # 8x8x8 cube grid\n\texpart.settings.count = 6 # for now\n\texpart.settings.rotation_factor_random = 2.5\n\texpart.settings.frame_start = scn.frame_current\n\texpart.settings.frame_end = scn.frame_current + 1\n\texpart.settings.lifetime = 120\n\texpart.settings.lifetime_random = 1\n\texpart.settings.use_dynamic_rotation = True\n\texpart.settings.render_type = 'NONE'\n\texpart.settings.draw_method = 'NONE'\n\texpart.settings.rotation_factor_random = 1.0\n\texpart.settings.factor_random = 10.0\n\n\texpart.settings.object_align_factor\t= [vx*vx*vx, vy*vy*vy, 0]\n\t#expart.settings.object_factor = 2\n\texpart.settings.effector_weights.gravity = 0.0\n\texpart.settings.brownian_factor = .25\n\t#expart.settings.particle_size = 1\n\t#expart.settings.use_multiply_size_mass = True\n\t#expart.settings.use_size_deflect = True\n\t#expart.settings.size_random = 2.5\n\t###??? child particles?\n\texmod = obQ.modifiers.new(name = 'explosivo', type = 'EXPLODE')\n\texmod.show_dead = False\n\texmod.use_edge_split = True\n\t#!!!bpy.ops.ptcache.bake(bake=True) now\n\t#\t\tor bpy.ops.ptcache.bake_all() at the end of loop?\n\n#-set all globs vectors tangent to the nearest sun\n#\t\thopefully will create more interesting sims\ndef setVecTangentToNearestHole():\n\t#-trying set tan to nearest ob if no sun...\n\tholeindex = []\n\tfor hole in scn.objects:\n\t\tif hole.bhole:\n\t\t\tholeindex.append(hole)\n\t\t\ttempmult=35\n\tif len(holeindex)&lt;1:\n\t\tfor gobs in scn.objects:\n\t\t\tif gobs.glob:\n\t\t\t\tholeindex.append(gobs)\n\t\t\t\ttempmult=10\n\n\tprint(holeindex)\n\tfor gob in scn.objects:\n\t\tif gob.glob and gob.bhole == False:\n\t\t\tx1, y1 = gob.location[0], gob.location[1]\n\t\t\tnholeinit = True\n\t\t\tfor hole in holeindex:\n\t\t\t\tif hole.name != gob.name:\n\t\t\t\t#if sol != gob:\n\t\t\t\t\tx2, y2 = hole.location[0], hole.location[1]\n\t\t\t\t\tdix, diy = x2 - x1, y2 - y1\n\t\t\t\t\tdisq = dix*dix + diy*diy\n\t\t\t\t\tdri = sqrt(disq)\n\t\t\t\t\t# find nearest Sun\n\t\t\t\t\tif nholeinit:\n\t\t\t\t\t\tnholeinit = False\n\t\t\t\t\t\tnhole = hole\n\t\t\t\t\t\tnholedri = dri\n\t\t\t\t\t\tnholex = dix\n\t\t\t\t\t\tnholey = diy\n\t\t\t\t\t\tcontinue\n\t\t\t\t\tif\tdri &lt; nholedri: \t\t\t\t\t\tnhole = hole \t\t\t\t\t\tnholedri = dri \t\t\t\t\t\tnholex = dix \t\t\t\t\t\tnholey = diy \t\t\tvang, vmag = getVectorAngle(nholex, nholey, 0.0, False) \t\t\t#-random if vector is clockwz\/anticlock to sun and if  \t\t\t#\t\tmagnitude is proportional\/invesely to dist to sun \t\t\tcoinflip = random.uniform(0,1) \t\t\tcoinflip = 1\t#cheat for testing \t\t\tif coinflip &gt;=.333:\n\t\t\t\tvangNEW = vang + (pi\/2)\n\t\t\t\tvmagNEW = (1\/nholedri)*tempmult\n\t\t\t\t#-should include mass of second object in calc...\n\t\t\tif coinflip &lt; .333: \t\t\t\tvangNEW = vang - (pi\/2) \t\t\t\tvmagNEW = vmag * nholedri \/ VECMULT \t\t\tfor c in gob.children: \t\t\t\tif c.name[0:7] == 'vectail': \t\t\t\t\tc.rotation_euler = [0.0, 0.0, vangNEW] \t\t\t\t\tc.scale = [vmagNEW, vmagNEW, 0] \t\t\thyp = vmagNEW  \/ scn.VECMULT \t\t\tcvx = cos(vangNEW)*hyp \t\t\tcvy = sin(vangNEW)*hyp \t\t\tgob.vel = [cvx, cvy, 0.0] def updateVecFromTail(globV): \tkids = globV.children \tfor c in kids: \t\t# get vx and vy back from rot, scale \t\tvecang = c.rotation_euler[2] \t\tvecmag = c.scale[0] \t\thyp = vecmag \/ scn.VECMULT \t\tcvx = cos(vecang)*hyp \t\tcvy = sin(vecang)*hyp \t\tglobV.vel = [cvx, cvy, 0.0]\t\t\t\t\t \t\t\t\t def getVectorAngle(vx, vy, vz, hyp): \tif hyp == False: hyp = (sqrt((vx*vx)+(vy*vy))) \t# avoid div-0, hacky I know... \tif hyp == 0: hyp = .0000000000001 \tif vx &gt;= 0 and vy &gt;= 0:\t\t\t\t\t# -I\n\t\tvecang = asin(vy\/hyp)\n\tif vx &lt;= 0 and vy &gt;= 0:\t\t\t\t\t# -II\n\t\tvecang = pi-asin(vy\/hyp)\n\tif vx &lt;= 0 and vy &lt;= 0:\t\t\t\t\t# -III\t \t\tvecang = -pi-asin(vy\/hyp)\t\t \tif vx &gt;= 0 and vy &lt;= 0:\t\t\t\t\t# -IV \t\tvecang = asin(vy\/hyp)\t \tvecmag = (hyp*scn.VECMULT)\t\t#this makes return value only good for tail DISPLAY \treturn(vecang, vecmag)\t\t\t\t\t\t \t\t\t\t\t \t def flush(): \tkillall = bpy.data.objects \tfor deadmesh in killall: \t\tif deadmesh.glob  \t\tor deadmesh.name[0:7] == \"vectail\": # \t\t#or deadmesh.name[0:len(SPREFIX)] == SPREFIX: \t\t\tif deadmesh.users == 0: \t\t\t\tbpy.data.objects.remove(deadmesh) \t\t\telse: print(deadmesh.name + ' is being stubborn...') \t\t\tscn.objects.link(deadmesh) \tfor deadob in killall: \t\tif deadob.glob  \t\tor deadob.name[0:7] == \"vectail\": # \t#\tor deadob.name[0:len(SPREFIX)] == SPREFIX: \t\t\tif deadob.users == 0:\t\t\t \t\t\t\tbpy.data.objects.remove(deadob) \t\t\telse: print(deadob.name + ' is being stubborn...') \t\t\tscn.objects.link(deadob)\t\t\t ######################### PHYSICS FXNS ######################### ######################### GLOB\/SUN FXNS ######################### \t\t def updateAllVecFromTail(): \tfor obs in scn.objects: \t\tif obs.glob: \t\t\tupdateVecFromTail(obs) def updateTailFromVec(globV): \tkids = globV.children \tif globV.merged == False and len(kids) &gt; 0:\n\t\tvecang, vecmag = getVectorAngle( \n\t\t\tglobV.vel[0], globV.vel[1], globV.vel[2], False)\n\t\tfor c in kids:\n\t\t\tc.rotation_euler = [0.0, 0.0, vecang]\n\t\t\tc.scale = [vecmag, vecmag, 0.0]\n\t\t\tc.keyframe_insert('rotation_euler', 2)\n\t\t\tc.keyframe_insert('scale', 0)\n\t\t\tc.keyframe_insert('scale', 1)\n\ndef makeVectorTail(globV):\n\tmmesh = bpy.data.meshes.new('vectail')\n\tmmesh.vertices.add(2)\n\tmmesh.vertices[0].co = [0.0, 0.0, 0.0]\n\tmmesh.vertices[1].co = [6.0, 0.0, 0.0]\n\tmmesh.edges.add(1)\n\tmmesh.edges[0].vertices = [0,1]\n\tmmesh.update()\n\tomesh = bpy.data.objects.new('vectail', mmesh)\n\tscn.objects.link(omesh)\n\tomesh.parent = globV\n\tomesh.data = mmesh\n\tomesh.hide_render = True\n\n\tvecang, vecmag = getVectorAngle( \n\t\tglobV.vel[0], globV.vel[1], globV.vel[2], False)\n\n\tomesh.rotation_euler = [0.0, 0.0, vecang]\n\tomesh.scale = [vecmag, vecmag, 0]\n\ndef addVectorTails():\n\tfor obs in scn.objects:\n\t\tif obs.glob:\n\t\t\tif len(obs.children) &gt; 0:\n\t\t\t\tfor kid in obs.children:\n\t\t\t\t\ttry: scn.objects.unlink(kid)\n\t\t\t\t\texcept: print('i dont get unlinking...')\n\t\t\tmakeVectorTail(obs)\n\ndef removeObject(xob):\n\txmesh = xob.data\n\tscn.objects.unlink(xob)\n\ttry: bpy.data.objects.remove(xmesh)\n\texcept: print('---cannot remove ' + xmesh.name + '---')\n\ttry: bpy.data.objects.remove(ob)\n\texcept: print('---cannot remove ' + xob.name + '---')\n\ndef delSuns():\n\tfor xall in scn.objects:\n\t\tif xall.bhole:\n\t\t\tremoveObject(xall)\n\t\t\t#bpy.context.scene.objects.unlink(xall)\n\tselectCheck()\t\t\n\ndef delGlobs():\n\tfor xall in scn.objects:\n\t\tif xall.glob \n\t\tor xall.name[0:7] == 'vectail' \n\t\tor xall.name[0:8] == 'pathglob':\n\t\t\tremoveObject(xall)\n\tselectCheck()\t\t\t\t\t\n\ndef selectCheck():\n#-make sure there's an object active so panel doesn't disappear\n\tif scn.objects.active: return\n\telse:\n\t\tif len(scn.objects) &gt; 1:\n\t\t\tscn.objects.active = scn.objects[0]\n\t\telse:\n\t\t\tnewempty = bpy.ops.object.add()\n\t\t\tnewempty.hide = False\n\t\t\tnewempty.hide_select = False\n\t\t\tnewempty.hide_render = False\n\t\t\tscn.objects.link(newempty)\n\t\t\tscn.objects.active=newempty\n\n\"\"\"\ndef makeGlobIndex():\n\tGI = []\n\tobs = scn.objects\n\tfor ob in obs:\n\t\tif ob.glob:\n\t\t#or ob.name[0:len(SPREFIX)] == SPREFIX:\n\t\t\tGI.append(ob.name)\n\treturn GI\n\"\"\"\n\n######################### RUNLOOPS #########################\n\n#def runit(GI):\ndef runit():\n\tfor globA in scn.objects:\n\t\tif globA.glob:\n\t\t\t#print(globA.name, ' is a glob')\n\t#for i in range(0, len(GI)):\n\t\t#globA = obs[GI[i]]\n\t\t#globA = glob\n\t\t\tif globA.bhole: continue #-don't calc force on blackholes (immovable)\n\t\t\tif globA.merged: continue #-don't calc force on merged\n\n\t\t\tAx, Ay = globA.location[0], globA.location[1]\n\n\t\t\t\t### ??? ### add option for round cliploop?\n\t\t\t\t# check for CLIP (border)\n\t\t\tif sqrt(Ax*Ax+Ay*Ay) &gt; scn.CLIP:\n\t\t\t\tif scn.LOOPATCLIP:\n\t\t\t\t\t#-if loopatclip set, loop glob around\n\t\t\t\t\tif abs(Ax) &gt; scn.CLIP:\n\t\t\t\t\t\tglobA.location[0] = -Ax\n\t\t\t\t\tif abs(Ay) &gt; scn.CLIP:\n\t\t\t\t\t\tglobA.location[1] = -Ay\n\t\t\t\telse:\n\t\t\t\t\t#-otherwise stop and mark as merged so it'll be ignored\n\t\t\t\t\tglobA.merged = True\n\t\t\t\t\tcontinue\t#-skip to next globA loop if globA outside CLIP\n\n\t\t\t# temp loc, vel and acc vars for loop\n\t\t\ttloc = globA.location\n\t\t\ttvel = globA.vel\n\t\t\ttacc = [0.0, 0.0, 0.0]\n\n\t\t\t#for j in range(0, len(GI)):\n\t\t\tfor globB in scn.objects:\n\t\t\t\tif globB.glob:\n\t\t\t\t\tif globB == globA or globB.merged: continue\n\t\t\t\t\t#globB = obs[GI[j]]\n\t\t\t\t\t#globB = glob2\n\t\t\t\t\tBx, By = globB.location[0], globB.location[1]\n\t\t\t\t\tdx, dy = Bx - Ax, By - Ay\n\t\t\t\t\tdsq = dx*dx + dy*dy\n\t\t\t\t\t#if dsq==0:dsq=0.0001 #-I am such a hack...\n\t\t\t\t\tdr = sqrt(dsq)\n\t\t\t\t\t#ignore own force\n\t\t\t\t\tif dr &gt; scn.MAXINTERAD: continue #ignore if beyond interaction radius\n\n\t\t\t\t\t# add acceleration\/force from this glob\n\t\t\t\t\t#print(globA.name, ' has a problem with ', globB.name)\n\t\t\t\t\tforce = G * globA.tmass * globB.tmass \/ dsq\n\t\t\t\t\ttacc[0] += force*dx\/dr\n\t\t\t\t\ttacc[1] += force*dy\/dr\n\t\t\t\t\ttloc[0] += tvel[0] * scn.DAMP #DAMPVELx\n\t\t\t\t\ttloc[1] += tvel[1] * scn.DAMP #DAMPVELy\n\t\t\t\t\ttvel[0] += tacc[0] * scn.DAMP #DAMPACCx\n\t\t\t\t\ttvel[1] += tacc[1] * scn.DAMP #DAMPACCy\n\t\t\t\t\t###!!!maybe add a mock relativity here by\n\t\t\t\t\t#\t\tdamping acceleration as approaches v approaches c\n\n\t\t\t\t\t#-check if over max velocity, if so set to max\n\t\t\t\t\tif tvel[0] &gt; scn.MAXVEL: tvel[0] = scn.MAXVEL\n\t\t\t\t\tif tvel[0] &lt; -scn.MAXVEL: tvel[0] = -scn.MAXVEL\t \t\t\t\t\tif tvel[1] &gt; scn.MAXVEL: tvel[1] = scn.MAXVEL\n\t\t\t\t\tif tvel[1] &lt; -scn.MAXVEL: tvel[1] = -scn.MAXVEL\n\t\t\t\t\ttacc = [0.0, 0.0, 0.0]\n\n\t\t\t\t\t#-merge if close enough (relative to draw size - a cheat - I know)\n\t\t\t\t\tif dr &lt;= (globA.scale[0]+globB.scale[0])*scn.DSIZE: \t\t\t\t\t\tif scn.ACCRETE: \t\t\t\t\t\t\t#-they're close, merge smaller to larger \t\t\t\t\t\t\tif globA.tmass &gt;= globB.tmass:\n\n\t\t\t\t\t\t\t\tglobMerge(globB, globA)\n\t\t\t\t\t\t\telse:\n\n\t\t\t\t\t\t\t\tglobMerge(globA, globB)\n\t\t\t\t\t###!!!also add collision damping here based on density\n\t\t\t\t\t\tif scn.EXPLODE:\n\t\t\t\t\t\t\tvx1, vy1 = globA.vel[0], globA.vel[1]\n\t\t\t\t\t\t\tvx2, vy2 = globB.vel[0], globB.vel[1]\n\t\t\t\t\t\t\tvdx, vdy = vx2 = vx1, vy2 - vy1\n\t\t\t\t\t\t\tvdsq =vdx*vdx + vdy*vdy\n\t\t\t\t\t\t\tvdr = sqrt(vdsq)\n\t\t\t\t\t\t\tif abs(vdr) &gt; scn.EXTHRESH:\n\t\t\t\t\t\t\t\tif globA.tmass &gt;= globB.tmass:\n\t\t\t\t\t\t\t\t\tif globB.type != 'META':\n\t\t\t\t\t\t\t\t\t\taddExplosivo(globB, vdx, vdy)\n\t\t\t\t\t\t\t\telse:\n\t\t\t\t\t\t\t\t\tif globA.type != 'META':\n\t\t\t\t\t\t\t\t\t\taddExplosivo(globA, vdx, vdy)\n\n\t\t\t#update loc, vel, and insert kframes\n\t\t\t\tglobA.location[0] = tloc[0] #\/ scn.SPACEsSCALE\n\t\t\t\tglobA.location[1] = tloc[1] #\/ scn.SPACESsCALE\n\t\t\t\tglobA.vel = tvel\n\t\t\t#if globA.name[0:len(SPREFIX)] != SPREFIX:\n\t\t\t# ignore vectails of merged globs\n\t\t\tif globA.merged == False:\n\t\t\t\tglobA.keyframe_insert('tmass')\n\t\t\t\tglobA.keyframe_insert('merged')\n\t\t\tif globA.bhole == False:\n\t\t\t\tglobA.keyframe_insert('location', 0)\n\t\t\t\tglobA.keyframe_insert('location', 1)\n\t\t\t\tglobA.keyframe_insert('vel', 0)\n\t\t\t\tglobA.keyframe_insert('vel', 1)\n\t\t\t#-check if the glob has vectails, update if they exist\n\t\t\t\tfor c in globA.children:\n\t\t\t\t\tif c.name[0:7] == 'vectail':\n\t\t\t\t\t\tupdateTailFromVec(globA)\n\t\t\t\t\t\tcontinue\t# vectail updated, so leave loop\n\ndef loopit():\n\tt1 = time.ctime(time.time())\n\t#GI = makeGlobIndex()\n\tscn.frame_current = scn.STARTFRAME\n\t#-adjust for user changes to vectails\n\tupdateAllVecFromTail()\n\tsetCurvesToConstant()\n\t#-start on frame 2, 1st should NOT be recalculated\n\tfor f in range(scn.STARTFRAME+1, scn.STARTFRAME+scn.FRAMERUN):\n\t\tscn.frame_current = f\n\t\tprint(scn.frame_current)\n\t\t#runit(GI)\n\t\trunit()\n\tt2 = time.ctime(time.time())\n\t\t# calc processing time\n\ts1, m1 = int(t1[17:19]), int(t1[14:16])\n\ts2, m2 = int(t2[17:19]), int(t2[14:16])\n\tprint(str(t1)[11:20], str(t2)[11:20])\n\tprint('simulation time: ' + str(abs(m2-m1)) + ':' + str(abs(s2-s1)))\n\n###!!!ABSORB SOME IMPACT IN COLLISION!!!\n###\tTHESEARE NOT INDESTRUCTABLE...\n###\tALSO MAYBE ADD POTENTIAL FOR 'GLANCING BLOW'S and 'BOUNCES'\n###\tbecause for now w acrete and axplode off all collisions will pass thru\ndef globMerge(globS, globL):\n\tprint(globL.name, globL.tmass, '+', globL.tmass, globS.name)\n\t#if globS.bhole == 1: return\n\tglobS.merged = True\n\n\t#-make merged globs vectail disappear\n\tfor cs in globS.children:\n\t\tif cs.name[0:7] == 'vectail':\n\t\t\tcs.scale = [0.0, 0.0, 0.0]\n\t\t\tcs.keyframe_insert('scale', 0)\n\t\t\tcs.keyframe_insert('scale', 1)\n\n\t#-figure out vector between L and S to offset\n\t#\t\tconstraint of S on L as if stuck where hit\n\t#\t\talso to direct particles\/explode modifier\n\tSLx = globS.location[0] - globL.location[0]\n\tSLy = globS.location[1] - globL.location[1]\n\tif SLx &gt;= globL.scale[0]*scn.DSIZE: SLx = globL.scale[0]*scn.DSIZE\n\tif SLy &gt;= globL.scale[0]*scn.DSIZE: SLy = globL.scale[0]*scn.DSIZE\n\tif SLx &lt; -globL.scale[0]*scn.DSIZE: SLx = -globL.scale[0]*scn.DSIZE\n\tif SLy &lt; -globL.scale[0]*scn.DSIZE: SLy = -globL.scale[0]*scn.DSIZE\n\t#SLx = 1\t\t\t###!!! sun merging is still weird\n\t#SLy = 1\t\t\t\n\n\t#-contrain smaller glob to larger\n\tgcon = globS.constraints.new('COPY_LOCATION')\n\tgcon.use_offset = True\n\tgcon.target = globL\n\n\t#-add constraint influence keyframe of\n\t#\t\tpre-merge state to previous frame\n\tftemp = scn.frame_current\n\tscn.frame_current = ftemp - 1\n\tgcon.influence = 0\n\tgcon.keyframe_insert('influence')\n\n\t#-back to this frame to insert merged state keyframe\n\tscn.frame_current = ftemp\n\tgcon.influence = 1\n\tgcon.keyframe_insert('influence')\t\n\n\tglobS.location = [SLx, SLy, 0.0]\t\t\t\t\t\t  \n\n\t#-add keyframes for post-merge\n\t#\t\tlocation and constraint influence\n\tglobS.keyframe_insert('location', 0)\n\tglobS.keyframe_insert('location', 1)\t\t\t\t  \t\n\n\t# add velocity ofsmall glob to larger\n\t### ??? ### CHECK THIS, OBJECT VELS SEEM TO GOOF ON IMPACK\n\tnewvx = (globL.vel[0] * globL.tmass + \n\t\t\t\tglobS.vel[0] * globS.tmass) \/ \n\t\t\t\t(globL.tmass + globS.tmass)\n\tnewvy = (globL.vel[1] * globL.tmass + \n\t\t\t\tglobS.vel[1] * globS.tmass) \/ \n\t\t\t\t(globL.tmass + globS.tmass)\n\n\t#-update larger globs total mass and keyframe\n\n\tglobL.tmass += globS.tmass\n\tglobL.keyframe_insert('tmass')\n\tprint('mass updated : ', globL.name, globL.tmass)\n\tglobL.vel[0] = newvx\n\tglobL.vel[1] = newvy\n\ndef setCurvesToConstant():\n\tfor ob in scn.objects:\n\t\tif ob.glob:\n\t\t\toanim = ob.animation_data\n\t\t\tif oanim:\n\t\t\t\tocurves = oanim.action.fcurves\n\t\t\t\tfor ocurve in ocurves:\n\t\t\t\t\tocurve.extrapolation = 'CONSTANT'\n\n###analysis fxns\ndef calcTotalMassRemaing():\n\t#also how many last past 500 frames or so...\n\tpass\n\n######################### USER INTERFACE #########################\n\ndef initSceneProps(scn):\n\tbpy.types.Scene.FRAMERUN = bpy.props.IntProperty(\n\t\tname = \"framerun\")\n\tbpy.types.Scene.PARTICLES = bpy.props.IntProperty(\n\t\tname = \"particles\")\t\t  \n\n\tbpy.types.Scene.M = bpy.props.FloatProperty(\n\t\tname = \"earthmass\")\n\n\tbpy.types.Scene.T = bpy.props.FloatProperty(\n\t\t\tname = \"siderealyear\")\t\t\t\n\n\tbpy.types.Scene.WIDTH = bpy.props.IntProperty(\n\t\tname = \"width\")\n\tbpy.types.Scene.HEIGHT = bpy.props.IntProperty(\n\t\tname = \"height\")\n\tbpy.types.Scene.CLIP = bpy.props.IntProperty(\n\t\tname = \"clip\")\n\n\tbpy.types.Scene.DSIZE = bpy.props.FloatProperty(\n\t\tname = \"drawsize\")\n\t#bpy.types.Scene.SOLDIAM = bpy.props.FloatProperty(\n\t#\tname = \"earthdiameter\")\t\t  \n\n\tbpy.types.Scene.A = bpy.props.FloatProperty(\n\t\tname = \"spacespace\")\n\n\tbpy.types.Scene.SIZEVAR = bpy.props.FloatProperty(\n\t\tname = \"sizevar\")\n\tbpy.types.Scene.DAMP = bpy.props.FloatProperty(\n\t\tname = \"damp\")\n\n\tbpy.types.Scene.LOOPATCLIP = bpy.props.BoolProperty(\n\t\tname = \"loopatclip\")\n\tbpy.types.Scene.MAXVEL = bpy.props.FloatProperty(\n\t\tname = \"maxiumum velocity\")\n\tbpy.types.Scene.SOLDIAM = bpy.props.FloatProperty(\n\t\tname = \"sun radius\")\n\tbpy.types.Scene.SUNRANDLOC = bpy.props.BoolProperty(\n\t\tname = \"random sun location\")\n\n\tbpy.types.Scene.RANDVEL = bpy.props.BoolProperty(\n        name = \"random starting velocity\")\n\n\tbpy.types.Scene.STARTFRAME = bpy.props.IntProperty(\n\t\tname = \"startframe\")\t\t\n\n\tbpy.types.Scene.VECMULT = bpy.props.FloatProperty(\n\t\tname = \"vectordisplaymult\")\n\n\tbpy.types.Scene.MAXINTERAD = bpy.props.FloatProperty(\n\t\tname = \"maxinteractionradius\")\t\t\t\t\n\n\tbpy.types.Scene.RANDVELRANGE = bpy.props.FloatProperty(\n\t\tname = \"rendvelrange\")\t\n\n\tbpy.types.Scene.EXPLODE = bpy.props.BoolProperty(\n        name = \"explode on impact\")\n\n\tbpy.types.Scene.ACCRETE = bpy.props.BoolProperty(\n        name = \"accrete or not\")\n\n\tbpy.types.Scene.METABALLS = bpy.props.BoolProperty(\n        name = \"accrete or not\")\n\n\tbpy.types.Scene.EXTHRESH = bpy.props.FloatProperty(\n\t\t\tname = \"explodeimpacethreshold\")\t\n\n\tscn.LOOPATCLIP = LOOPATCLIP\n\tscn.FRAMERUN = FRAMERUN\n\tscn.PARTICLES = PARTICLES\n\tscn.M = M\n\tscn.T = T\n\tscn.WIDTH = WIDTH\n\tscn.HEIGHT = HEIGHT\n\tscn.CLIP = CLIP\n\tscn.DSIZE = DSIZE\n\t#scn.SOLDIAM = SOLDIAM\n\tscn.SIZEVAR = SIZEVAR\n\tscn.DAMP = DAMP\n\tscn.MAXVEL = MAXVEL\n\t#scn.SOLDIAM = SOLDIAM\n\tscn.SUNRANDLOC = SUNRANDLOC\n\n\tscn.RANDVEL = RANDVEL\n\n\tscn.STARTFRAME = STARTFRAME\n\tscn.RANDVELRANGE = RANDVELRANGE\n\n\tscn.MAXINTERAD = MAXINTERAD\n\tscn.EXTHRESH = EXTHRESH\n\tscn.A = A\n\n\tscn.VECMULT = VECMULT\n\tscn.ACCRETE = ACCRETE\n\tscn.EXPLODE = EXPLODE\n\tscn.METABALLS = METABALLS\n\ninitSceneProps(scn)\nbpy.types.Object.glob = bpy.props.BoolProperty(\n\tname = 'glob',\n\tdefault = False)\nbpy.types.Object.tmass = bpy.props.FloatProperty(\n\tname = 'total mass of object including others merged to it.',\n\tdefault = 0.0)\nbpy.types.Object.vel = bpy.props.FloatVectorProperty(\n\tname = 'velocity',\n\tdefault = (0.0, 0.0, 0.0))\nbpy.types.Object.merged = bpy.props.BoolProperty(\n\tname = 'merged',\n\tdefault = False)\nbpy.types.Object.bhole = bpy.props.BoolProperty(\n\tname = 'blackhole',\n\tdefault = False)\t\n\nclass OBJECT_PT_SOMPanel(bpy.types.Panel):\n\tbl_space_type = \"PROPERTIES\"\n\tbl_region_type = \"WINDOW\"\n\tbl_context = \"physics\"\n\tbl_label = \"Simple Orbital Mechanics\"\n\n\tdef draw_header(self, context):\n\t\tlayout = self.layout\n\n\tdef draw(self, context):\n\t\tlayout = self.layout\n\t\tscene = scn\n\t\trow1 = layout.row(align=True)\n\t\trow2 = layout.row(align=True)\n\n\t\tsplit1 = row1.split(percentage=0.5)\n\t\tcolX = split1.column()\n\t\tcolY = split1.column()\n\t\tsplit2 = row2.split(percentage=0.33)\n\t\tcolL = split2.column()\n\t\tcolM = split2.column()\n\t\tcolR = split2.column()\n\n\t\tcolX.label(text=\"2D Gravity\/Accretion Simulator\", icon='WORLD_DATA')\n\t\tltext1 = \t'vx: ' + str(scn.objects.active.vel[0])[0:9] + \n\t\t\t\t\t' | ' + \n\t\t\t\t\t'vy: ' + str(scn.objects.active.vel[1])[0:9]\n\t\tcolY.label(text=ltext1)\n\n\t\tcolX.label(text=scn.objects.active.name)\n\t\tcolY.label(text='scale: ' + str(scn.objects.active.scale[0]))\n\t\tltext2 =  'tmass: ' + str(scn.objects.active.tmass)[0:7]\n\t\tltext3 = 'merged: ' + str(scn.objects.active.merged)\n\t\tcolX.label(text=ltext3)\n\t\tcolY.label(text=ltext2)\n\t\tcolX.label(text='bhole: ' + str(scn.objects.active.bhole))\n\t\tcolY.label(text='')\n\n\t\tcolX.operator(\"create_globfield\")\n\t\tcolY.operator(\"delete_globfield\")\n\t\tcolX.label(text = '')\n\t\tcolY.operator(\"clear_animation\")\n\t\tcolX.operator(\"addVecTails\")\n\t\tcolY.operator(\"setVecTanToNearestSun\")\t\t\n\n\t\tcolX.prop(scene, 'RANDVEL', icon='BLENDER', toggle=True)\n\t\tcolY.prop(scene, 'LOOPATCLIP', icon='BLENDER', toggle=True)\n\t\tcolX.prop(scene, 'RANDVELRANGE', icon='BLENDER')#, toggle=True)\n\t\tcolY.prop(scene, 'VECMULT', icon='BLENDER')#, toggle=True)\t\t\n\n\t\tcolL.operator(\"animate_globfield\")\n\t\tcolM.prop(scene, 'FRAMERUN')\n\n\t\tcolR.prop(scene, 'STARTFRAME')\n\n\t\tcolL.prop(scene, 'WIDTH', icon='BLENDER')#, toggle=True)\n\t\tcolM.prop(scene, 'HEIGHT', icon='BLENDER')#, toggle=True)\n\t\tcolR.prop(scene, 'CLIP', icon='BLENDER')#, toggle=True)\n\n\t\tcolL.separator()\n\t\tcolM.separator()\n\t\tcolR.separator()\t\t\t\t\n\n\t\tcolL.prop(scene, 'PARTICLES', icon='BLENDER')#, toggle=True)\n\t\tcolM.prop(scene, 'MAXINTERAD', icon='BLENDER')#, toggle=True)\n\t\tcolR.prop(scene, 'SIZEVAR', icon='BLENDER')#, toggle=True)\n\n\t\tcolL.label(text='')\n\t\tcolM.prop(scene, 'DSIZE', icon='BLENDER')#, toggle=True)\n\t\t#colR.prop(scene, 'SOLDIAM', icon='BLENDER')#, toggle=True)\t\t\n\n\t\tcolL.separator()\n\t\tcolM.separator()\n\t\tcolR.separator()\n\n\t\tcolL.prop(scene, 'DAMP', icon='BLENDER')#, toggle=True, expand=False)\n\t\t#colM.prop(scene, 'GRAVITY', icon='BLENDER')#, toggle=True)\n\t\tcolR.prop(scene, 'MAXVEL', icon='BLENDER')#, toggle=True)\t\t\t\t\t \t\t\t\t\t\t\n\n\t\tsunBox = colL.box()\n\t\tsunBox.label(text = \"Sun\/Blackhole\")\n\t\tsunBox.operator(\"create_sunhole\")\n\t\tsunBox.operator(\"delete_sunholes\")\n\t\tsunBox.prop(scene, 'SOLDIAM', icon='BLENDER')#, toggle=True)\n\t\tsunBox.prop(scene, 'SUNRANDLOC', icon='BLENDER', toggle=True)\n\t\t#sunBox.prop(scene, 'SUNsDSIZE', icon='BLENDER')#, toggle=True)\t\t\n\n\t\t#colM.template_curve_mapping(scene, 'mycurve', type='VECTOR')\n\t\t#colR.template_reports_banner()\n\t\t# these would be nice, also remember to useevent = true on props\n\t\tcolM.prop(scene, 'EXTHRESH', icon='BLENDER', toggle=True)\n\t\tcolR.prop(scene, 'A', icon='BLENDER')#, toggle=True)\n\n\t\tcolM.operator('createMeshPath')\n\t\tcolM.operator('testit3')\n\t\t#colR.label(text='')\t\t\t\n\n\t\tcolM.label(text='')\n\t\tcolR.label(text='')\t\n\n\t\tcolM.operator('testit')\n\t\tcolR.operator('testit2')\n\t\tcolM.prop(scene, 'EXPLODE', icon='BLENDER', toggle=True)\n\t\tcolR.prop(scene, 'ACCRETE', icon='BLENDER', toggle=True)\t\t\t\t\n\n\t\t#colM.prop(scene, 'TESTCOLLECT', icon='BLENDER', toggle=True)\n\t\t#colR.menu('amenu', 'irmanu')\n\n\t\t#colM.prop_enum(scene, 'TESTMENU', 't')\n\t\t#colM.prop_enum(scene, 'TESTMENU', 't')\t\t\n\nclass SCENE_OT_testit3(bpy.types.Operator):\n\tbl_idname = \"testit3\"\n\tbl_label = \"testit3\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"testit3\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---trying blah---')\n\t\t#tob = scn.objects.active\n\t\t#print(tob.name)\n\t\t#createMetaBall()\n\t\tsetCurvesToConstant()\n\t\treturn(\"FINISHED\")\n\nclass SCENE_OT_testit(bpy.types.Operator):\n\tbl_idname = \"testit\"\n\tbl_label = \"testit\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"testit\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---trying to create a metaglob---')\n\t\tcreateSolSystem()\n\t\treturn(\"FINISHED\")\n\nclass SCENE_OT_testit2(bpy.types.Operator):\n\tbl_idname = \"testit2\"\n\tbl_label = \"testit2FLUSH\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"testit2\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---testit2---')\n\t\tflush()\n\t\t#tob = scn.objects.active\n\t\t#print(tob.name)\n\t\t#createMetaBall()\n\t\treturn(\"FINISHED\")\t\n\nclass SCENE_OT_createMeshPath(bpy.types.Operator):\n\tbl_idname = \"createMeshPath\"\n\tbl_label = \"createMeshPath\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"create mesh ribbon from glob paths\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---watch it grow---')\n\t\tcreateMeshPath()\n\t\treturn(\"FINISHED\") \n\nclass SCENE_OT_setVecTanToNearestSun(bpy.types.Operator):\n\tbl_idname = \"setVecTanToNearestSun\"\n\tbl_label = \"setVectorTangentToSuns\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"set vectors tangent to their nearest sun\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---turn away from the light---')\n\t\tsetVecTangentToNearestHole()\n\t\treturn(\"FINISHED\")\t\t\t\n\nclass SCENE_OT_addVecTails(bpy.types.Operator):\n\tbl_idname = \"addVecTails\"\n\tbl_label = \"addVectorTails\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"add\/update vector tails to globs\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---youve got tails!---')\n\t\taddVectorTails()\n\t\treturn(\"FINISHED\")\t\t\t\n\nclass SCENE_OT_delete_sunholes(bpy.types.Operator):\n\tbl_idname = \"delete_sunholes\"\n\tbl_label = \"deleteSunHoles\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"remove all suns\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---goodbye norma jean---')\n\t\tdelSuns()\n\t\treturn(\"FINISHED\")\t\t\n\nclass SCENE_OT_create_globfield(bpy.types.Operator):\n\tbl_idname = \"clear_animation\"\n\tbl_label = \"clearAnimation\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"clear all animation data\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---be gone animation data!---')\n\t\tclearAnimation()\n\t\treturn(\"FINISHED\")\t\n\nclass SCENE_OT_create_sunhole(bpy.types.Operator):\n\tbl_idname = \"create_sunhole\"\n\tbl_label = \"createSunHole\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"create a Sun\/Blackhole type stationary gravity well\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---mmm... matter---')\n\t\tmakeSunHole()\n\t\treturn(\"FINISHED\")\n\nclass SCENE_OT_create_globfield(bpy.types.Operator):\n\tbl_idname = \"create_globfield\"\n\tbl_label = \"createGlobs\"\n\tbl_options = {'REGISTER'}\n\tbl_description = \"create a field of globs based on parameters\"\n\n\tdef invoke(self, context, event):\n\t\tprint('---let there be globs---')\n\t\tmakeGlobField()\n\t\treturn(\"FINISHED\")\n\nclass SCENE_OT_delete_globfield(bpy.types.Operator):\n\tbl_idname = \"delete_globfield\"\n\tbl_label = \"deleteGlobs\"\n\tbl_description = \"delete all globs\"\n\tbl_options = {'REGISTER', 'UNDO'}\n\n\tdef invoke(self, context, event):\n\t\tprint('---destroy all globs---')\n\t\tdelGlobs()\n\t\treturn{'FINISHED'}\n\nclass SCENE_OT_animate_globfield(bpy.types.Operator):\n\tbl_idname = \"animate_globfield\"\n\tbl_label = \"animateGlobs\"\n\tbl_description = \"gravitometicically animateify globjects\"\n\tbl_options = {'REGISTER', 'UNDO'}\n\n\tdef invoke(self, context, event):\n\t\tprint('---i am busy calculating glob animations---')\n\t\tloopit()\n\t\tbpy.context.scene.frame_current = STARTFRAME\n\t\treturn{'FINISHED'}\t \n\ndef register():\n\tbpy.types.Scene.some_strvar = bpy.props.StringProperty(\n\t\tname='some_strvar',\n\t\tdescription='a string variable i might need')\n\ndef unregister():\n\tdel bpy.types.Scene.some_strvar\n\nif __name__ == \"__main__\":\n    register()\n\n##########    DROPDOWN BOX \/ MENU\n\"\"\"\nclass RENDER_PT_matdropdown(bpy.types.Panel):\n    bl_space_type = \"PROPERTIES\"\n    bl_region_type = \"WINDOW\"\n    bl_context = \"render\"\n    bl_label = \"Material Dropdown lists\"\n\n    def draw(self, context):\n        rd = context.scene\n        layout = self.layout\n        layout.prop(rd, \"mat_list_old\", text=\"Replace\")\n        layout.prop(rd, \"mat_list_new\", text=\"by\")\n        layout.separator()\n        row = layout.row()\n        row.operator(\"custom.update_materiallists\")\n        row.operator(\"custom.print_materials\")\n\ndef replace():\n    MATERIALS = []\n    for i in range(len(bpy.data.materials)):\n        MATERIALS.append((str(i), bpy.data.materials[i].name, str(i)))\n\n    bpy.types.Scene.EnumProperty( attr=\"mat_list_old\",\n        name=\"Replace\",\n        description=\"Choose a material to be replaced\",\n        items = MATERIALS, default = '0')\n    bpy.types.Scene.EnumProperty( attr=\"mat_list_new\",\n        name=\"Replace by\",\n        description=\"Choose a replacement material\",\n        items = MATERIALS, default = '1')    \n\nclass CUSTOM_OT_update_materiallists(bpy.types.Operator):\n    bl_idname = \"CUSTOM_OT_update_materiallists\"\n    bl_label = \"Update\"\n    bl_description = \"Update the dropdown boxes. Necessary if you added or deleted materials in the scene.\"\n\n    def invoke(self, context, event):\n        replace()\n        return{'FINISHED'}\n\nclass CUSTOM_OT_print_materials(bpy.types.Operator):\n    bl_idname = \"CUSTOM_OT_print_materials\"\n    bl_label = \"Print\"\n    bl_description = \"Print the selections of the dropdown boxes.\"\n    def invoke(self, context, event):\n        old = bpy.data.materials[int(bpy.context.scene.mat_list_old)]\n        new = bpy.data.materials[int(bpy.context.scene.mat_list_new)]\n        print(\"Replace\",old.name,\"by\",new.name)\n        return{'FINISHED'}\n\nif __name__ == '__main__':\n    bpy.types.register(CUSTOM_OT_update_materiallists)\n    bpy.types.register(CUSTOM_OT_print_materials)\n    replace()\n    bpy.types.register(RENDER_PT_matdropdown)\n\"\"\"<\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s on the back burner for right now. Anyway it works if you feel like playing with it. Features: -2d <a href='http:\/\/funkboxing.com\/wordpress\/?p=41' class='excerpt-more'>[&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,5,47],"tags":[28],"_links":{"self":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/41"}],"collection":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=41"}],"version-history":[{"count":2,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/41\/revisions"}],"predecessor-version":[{"id":2725,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/41\/revisions\/2725"}],"wp:attachment":[{"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=41"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=41"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/funkboxing.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=41"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}