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$
  • $\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$ – TARDIS Maker Oct 10 '15 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 '15 at 5:34
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$
  • $\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 '15 at 5:29

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.