2

I found this code I want to use:

from mathutils import Vector
direction = Vector(your_tuple)
your_object.rotation_mode = 'QUATERNION'
your_object.rotation_quaternion = direction.to_track_quat('Z','Y')

It says your_object. I tried to use Area.001.rotation_mode = 'QUATERNION' but it doesn't work. In that case my object is a area light. How can I transform the code to be able to use it with the area light from my scene ?

Marty Fouts
  • 33,070
  • 10
  • 35
  • 79
  • 1
    Object reference e.g. object in context: C.object or via scene C.scene.object.get("Cube"). Suggest use the python console to figure out: https://docs.blender.org/manual/en/latest/editors/python_console.html – brockmann Sep 25 '21 at 13:03
  • I tried to use the console. The only output I get is bpy.ops.outliner.item_activate(extend=False, deselect_all=True) – Dirk Schiller Sep 25 '21 at 13:06
  • 1
    Thanks brockmann! – Dirk Schiller Sep 25 '21 at 13:11
  • When I enter C.scene.object.get("Area.001") and hit enter I get this error: Traceback (most recent call last): File "<blender_console>", line 1, in <module> AttributeError: 'Scene' object has no attribute 'object' – Dirk Schiller Sep 25 '21 at 13:13
  • Seems I can accept the answer in at least two days. – Dirk Schiller Sep 25 '21 at 13:14

2 Answers2

4

It's advisable to access objects via context members (bpy.context) since most of the available functions a.k.a operators as well as entire UI is based on the current context by design. You can either use C.object, C.active_object (both are interchangeable) or access all selected objects using C.selected_objects. Make sure the object is selected in the viewport/outliner and use the python console to figure out:

>>> C.object
bpy.data.objects['Cube']

>>> C.object.rotation_mode # get the rotation mode 'XYZ'

>>> C.object.rotation_mode = 'QUATERNION' # set the rotation mode ...

Based on that knowledge, it should be pretty straight forward to adapt the given script:

import bpy
from mathutils import Vector

C = bpy.context obj = C.object

direction = Vector((1.0, 0.0, 0.0)) obj.rotation_mode = 'QUATERNION' obj.rotation_quaternion = direction.to_track_quat('Z','Y')


If you'd like to access objects by their name, best practice to get the actual object reference is using pythons get() on Scene.objects collection. Using the index operator [] on Scene.objects collection would raise a KeyError if the key is missing however (object name or index in this case). I'd suggest use the python console to figure out:

>>> C.scene.objects.get("Cube")
bpy.data.objects['Cube'] # object reference

>>> C.scene.objects["Cube1"] Traceback (most recent call last): File "<blender_console>", line 1, in <module> KeyError: 'bpy_prop_collection[key]: key "Cube1" not found'

>>> C.scene.objects.get("Cube1", False) # get allows to provide a default value False

See: Why dict.get(key) instead of dict[key]?

>>> obj = C.scene.objects.get("Cube")
>>> obj
bpy.data.objects['Cube']
>>> obj.rotation_mode
'XYZ'

Based on that knowledge, it should be pretty straight forward to adapt the given script:

import bpy
from mathutils import Vector

C = bpy.context obj = C.scene.objects.get("Cube")

if obj: direction = Vector((1.0,0.0,0.0)) obj.rotation_mode = 'QUATERNION' obj.rotation_quaternion = direction.to_track_quat('Z','Y')

You can also use get() on the object data-block of the current file D.objects.get("Cube"). However, might lead into potential context issues if eg. the object you're trying to access is no part of the current scene.

Related:

brockmann
  • 12,613
  • 4
  • 50
  • 93
  • 1
    I'm not sure how using get is best practice, since in the OP's case, if the object isn't in objects he's going to trigger an AttributeError on the attempt to use rotation_mode. ISTM that best practice is to handle the error where it occurs. I suppose it's a dogmatic thing whether using a try block or testing the return value of get is better, but best practice would be to check the result in either case. – Marty Fouts Sep 25 '21 at 16:17
  • 1
    The reason is simple: Scene.objects collection supports it so there is no reason not using get(), see the linked stackoverflow post @MartyFouts – brockmann Sep 25 '21 at 16:55
  • @batFinger is suggesting using the active object to avoid the dictionary lookup altogether. I think that's a better approach as well, although it doesn't eliminate the error possibility of there being no active object when you run the script. You really cannot robustly avoid dealing with the possibility that the script will be attempted when there's no object for it to operate on. – Marty Fouts Sep 26 '21 at 15:15
  • @brockmann If you look carefully at the answer with 200 score to the stackoverflow question you posted, it specifically states that there are times when you should not use get. See my best practices comment in my answer for a quick summary; but they mention cases like this question: dont' use get when a default result won't do. – Marty Fouts Sep 26 '21 at 15:32
  • PEP8 does not advise against the use of try/except blocks. It even has a long section on how to create Exceptions and use them. It recommends against using using of try/except in performance sensitive situations. No, the exception can't be wrong, because exceptions are raised in the order generated. – Marty Fouts Sep 26 '21 at 15:44
1

I found the solutions:

from mathutils import Vector
direction = Vector([-1.0, 0.02, 0.1])
bpy.context.scene.objects[1].rotation_mode = 'QUATERNION'
bpy.context.scene.objects[1].rotation_quaternion = direction.to_track_quat('Z','Y')