I am new to Blender and Python. I wanted to see if there is a way to grab the rotation value of an object and show it as text. I am trying to export this as a 3D model to other software, so I am also wondering if I export it as a FBX will the numbers still show up as changing.
-
$\begingroup$ Hello ! I can definitely say that the answer to the last part of your question is no. Can you elaborate a bit on your setup ? Do you want the 3D text to change dynamically when the object rotation changes ? Does the object rotation change with user input or via code ? $\endgroup$– GorgiousFeb 16 at 16:20
-
$\begingroup$ @Gorgious I am wanting the 3D text to change dynamically when the object rotation changes. So when the rotation is 50 I want the text to say that the rotation is 50. when its 61 the text to say 61 and so on. As of right now the object rotation changes by using the keyframe animation. $\endgroup$– Sean MartinFeb 16 at 16:28
1 Answer
TL;DR
If you want to get something in Python written in a 3D Text in your scene, see:
How can I make dynamic text in an animation? - Blender Stack Exchange
You can get an object's euler rotation via:
bpy.data.objects["NAME OF OBJECT"].rotation_euler
Short introduction to Python and Blender's API and how to discover it by yourself
Let's switch to the scripting workspace to make some experiments:
When you want to get a value as python, all you have to do is RMB it and click Copy Full Data Path
:
Then, to test it out, you can paste it into Blender's Python Console:
>>> bpy.data.objects["Cube"].rotation_euler[1]
0.0
The line with >>>
is a command you entered, and the line after that is what Blender returned as value.
Think of the dots in a command like the /
in a file path. Each "folder" may contain data that you can querry or edit, or other "folders".
Let's decompose that command:
bpy.data.objects["Cube"]
point to the data of the object named "Cube"..rotation_euler
gets its Euler rotation (objects have different rotation systems with different coordinates, so you have to indicate which one you want to access). The different axes values are stored as a list, so you can either get all the values at once from there, or you can ask for a specific element of the list like bellow:[1]
gets you the second value within the list of values contained inrotation_euler
. Counting starts from zero in programming. So X = 0, Y = 1, Z = 2
Now, let's say you just want to get the full rotation of the object, you could simply write the same command without [0]
:
>>> bpy.data.objects["Cube"].rotation_euler
Euler((0.0, 0.0, 0.0), 'XYZ')
Now, this command works only on the object named "Cube". If you wanted a different object, you could simply replace the name in the command. But more often than not, in scripting we prefer to have make scripts that work without the need to manually tell object names.
An easy way for that is to replace the part pointing to a specific object by a query to the selected object. This kind of information is usually stored under bpy.context
.
Let's pretend I don't remember what exactly is the command to querry my selection. What I can do is type bpy.context.selec
and press ↹ Tab to have the python console autocomplete, or show the possible things I can get:
Here you can see "selected_objects" in the list. That sounds like what we want, so let's assemble the full line:
>>> bpy.context.selected_objects
[bpy.data.objects['Cube'], bpy.data.objects['Camera']]
As you can see, it didn't just returned the path to our Cube, it also returned the path to my camera which is also selected, separated with a ,
and put them between []
. That is a Python list. And it's logical, we asked to get the selected_objectS
. And that's what will allow you work on multiple objects at once if you want.
Now, if you want to get only one object, you can do as we did with the rotation axes and pick which object's rotation you want to see by adding a [number]
in front of the selected_objects
:
>>> bpy.context.selected_objects[0].rotation_euler
Euler((0.0, 0.0, 0.0), 'XYZ')
Alternatively, if you want to get all selected object's rotation, you can't just put .rotation_euler
at the end. What you need to do is tell Python "for each selected_objects
, show me rotation_euler
. Which is done by a for
loop:
>>> for obj in bpy.context.selected_objects:
... obj.rotation_euler
...
Euler((0.0, 0.0, 0.0), 'XYZ')
Euler((1.1093189716339111, 0.0, 0.8149281740188599), 'XYZ')
Now, I will skip lengthy explanations because I won't make a full Python tutorial here, but if you wanted to make a reusable script out of this, and make the returned data more readable, you could do this:
import bpy
for obj in bpy.context.selected_objects:
re = obj.rotation_euler
objName = obj.name
rx, ry, rz = round(re[0], 1), round(re[1], 1), round(re[2], 1)
print(f"'{objName}' rotation : X {rx} Y {ry} Z {rz}")
You need to enter that in the Text Editor, click the Run button, and you will see the result in Blender's system console (Window > Toggle System Console)
For more information about scripting in Blender:
-
1$\begingroup$ Outstanding answer ! I would just avoid overriding the builtin
object
keyword in python, it can have unintended consequences. $\endgroup$– GorgiousFeb 17 at 6:43 -
$\begingroup$ yeah I first missed the part where the OP said he wanted to output stuff as a 3d text object, so i thought a mini introduction to bpy discovery was needed. And by the time i got my mistake, it was already all written and I didn't want it to go to waste x) Good point about
object
, made some changes. $\endgroup$– L0LockFeb 17 at 20:29