2
$\begingroup$
import bpy
def makeMaterial(name, diffuse, specular, alpha):
  mat=bpy.data.materials.new(name)
  mat.diffuse_color = diffuse
  mat.diffuse_shader = 'LAMBERT'
  mat.diffuse_intensity = 1.0
  mat.specular_color = specular
  mat.specular_shader = 'COOKTORR'
  mat.specular_intensity = 0.5
  mat.alpha = alpha
  mat.ambient = 1
return mat

def setMaterial(ob, mat):
  me = ob.data
  me.materials.append(mat)

def run(origin):
  red = makeMaterial('Red', (1,0,0), (1,1,1), 1)
  blue = makeMaterial( 'Blue', (0,0,1), (0.5,0.5,0), 0.5)
  bpy.ops.mesh.primitive_plane_add(location = origin)
  setMaterial(bpy.context.object,red)
  bpy.ops.mesh.primitive_uv_sphere_add(location = origin)
  bpy.ops.transform.translate(value = (1,0,0))
  setMaterial(bpy.context.object,blue);
  ****bpy.ops.render.render()**// This code doesn't seem to execute**

if __name__=="__main__":
  run((0,0,0))    

The above code when executed doesn't give me the render output. I have no idea why. I'm running the latest blender version. Any help would be welcome.

$\endgroup$
2
  • $\begingroup$ Try getting rid of the semicolon at the end of the setMaterial line. Looks like you've been coding too much c++ :) Make sure you get rid of the asterisks also. $\endgroup$ Oct 10, 2015 at 5:01
  • $\begingroup$ do you mean it does render but doesn't change one of the views to show the result ? $\endgroup$
    – zeffii
    Oct 10, 2015 at 5:34

1 Answer 1

1
$\begingroup$

The makeMaterial function's return statement isn't indented correctly. The semicolon is syntactically allowed, but it's used to place multiple statements on a single line. 2 space indentation makes it less obvious where your indentation is incorrect, standard Python practice is 4 spaces.

This works:

enter image description here

import bpy
def makeMaterial(name, diffuse, specular, alpha):
  mat=bpy.data.materials.new(name)
  mat.diffuse_color = diffuse
  mat.diffuse_shader = 'LAMBERT'
  mat.diffuse_intensity = 1.0
  mat.specular_color = specular
  mat.specular_shader = 'COOKTORR'
  mat.specular_intensity = 0.5
  mat.alpha = alpha
  mat.ambient = 1
  return mat

def setMaterial(ob, mat):
  me = ob.data
  me.materials.append(mat)

def run(origin):
  red = makeMaterial('Red', (1,0,0), (1,1,1), 1)
  blue = makeMaterial( 'Blue', (0,0,1), (0.5,0.5,0), 0.5)
  bpy.ops.mesh.primitive_plane_add(location = origin)
  setMaterial(bpy.context.object, red)
  bpy.ops.mesh.primitive_uv_sphere_add(location = origin)
  bpy.ops.transform.translate(value = (1,0,0))
  setMaterial(bpy.context.object, blue);
  bpy.ops.render.render()

if __name__=="__main__":
  run((0,0,0))

Setting a material is a little bit easier too:

obj.active_material = bpy.data.materials['Blue']

this also works, reusing the makeMaterial function:

def run(origin):
    red = makeMaterial('Red', (1,0,0), (1,1,1), 1)
    blue = makeMaterial( 'Blue', (0,0,1), (0.5,0.5,0), 0.5)
    bpy.ops.mesh.primitive_plane_add(location = origin)
    bpy.context.object.active_material = red
    bpy.ops.mesh.primitive_uv_sphere_add(location = origin)
    bpy.ops.transform.translate(value = (1,0,0))
    bpy.context.object.active_material = blue
    bpy.ops.render.render()

if __name__=="__main__":
    run((0,0,0))

You won't see the objects or material changes until the render has completed.

Changing the render call to bpy.ops.render.render('INVOKE_DEFAULT'), will switch the current TextEditor window to a UV editor, and show the render progress. When we press the UI button for render.render() it does a few more things behind the scene, like pick where to display the render based on the setting in render.display_mode.

Which amounts to something like this:

def find_largest_3dview_and_switch():
    collected_areas = []
    for window in bpy.context.window_manager.windows:
        for area in window.screen.areas:
            if area.type == 'VIEW_3D':
                size = area.height * area.width
                collected_areas.append([size, area])

    # no 3dview found? use texeditor.
    if len(collected_areas) == 0:
        bpy.ops.render.render('INVOKE_DEFAULT')
        return

    # else use largest 3dview.
    for area in sorted(collected_areas, reverse=True):
        area[1].type = 'IMAGE_EDITOR'
        bpy.ops.render.render('INVOKE_AREA')
        return

Instead of calling the naked bpy.ops.render.render() you could call something like find_largest_3dview_and_switch() and let that decide how to call the render function. It would switch any available 3dview (or largest) to an 'IMAGE_EDITOR' and show the render progress.

$\endgroup$
1
  • $\begingroup$ well i did use 4 indent spaces. Its just that i pasted them here that way. Either way that isn't the problem. The problem is why it doesn't show the render output. $\endgroup$
    – Gabriel
    Oct 10, 2015 at 5:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .