2
$\begingroup$

I want to run this script and have it pick up references the four pre-existing "my_xxx" objects, so that the script can then operate on them. However, all four variables end up referring to my_Sun, and it is the only object that moves.

Question: I would like to understand why this isn't working the way I expect, am I missing something obvious?

Question: What is the correct way to assign python variables to pre-existing objects based on name, if this isn't right?

import bpy

bpy.ops.object.select_all(action="DESELECT")

bpy.ops.object.select_pattern(pattern="my_Cube")
cube = bpy.context.active_object
bpy.ops.object.select_all(action="DESELECT")

bpy.ops.object.select_pattern(pattern="my_Cone")
cone = bpy.context.active_object
bpy.ops.object.select_all(action="DESELECT")

bpy.ops.object.select_pattern(pattern="my_Suzanne")
monkey = bpy.context.active_object
bpy.ops.object.select_all(action="DESELECT")

bpy.ops.object.select_pattern(pattern="my_Sun")
sun = bpy.context.active_object
bpy.ops.object.select_all(action="DESELECT")

print ("monkey.name: ", monkey.name)
print ("cone.name :  ", cone.name)
print ("cube.name:   ", cube.name)
print ("sun.name:    ", sun.name)

monkey.location = 5,5,5  # note to self: use "location" not "position" !!!
cone.location   = 5,5,5
cube.location   = 5,5,5
sun.location    = 5,5,5

Output to terminal:

monkey.name:  my_Sun
cone.name :   my_Sun
cube.name:    my_Sun
sun.name:     my_Sun

RESULTS: Only sun is moved to new location 5, 5, 5

four things gif four things list

$\endgroup$
5
$\begingroup$

The script is setting the location of whatever object is active when the script is run.

bpy.ops.object.select_pattern(pattern="my_Cube")

assigns to the context selected objects list. This is the list of all objects in the scene whose select property is true (obj.select). Using "my_" as a search string for the op would select all your "my_" objects. The operator setting one as active is somewhat meaningless. Use

monkey = bpy.context.selected_objects[0]

to assign the first of the selected objects list, after running that operator.

The context active object, is best set using

scene.objects.active = obj

after running an operator that sets active object.

Suggest replacing all the annoying operators with API calls something akin to:

import bpy

context = bpy.context
scene = context.scene

for name in ["Cube", "Cone", "Lamp", "Suzanne"]: # not a my_ fan 8^)
    obj = scene.objects.get(name)
    if obj:
        obj.location = (5, 5, 5)
$\endgroup$
  • $\begingroup$ Thanks! The script is a minimal demonstration. I am trying to select one pre-existing object at a time though it's unique name (e.g. "my_Cone") by making it the active object (of which there can only be one I think) then give the active object a new reference such as cone. Then I am thinking I clear all selection with bpy.ops.object.select_all(action="DESELECT") and then make the next object the active object. Thus the second part of the question "What is the correct way to assign python variables to pre-existing objects based on name...?" $\endgroup$ – uhoh Mar 17 '16 at 10:14
  • $\begingroup$ The prints and obj.location assignments are just to demonstrate that what I am trying to do is not working. I'll fix the "position" - I'm trying to integrate with Skyfield where obj.location is called obj.position(), and when I retyped the line during cleanup (delete other debugging lines) I must have crossed wires. $\endgroup$ – uhoh Mar 17 '16 at 10:20
  • 2
    $\begingroup$ As suggested use objects.get(name) where objects is one of the objects collection bpy.data.objects (all in fle) scene.objects (all in scene) or it returns None if there is no object with name name. To make it the active object use 'scene.objects.active = scene.objects.get("my_Doughnut")` Which is my answer again really. $\endgroup$ – batFINGER Mar 17 '16 at 10:20
  • $\begingroup$ Thanks for spelling it out for me! OK that looks quite straightforward. In the past I've always used bpy.context.active_object - is that less reliable? Is it causing trouble here? $\endgroup$ – uhoh Mar 17 '16 at 10:29
  • 1
    $\begingroup$ No, the select pattern operator merely sets obj.select to True if its name matches, which makes it a member of context.selected_objects. It doesn't assign an "active" object. What object should be active if i call `bpy.ops.object.select_pattern("*") ? $\endgroup$ – batFINGER Mar 17 '16 at 10:31
2
$\begingroup$

Here's a compact version of batFINGER's answer:

obj = bpy.data.objects.get(name)

Also, part of the failure of the script from the poster is that it fails to understand that there is a difference between

  • the one "active" object bpy.context.active_object or bpy.context.scene.objects.active (the first is read-only, the second is read/write)

and

  • the set of selected objects [o for o in bpy.data.objects if o.select]
$\endgroup$
  • $\begingroup$ Thank you for that! Yes, my scripts always have a hard time understanding things. Often I do too. I'm always grateful to live in a time when stackexchange puts me in contact with understanding people. $\endgroup$ – uhoh Mar 17 '16 at 16:01

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.