Simple test in python console
Run a simple test. Put the cursor at some known scene location, and add an object using the bpy_extras.object_utils.object_data_add method. (Simply pinched a mesh from the active object cube)
>>> C.object
bpy.data.objects['Cube']
>>> me = C.object.data
>>> C.scene.cursor.location = (10, 10, 10)
>>> import bpy_extras
>>> ob = bpy_extras.object_utils.object_data_add(C, me)
>>> ob.location
Vector((10.0, 10.0, 10.0))
Hence without any operator passed, uses the scene cursor. btw the python source is readily available, and could check thru scripts/modules/bpy_extras/object_utils.py to confirm
To make it zero location, rotation and unit scale
>>> ob.matrix_world = Matrix()
>>> ob.location
Vector((0.0, 0.0, 0.0))
Check the docstring
For a quick run down check the docstring in the python console
>>> bpy_extras.object_utils.object_data_add(
object_data_add(context, obdata, operator=None, name=None)
Add an object using the view context and preference to initialize the
location, rotation and layer.
:arg context: The context to use.
:type context: :class:`bpy.types.Context`
:arg obdata: the data used for the new object.
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
:type operator: :class:`bpy.types.Operator`
:arg name: Optional name
:type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.Object`
Use in conjunction with an operator
is designed to be used in conjunction with an add object operator in which case transform settings are taken from the instance of the operator. Often also used with AddObjectHelper class, as demonstrated in Text Editor > Python > Templates > Add Object and in this example https://blender.stackexchange.com/a/160995
Using a decorator
An example of wrapping a decorator around the imported method to set the new object created to a transform of our choosing.
import bpy
from bpy_extras.object_utils import object_data_add
from mathutils import Matrix
def location_decorator(matrix=Matrix()):
def decorator(f):
def g(args, kwargs):
ob = f(args, **kwargs)
ob.matrix_world = matrix
return ob
return g
return decorator
object_data_add = location_decorator()(object_data_add)
me = bpy.data.meshes.new("Foo")
ob = object_data_add(bpy.context, me)
or if using with an operator that has a location property, but we wish to make it default to scene origin (or another transform) when not set then
def location_decorator(matrix=Matrix()):
def decorator(f):
def g(*args, **kwargs):
op = kwargs.get("operator")
if op and not op.properties.is_property_set("location"):
op.location = matrix.translation
return f(*args, **kwargs)
return g
return decorator
locationargument is set it is relative to global origin. – batFINGER Mar 22 '21 at 16:45