1
$\begingroup$

Dears, I am trying to create a simple empty room using Python scripts. But when I tried to reach the object using "bpy.context.object" to scale it, the compiler stops and give me this error. "AttributeError: 'Context' object has no attribute 'object'". I looked in the documentation and it exists.

Can you please tell me what is wrong with my code? I am using Blender v3.6.5.

Many thanks in advance.

import bpy

# Clear existing mesh objects
bpy.ops.wm.read_factory_settings(use_empty=True)

# Set units to metric
bpy.context.scene.unit_settings.system = 'METRIC'
bpy.context.scene.unit_settings.scale_length = 1.0

# Create a wooden floor
bpy.ops.mesh.primitive_plane_add(size=8, align='WORLD', location=(0, 0, 0))
floor = bpy.context.object
floor.scale[0] = 2  # Scale it to 16x16 meters
floor.scale[1] = 2
floor.name = 'Wooden Floor'

# Create white walls
wall_thickness = 0.1  # Thickness of the walls
wall_height = 4.0  # Height of the walls

# Create walls
walls_data = [
    (8, -1, 0, wall_thickness, 18, wall_height),  # Left wall
    (8, 17, 0, wall_thickness, 18, wall_height),  # Right wall
    (-1, 8, 0, 18, wall_thickness, wall_height),  # Back wall
    (17, 8, 0, 18, wall_thickness, wall_height),  # Front wall
]

walls = []

for i, (x, y, z, sx, sy, sz) in enumerate(walls_data):
    bpy.ops.mesh.primitive_cube_add(size=1, location=(x, y, z + sz / 2))
    wall = bpy.context.object
    wall.scale[0] = sx
    wall.scale[1] = sy
    wall.scale[2] = sz
    wall.name = f'Wall {i + 1}'
    walls.append(wall)

# Set materials for the floor
floor.data.materials.append(bpy.data.materials.new(name='Wooden Floor Material'))
floor.active_material.diffuse_color = (0.5, 0.3, 0.1, 1)  # Brown color for wood

# Set materials for the walls
for wall in walls:
    wall.data.materials.append(bpy.data.materials.new(name='White Wall Material'))
    wall.active_material.diffuse_color = (1, 1, 1, 1)  # White color for walls
$\endgroup$

2 Answers 2

1
$\begingroup$

You need to add a timer, when you reload a file there is at least one tick where the context is not initialized.

BTW I suspect this is an artifact of using a LLM like ChatGPT to produce the code, but being overzealous with comments can be detrimental to the script. I advise you to rather use descriptive function names. Also resetting factory settings is a weird choice, I think you want to load a new file.

import bpy

def set_units_to_metric():
    bpy.context.scene.unit_settings.system = 'METRIC'
    bpy.context.scene.unit_settings.scale_length = 1.0

def create_wooden_floor():
    bpy.ops.mesh.primitive_plane_add(size=8, align='WORLD', location=(0, 0, 0))
    floor = bpy.context.object
    floor.scale[0] = 2  # Scale it to 16x16 meters
    floor.scale[1] = 2
    floor.name = 'Wooden Floor'
    return floor

def create_walls():
    wall_thickness = 0.1  # Thickness of the walls
    wall_height = 4.0  # Height of the walls

    walls_data = [
        (8, -1, 0, wall_thickness, 18, wall_height),  # Left wall
        (8, 17, 0, wall_thickness, 18, wall_height),  # Right wall
        (-1, 8, 0, 18, wall_thickness, wall_height),  # Back wall
        (17, 8, 0, 18, wall_thickness, wall_height),  # Front wall
    ]

    walls = []

    for i, (x, y, z, sx, sy, sz) in enumerate(walls_data):
        bpy.ops.mesh.primitive_cube_add(size=1, location=(x, y, z + sz / 2))
        wall = bpy.context.object
        wall.scale[0] = sx
        wall.scale[1] = sy
        wall.scale[2] = sz
        wall.name = f'Wall {i + 1}'
        walls.append(wall)
    return walls

def set_floor_materials(floor):
    floor.data.materials.append(bpy.data.materials.new(name='Wooden Floor Material'))
    floor.active_material.diffuse_color = (0.5, 0.3, 0.1, 1)  # Brown color for wood
    
def set_walls_materials(walls):
    for wall in walls:
        wall.data.materials.append(bpy.data.materials.new(name='White Wall Material'))
        wall.active_material.diffuse_color = (1, 1, 1, 1)  # White color for walls

def main():
    set_units_to_metric()
    floor = create_wooden_floor()
    walls = create_walls()
    set_floor_materials(floor)
    set_walls_materials(walls)

if __name__ == "__main__":
    bpy.ops.wm.read_homefile()
    bpy.app.timers.register(main, first_interval=0.01)
$\endgroup$
0
$\begingroup$

I had the same problem with a similar scene also created by chatGPT:

Write a Python script for Blender that creates an animation. The animation should show relativistic time dilation simulating the bouncing of light in an hourglass like the one used to demonstrate Lorentz time contraction. The hourglass must move along the X axis with constant speed. The speed of the hourglass mirrors must be half the speed of the photon bouncing between the mirrors.

ChatGPT answer:

import bpy
import math

# Limpiar la escena
bpy.ops.wm.read_factory_settings(use_empty=True)

