2
$\begingroup$

I wrote a script. In one part of the script, there is this line:

base_object.data.materials.append (changeable_material)

Whenever I try to run the script, Blender just shuts down, immediately, without any error or anything, within a fraction of a second.

base_object is a cube generated by the script, changeable_material is a precreated material. I don't have much experience with Blender scripting.

Is this a mistake in my code or a bug? If not a bug, how do I fix it?

Edit:

Relevant parts of the script:

import bpy

matrix_size = 3

matrix = []
cubes = []
materials = []
matrix_range = range (matrix_size)

changeable_material = bpy.data.materials.get("Material")

material_value = 0

for i in range (matrix_size):
    matrix.append([])
    cubes.append ([])
    materials.append (changeable_material.copy ())
    materials [-1].node_tree.nodes.get("Value").outputs [0].default_value = material_value
    material_value += 1 / matrix_size
    for j in range (matrix_size):
        matrix [-1].append ((i * j) % matrix_size)
        cubes [-1].append (0)

(...)

#removes all unused materials
for material in bpy.data.materials:
    if (not (material.users)):
        bpy.data.materials.remove(material)

bpy.ops.mesh.primitive_cube_add()
base_object = bpy.context.object
base_object.name = "base cube"
base_object.data.materials.append (changeable_material)

bpy.context.scene.objects.active = base_object

(...)

for i in range (matrix_size):
    for j in range (matrix_size):
        if cubes [i][j].data.materials:
            cubes [i][j].data.materials[0] = materials [matrix [i][j]]

Here is the whole:

import bpy

matrix_size = 3

(...)

materials = []
matrix_range = range (matrix_size)

changeable_material = bpy.data.materials.get("Material")

material_value = 0

for i in range (matrix_size):
    (...)
    materials.append (changeable_material.copy ())
    materials [-1].node_tree.nodes.get("Value").outputs [0].default_value = material_value
    material_value += 1 / matrix_size
    for j in range (matrix_size):
        matrix [-1].append ((i * j) % matrix_size)
        cubes [-1].append (0)

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

for i in bpy.data.objects:
    if ((i.type == "CAMERA") or (i.type == "LAMP") or (i.name == "Material_Holder")):
        i.select = False
bpy.ops.object.delete()

#removes all unused materials
for material in bpy.data.materials:
    if (not (material.users)):
        bpy.data.materials.remove(material)

bpy.ops.mesh.primitive_cube_add()
base_object = bpy.context.object
base_object.name = "base cube"
base_object.data.materials.append (changeable_material)

base_object.scale = (0.5, 0.5, 0.5)

bpy.context.scene.objects.active = base_object

arrayOne = base_object.modifiers.new (name = "arrayOne", type = "ARRAY")
arrayOne.count = matrix_size
arrayTwo = base_object.modifiers.new (name = "arrayTwo", type = "ARRAY")
arrayTwo.count = matrix_size
arrayTwo.relative_offset_displace [0] = 0
arrayTwo.relative_offset_displace [1] = 1

bpy.ops.object.modifier_apply (modifier = "arrayOne")
bpy.ops.object.modifier_apply (modifier = "arrayTwo")

base_object.select = True
bpy.ops.mesh.separate (type = "LOOSE")

for i in bpy.data.objects:
    if ("cube" in i.name):
        bpy.ops.object.select_all(action = "DESELECT")
        i.select = True
        bpy.ops.object.origin_set (type = "ORIGIN_CENTER_OF_MASS")
        cubes [int (i.location [0])][int (i.location [1])] = i

for i in range (matrix_size):
    for j in range (matrix_size):
        if cubes [i][j].data.materials:
            cubes [i][j].data.materials[0] = materials [matrix [i][j]]
$\endgroup$
  • 1
    $\begingroup$ You should probably post your relevant code, for others to check... $\endgroup$ – m.ardito Oct 17 '18 at 16:46
  • $\begingroup$ The line is correct assuming the variables contain correct information. The issue must be in another part of the code. Without seeing the code it is impossible to say what is wrong. $\endgroup$ – Martin Z Oct 17 '18 at 17:53
  • 2
    $\begingroup$ Try reducing the code to the minimal amount needed to reproduce the crash. Usually that gives you more insight, and also saves us from having to understand all of your stuff. $\endgroup$ – dr. Sybren Oct 18 '18 at 5:43
  • $\begingroup$ Agree with comment above, or post full code(or a link to).The collection bpy.data.objects is all objects in the blend file which may be linked to context scene, another scene or no scene whatsoever. Suggest using context.scene.objects instead. Also to set an object to active scene.objects.active = ob as well as ob.select = True before calling an operator like origin set. An object can be active and not selected. $\endgroup$ – batFINGER Oct 18 '18 at 6:37
1
$\begingroup$

From the code snippets given, it's difficult to reproduce the error.

Here's my guess:

If the object with the name 'Material_Holder' does not have the material referenced by the variable changeable_material, that material will get removed (in block with the comment #removes all unused materials). There would be problem if later this (removed) material is appended to any object (base_object.data.materials.append (changeable_material)). The crash could be related to this.

So if the changeable_material is needed later in the code, the condition should be if (not (material.users)) and material is not changeable_material before calling remove.

$\endgroup$
  • $\begingroup$ The problem indeed was the material I was trying to assign did not exist at the time at that time. Moving the "remove all unused materials" to the top fixed this $\endgroup$ – aky-her Oct 18 '18 at 6:50

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.