So I'm trying to animate a rubiks cube via a python script using the scripting capabilities given with Blender.
My current cube looks like this:
It consists of 27 separate objects (cubelets) that are organized in a collection like this:
Initially the locations of the individual cubelets were not applied and so I could select all cubelets of a given side by sorting the objects of the collection by the corresponding location and reversing the resulting list if necessary:
def cubeletsBySide(cube, side):
dimensionsBySide = {'U': 2, 'D': 2, 'F': 1, 'B': 1, 'R': 0, 'L': 0}
revertBySide = {'U': True, 'D': False, 'F': True, 'B': False, 'R': False, 'L': True}
dimension = dimensionsBySide[side]
return sorted(
list(cube.all_objects.values()),
key=lambda c: c.location[dimension],
reverse=revertBySide[side])[:9]
After some initial trouble with animating the cube I found a tutorial that helped me in animating a cube by hand. However it seems the right thing to do to apply the locations and set the origins of the individual cubelets to the same common point (the 3D cursor in this case).
While this works when animating the cube manually I can now no longer use the location to reliably sort cubelets. I pondered the idea of attaching custom properties to these objects, but that would imply that I also need to update this data whenever rotating some cubelets. To my mind there is a certain beauty in not needing to keep track of redundant data here and just selecting the desired objects at will. I also looked trough other object properties in the hope that I could find something to sort the cubelets by but had no luck with that.
Simply stated: I desire some sort of property or mechanism to compare objects in a given world location independently of their origins so that I can find the required cubelets independently of previously executed rotations.
For completion here's the code I currently use to rotate a side of the cube that makes use of the cubeletsBySide
function:
def rotateSide(cube, side, angle):
axisBySide = {'U': 'Z', 'D': 'Z', 'F': 'Y', 'B': 'Y', 'R': 'X', 'L': 'X'}
override = bpy.context.copy()
override['selected_objects'] = cubeletsBySide(cube, side)
bpy.ops.transform.rotate(override, value=angle, orient_axis=axisBySide[side])
I'd be grateful for any pointers on this 🙏.
o
I might be able to use theo.data.vertices
for this. TheMeshVertex.co
property seems to hold 3 coordinates, and since cubelets form quite the grid I could maybe just sort using the first of them not worrying about looping trough all or computing in a more complex fashion. $\endgroup$