2
$\begingroup$

I would like to create an automatic list of the objects that have been selected with the mouse click. So for example I have cube1, cube2, cube3, cube4.

I select them in the following order cube3, cube2, cube4, cube1 then a list on a text file shoud be generated in the order that they have been selected 3,2,4,1.

$\endgroup$
4
$\begingroup$

So the answer to this question is not as straight forward as you would expect. Blender is not storing the selection order for objects. It only stores the active object and a sorted list of all other objects. So what you really need is a way to catch all selection events. One way to do that is using a modal operator like this:

import bpy

class OBJECT_OT_record_selection(bpy.types.Operator):
    """Records the selection order while running and when finished with ESC saves it to //order.txt"""
    bl_idname = "object.record_selection"
    bl_label = "Record Selection"

    origSel: None
    selOrder: None

    @classmethod
    def poll(cls, context):
        return context.mode == 'OBJECT'

    def modal(self, context, event):
        # Update selection
        curSel = context.object

        # On selecting new object
        if curSel is not self.origSel:
            self.report({'INFO'}, 'Selection was changed')
            self.origSel = curSel
            self.selOrder.append(context.object)
        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            # Use this to save to an internal text data block
            if "order.txt" not in bpy.data.texts:
                bpy.data.texts.new("order.txt")
            bpy.data.texts["order.txt"].clear()
            bpy.data.texts["order.txt"].write('\n'.join([obj.name for obj in self.selOrder]))
            
            # Use this for saving to a text file
            #try:
            #    with open(bpy.path.abspath("//order.txt"), 'w+') as f:
            #        for obj in self.selOrder:
            #            f.write("%s\n" % obj.name)
            #    self.report({'INFO'}, 'Saved order to file at ./order.txt')
            #except Exception:
            #    self.report({'ERROR'}, 'Error while writing to file at ./order.txt')
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        self.origSel = context.object
        self.selOrder = []
        if context.object is not None:
            self.selOrder.append(context.object)
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


def add_object_button(self, context):
    self.layout.operator(
        OBJECT_OT_record_selection.bl_idname,
        text="Record Selection",
        icon='RESTRICT_SELECT_OFF')


def register():
    bpy.utils.register_class(OBJECT_OT_record_selection)
    bpy.types.VIEW3D_MT_select_object.append(add_object_button)


def unregister():
    bpy.utils.unregister_class(OBJECT_OT_record_selection)
    bpy.types.VIEW3D_MT_select_object.remove(add_object_button)


if __name__ == "__main__":
    register()
$\endgroup$
11
  • $\begingroup$ Hello, I've tried the script in 2.8 and is not working. How should I use it? $\endgroup$ – Andy Andy Jun 27 '20 at 15:42
  • $\begingroup$ did you copy the accidental marks in the last row? (I just removed them) It should work by opening it in a blender text editor and pressing "Run Script" Then it should make the modal operator available in the search menu and in Viewport > Select > Record Selection $\endgroup$ – HenrikD Jun 27 '20 at 15:49
  • $\begingroup$ Can confirm that the script works fine. $\endgroup$ – brockmann Jun 27 '20 at 15:53
  • $\begingroup$ Thank you @HenrikD, is perfect. Can I use it in my add-on? $\endgroup$ – Andy Andy Jun 27 '20 at 15:58
  • $\begingroup$ sure thing. How is it called? $\endgroup$ – HenrikD Jun 27 '20 at 15:58

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.