2
$\begingroup$

I have a 3x3x3 grid of objects in a collection (intended to be used with non-duplicate objects), I want to sort them by x y and z and have them fed into a loop and animate transformations. I previously did this with index id keys and 3 sort list nodes; one for each axis fed through each other. but the sort list node has since been removed hence why I'm stuck.

I've tried separating the list vectors, running them each through an expression node with sorted(e) but but I'm stuck at how to take X list and sort it by Y, and then Y by Z. any solution or help is greatly appreciated :)

Download my .blend

this is all working except it lacks the control im looking for as to what axis and direction the process begins with

enter image description here

rather than it going from left to right, I want the control to set it so the order is back to front, and then upwards

EDIT: after many hours of tweaking i finally came to a solution using the expressions given to me by gorgious and some extra tweaks:

nodes

I used gorgious's method nearly exactly but before feeding the object list into the expression nodes, I created 3 sets of id keys for each axis, input them with object id key nodes, combined them into a vector list and output them into an object transforms output node. the result is full control over direction of animation.

$\endgroup$
2
$\begingroup$

I think you almost got it. I initially started designing loop subprograms but the sorted method and the expression nodes are your friends.

Remember you can chain expression nodes. Add an input of type "Object List"

The 3 expression nodes you should write are like so :

enter image description here

The 3 lines of code:

sorted(objs,key=lambda obj:obj.location[0])
sorted(objs,key=lambda obj:obj.location[1])
sorted(objs,key=lambda obj:obj.location[2])

To visualize it, create a loop subprogram to change the viewport color of the object depending on their order in the new, sorted list.

enter image description here

Add the subprogram at the end of your expression nodes :

enter image description here

Result :

enter image description here

Additionally, as a stand-alone python script :

import bpy

objs = bpy.data.objects; # Replace by relevant objects or collection
for axis in (0, 1, 2):
    objs = sorted(objs, key=lambda obj: obj.location[axis])

objs_len = len(objs)
for i, obj in enumerate(objs):
    fac = i / objs_len
    obj.color = (fac, 1 - fac, 0, 1)

Edit after comment asking for another way to sort the list (right to left, back to front, bottom to top)

You just have to add a slice operator at the end of the 2 first expression nodes to reverse the list : [::-1] See this doc for example (example 2)

So the expressions become :

sorted(objs,key=lambda obj:obj.location[0])[::-1]
sorted(objs,key=lambda obj:obj.location[1])[::-1]
sorted(objs,key=lambda obj:obj.location[2])

Result :

enter image description here

$\endgroup$
2
  • $\begingroup$ is there any way to use this method but with more control over what direction the sorting starts with? ie starting with +y +x and -z (bottom of structure) then building along the x axis, completing a row then progressing down the y axis, once theres no objects left along Z then moving up a slice if that makes sense $\endgroup$ Aug 31 '20 at 23:28
  • $\begingroup$ See my edit at the end of the answer, you can use [::-1] to reverse a list. I did not fully understand the order in which you want things to appear but also know that you can rearrange the expression nodes to rearrange the sorting. With these informations you should be able to do it $\endgroup$
    – Gorgious
    Sep 1 '20 at 6:46
1
$\begingroup$

AN have Sort Numbers node.You can use that to sort any number list, for example sort x list of vectors by its y list. enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.