# Crear los espejos del reloj de luz
bpy.ops.mesh.primitive_plane_add(size=2, location=(0, 0, 0))
mirror1 = bpy.context.object
mirror1.name = "Mirror1"

bpy.ops.mesh.primitive_plane_add(size=2, location=(0, 0, 5))
mirror2 = bpy.context.object
mirror2.name = "Mirror2"

# Crear el fotón como una esfera pequeña
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0, 0, 2.5))
photon = bpy.context.object
photon.name = "Photon"

# Configurar la animación del fotón
frame_start = 1
frame_end = 100

photon.keyframe_insert(data_path="location", frame=frame_start)
photon.location.z = 5
photon.keyframe_insert(data_path="location", frame=frame_start + (frame_end - frame_start) / 2)
photon.location.z = 0
photon.keyframe_insert(data_path="location", frame=frame_end)

# Configurar interpolación lineal para el fotón
for fcurve in photon.animation_data.action.fcurves:
    for kp in fcurve.keyframe_points:
        kp.interpolation = 'LINEAR'

# Configurar la animación del reloj de luz (espejos)
velocity = 0.1  # Velocidad del reloj de luz
frame_count = frame_end - frame_start

mirror1.keyframe_insert(data_path="location", frame=frame_start)
mirror2.keyframe_insert(data_path="location", frame=frame_start)
mirror1.location.x += velocity * frame_count
mirror2.location.x += velocity * frame_count
mirror1.keyframe_insert(data_path="location", frame=frame_end)
mirror2.keyframe_insert(data_path="location", frame=frame_end)

# Configurar la cámara
bpy.ops.object.camera_add(location=(10, -10, 10), rotation=(math.radians(60), 0, math.radians(45)))
camera = bpy.context.object
bpy.context.scene.camera = camera

# Configurar la luz
bpy.ops.object.light_add(type='SUN', location=(10, -10, 10))
light = bpy.context.object
light.data.energy = 3

# Configurar renderizado
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.samples = 128
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end

# Guardar el archivo
bpy.ops.wm.save_as_mainfile(filepath="relativistic_time_dilation.blend")

print("Animación de dilatación relativista del tiempo creada con éxito")

I asked chatGPT to fix the bug, using a combination of the #Gorgious answer and Blender's error message:

when you use primitive_plane_add there is at least one tick where the context is not initialized. results in a crash on line 9 " AttributeError: 'Context' object has no attribute 'object' " ¿can you rewrite the code to fix this problem?

After 5 attempts copying the Blender error message into the GPT chat...he finally solved it on his own:

import bpy
import math

# Limpiar la escena
bpy.ops.wm.read_factory_settings(use_empty=True)

# Función para crear un espejo
def create_mirror(location, name):
    bpy.ops.mesh.primitive_plane_add(size=2, location=location)
    bpy.context.view_layer.update()
    mirror = bpy.context.view_layer.objects.active
    mirror.name = name
    return mirror

# Crear el controlador vacío
bpy.ops.object.empty_add(type='PLAIN_AXES', location=(0, 0, 0))
bpy.context.view_layer.update()
controller = bpy.context.view_layer.objects.active
controller.name = "Controller"

# Crear los espejos del reloj de luz
mirror1 = create_mirror((0, 0, 0), "Mirror1")
mirror2 = create_mirror((0, 0, 5), "Mirror2")

# Hacer los espejos hijos del controlador
mirror1.parent = controller
mirror2.parent = controller

# Crear el fotón como una esfera pequeña
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0, 0, 2.5))
bpy.context.view_layer.update()
photon = bpy.context.view_layer.objects.active
photon.name = "Photon"

# Hacer el fotón hijo del controlador
photon.parent = controller

# Configurar la animación del fotón
frame_start = 1
frame_end = 100

photon.keyframe_insert(data_path="location", frame=frame_start)
photon.location.z = 5
photon.keyframe_insert(data_path="location", frame=frame_start + (frame_end - frame_start) / 2)
photon.location.z = 0
photon.keyframe_insert(data_path="location", frame=frame_end)

# Configurar interpolación lineal para el fotón
for fcurve in photon.animation_data.action.fcurves:
    for kp in fcurve.keyframe_points:
        kp.interpolation = 'LINEAR'

# Configurar la animación del controlador (movimiento a lo largo del eje X)
velocity = 0.1  # Velocidad del reloj de luz
frame_count = frame_end - frame_start

controller.keyframe_insert(data_path="location", frame=frame_start)
controller.location.x += velocity * frame_count
controller.keyframe_insert(data_path="location", frame=frame_end)

# Configurar la cámara
bpy.ops.object.camera_add(location=(10, -10, 10), rotation=(math.radians(60), 0, math.radians(45)))
bpy.context.view_layer.update()
camera = bpy.context.view_layer.objects.active
bpy.context.scene.camera = camera

# Configurar la luz
bpy.ops.object.light_add(type='SUN', location=(10, -10, 10))
bpy.context.view_layer.update()
light = bpy.context.view_layer.objects.active
light.data.energy = 3

# Configurar renderizado
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.samples = 128
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end

# Guardar el archivo
bpy.ops.wm.save_as_mainfile(filepath="relativistic_time_dilation.blend")

print("Animación de dilatación relativista del tiempo creada con éxito")

chatGPT updated the scene and changed the way to access the object:

bpy.context.view_layer.update()
mirror = bpy.context.view_layer.objects.active

UpVote if you love and hate AI

$\endgroup$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.