7
$\begingroup$

I am trying to modify an object after importing it. This post is related to this question

import bpy
full_path_to_file = "C:\\Users\\xyz\\Documents\\test.obj"
bpy.ops.import_scene.obj(filepath=full_path_to_file)
# create the material
mat = bpy.data.materials.new('MaterialName')
mat.diffuse_color = (1.0,0.0,1.0)
mat.diffuse_shader = 'LAMBERT'
mat.diffuse_intensity = 1.0

# get the object
obj = bpy.data.objects['Cube']

# get the material
mat = bpy.data.materials['MaterialName']

# assign material to object
obj.data.materials.append(mat)

I wanted to add a material to the imported object but that is not happening. So I tried to scale it even that is not happening.

I realized that no operation is being performed on the imported objects. But the same operations are executing on the objects that are created (i.e. not imported).

Any help would be appreciated.

$\endgroup$
2
  • $\begingroup$ You try to get an object named 'Cube', are you sure that is what you want? I think the imported object should be named 'test', like the .obj file. $\endgroup$
    – maddin45
    Feb 2, 2015 at 17:47
  • $\begingroup$ yeah the name I entered is right. First I just import the object, check its name and then type in the rest of the code so that wrong name isn't a problem $\endgroup$
    – Ross
    Feb 2, 2015 at 17:51

1 Answer 1

10
$\begingroup$

TLDR; Import operators like import_scene.obj() or import_scene.fbx() don’t return any object name(s) nor a reference as you might expect, they only return {'FINISHED'}.

>>> bpy.ops.import_scene.obj(filepath=</absolute/path/to/file.obj>)
{'FINISHED'}

Good news is all imported object(s) are selected right off the bat and we can get the reference(s) and name(s) after the import process either via bpy.context.object for one object or bpy.context.selected_objects in case the .obj file consists of multiple objects.

import bpy

# Call the obj import operator and pass the absolute file path
bpy.ops.import_scene.obj(filepath="/home/p2or/Desktop/foo.obj")

# Get the context object, print the name and its reference
obj = bpy.context.object
print(obj.name, ":", obj)

# Get all imported objects and print their names
objs = bpy.context.selected_objects
print(", ".join(o.name for o in objs))

Alternatively you can create a set from all objects in the scene bpy.context.scene.objects (t), create another set (s) right after the import process and subtract s from t, might take longer depending on how many objects coming in.

import bpy

# Create a set out of the objects in the current scene (unique by default)
objs = set(bpy.context.scene.objects)
bpy.ops.import_scene.obj(filepath="/home/p2or/Desktop/foo.obj")

# Substract all previous items from the current items and print their names
imported_objs = set(bpy.context.scene.objects) - objs
print(", ".join(o.name for o in imported_objs))

Basic demo

The following working example imports all meshes from the .obj file given, prints their names for error handling, creates a new demo material and assigns the material to all slots or appends a new slot (if there is none) for all incoming objects.

import bpy

bpy.ops.import_scene.obj(filepath="/home/p2or/Desktop/foo.obj")        # Linux
#bpy.ops.import_scene.obj(filepath="C:\\Users\\p2or\\Desktop\\foo.obj")# Windows
#bpy.ops.import_scene.obj(filepath="/Users/p2or/Desktop/foo.obj")      # MacOS

# Get all objects (create a copy of the entire list)
objs = bpy.context.selected_objects[:]

# Generate or get the material
material_name = 'MaterialName'
mat = bpy.data.materials.get(material_name)
if mat is None:
    mat = bpy.data.materials.new(material_name)

# Iterate through all imported objects
for obj in objs:
    # Print the actual name and reference
    # possibly modified since all names are unique
    print(obj.name, obj)
    # If there is no material slot append one with the (new) material
    if not len(obj.data.materials):
        obj.data.materials.append(mat)
    # Assign the (newly created) material to all existing slots
    for i in range(len(obj.data.materials)):
        obj.data.materials[i] = mat

# Edit the material viewport properties
mat.diffuse_color = (0,1,0,1) # Viewport color
mat.roughness = 1.0 # Viewport roughness
# .../api/current/bpy.types.Material.html#bpy.types.Material.diffuse_color

# Edit the material and create all nodes from scratch
mat.use_nodes = True
nodes = mat.node_tree.nodes
nodes.clear() 
node_principled = nodes.new(type='ShaderNodeBsdfPrincipled')
node_principled.inputs['Base Color'].default_value = (1,0,0,1) # Shader Base Color 
node_principled.location = 0,0
node_output = nodes.new(type='ShaderNodeOutputMaterial')   
node_output.location = 400,0
links = mat.node_tree.links
link = links.new(node_principled.outputs["BSDF"], node_output.inputs["Surface"])
# .../api/current/bpy.types.NodeTree.html#bpy.types.NodeTree.nodes

Related

For Blender 2.79 and earlier have a look into the revisions of this answer.

$\endgroup$
1
  • 1
    $\begingroup$ Thanks a lot for your help. I had been working on this for a week but without luck. Actually on importing there was a default material. Thus appednding only created the material but did not apply it to the faces. 'obj.data.materials[0] = mat' helped to get the texture on the object :) $\endgroup$
    – Ross
    Feb 3, 2015 at 6:59

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.