Skip to content

Instantly share code, notes, and snippets.

@ricardocchaves
Last active August 23, 2020 06:30
Show Gist options
  • Save ricardocchaves/789c377c0ef3330066a9e2444d3bf2a2 to your computer and use it in GitHub Desktop.
Save ricardocchaves/789c377c0ef3330066a9e2444d3bf2a2 to your computer and use it in GitHub Desktop.
Blender - An empty acts as a "force field" towards a group of objects.
import bpy
import mathutils
from random import randint
def my_handler(scene):
# I couldn't register a class as handler or use global variables
# so I'm using hidden empties as global variables to store the
# previous positions when required.
old_loc_name = "old_empty"
if old_loc_name not in bpy.data.objects:
print("Creating new")
o = bpy.data.objects.new(old_loc_name,None)
# Uncomment if you want the empty to appear
# in your scene manager. By default it's commented
# to prevent it from becoming too cluttered.
#bpy.context.scene.collection.objects.link(o)
old_loc = bpy.data.objects[old_loc_name].location
target = bpy.data.objects["Empty"].location # Get target's location
bpy.data.objects[old_loc_name].location = target
# Empty position changed
# Check cubes to update them
distance = 5
move_inc = 0.3
noise_factor = 0.4
# Noise vector
noise_vec = mathutils.Vector((randint(-1000,1000)/1000,randint(-1000,1000)/1000,randint(-1000,1000)/1000))*1
# Affects every object that is a MESH and has 'Cube' in the name
for cube in [x for x in bpy.data.objects if 'Cube' in x.name and x.type=="MESH"]:
t_vec = cube.location-target
origin_name = cube.name+"_origin"
# Get the original position of this cube
# or create a new empty for it if it doesn't already exist
if origin_name not in bpy.data.objects:
o = bpy.data.objects.new(origin_name,None)
o.location = cube.location
# Uncomment if you want the empty to appear
# in your scene manager. By default it's commented
# to prevent it from becoming too cluttered.
#bpy.context.scene.collection.objects.link(o)
else:
o = bpy.data.objects[origin_name]
o_vec = cube.location-o.location
# If cube is in range of target, move to the opposite direction
# else try to return to origins
if t_vec.length < distance:
t_vec_n = mathutils.Vector.normalized(t_vec)
# Noise shift
n_vec = (mathutils.Vector.orthogonal(t_vec_n)+noise_vec)*noise_factor
cube.location += t_vec_n*move_inc+n_vec
else:
if o_vec.length > move_inc:
o_vec_n = -mathutils.Vector.normalized(o_vec)*move_inc
cube.location += o_vec_n
# Uncomment this if you need to clear every the cube's origins
"""
for o in bpy.data.objects:
if '_origin' in o.name:
bpy.data.objects.remove(o)
"""
bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_pre.append(my_handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment