# Custom operator to toggle lamp energy not working

I wrote this simple python script for Blender 2.69, which creates a new operator. The operator is supposed to change the energy for four lamps in the scene (essentially switching them off and on again). However, while the script runs fine and creates the operator itself, when I select the operator, it has no effect on the lamps' energy.

Entire script:

import bpy

def main(context):
for ob in context.scene.objects:
print(ob)

class LightsOperator(bpy.types.Operator):

bl_idname = "object.lights_operator"

@classmethod
def poll(cls, context):
return context.active_object is not None

def execute(self, context):

else:

else:

else:

else:

def register():
bpy.utils.register_class(LightsOperator)

def unregister():
bpy.utils.unregister_class(LightsOperator)

if __name__ == "__main__":
register()

# test call
bpy.ops.object.lights_operator()

• Could it be that the poll and execute methods are not inside the class? Make sure that you indent them correctly – WorldSEnder May 23 '14 at 17:12

Here is a variation of the script that works on all lamp objects with their name (ob.data.name! ) starting with "headlight" (case insensitive):

import bpy

class LightsOperator(bpy.types.Operator):
bl_idname = "object.lights_operator"

def execute(self, context):

for ob in context.scene.objects:
if not ob.type == 'LAMP':
continue
lamp = ob.data
lamp.energy = 0.0 if lamp.energy >= 0.8 else 0.8

return {'FINISHED'}

def register():
bpy.utils.register_class(LightsOperator)

def unregister():
bpy.utils.unregister_class(LightsOperator)

if __name__ == "__main__":
register()

# test call
bpy.ops.object.lights_operator()


Note that it toggles the lights between 0.0 and 0.8, no matter what the initial value is. If you want to toggle only those with a specific energy, keep rounding errors in mind - it isn't really 0.8 unless you round(lamp.energy, 1):

>>> lamp.energy = 0.8

>>> lamp.energy == 0.8
False

>>> lamp.energy
0.800000011920929

>>> round(lamp.energy, 1)
0.8


Objects in scripting (bpy.data.objects) are not the same as the Objects you add with ShiftA.

Every scene holds a list (bpy_prop_collection) of objects. Now this is an abstract object that holds information that every object type (Mesh, Lamp, Armature) share - like position in worldspace, modifiers, etc. Here was your error.

Instead of calling bpy.data.objects[name].energy, the correct call is bpy.data.objects[name].data.energy.

Here is an improved version of the script that acts on the currently selected object (as the poll()-method suggests). Call it for every object by first setting context.scene.objects.active and then calling the operator with bpy.ops.object.lights_operator:

import bpy

def main(context):
for ob in context.scene.objects:
print(ob)

class LightsOperator(bpy.types.Operator):
"""Doc"""
bl_idname = "object.lights_operator"

# these two methods belong to the class, not global space
@classmethod
def poll(cls, context):
# can also use context.object instead of context.active_object
return context.object is not None

def execute(self, context):
# get the object
obj = context.object

# check if it is a lamp
if not obj.type == 'LAMP':
return {'CANCELLED'}

# now this is an abstraction by Blender. Every scene
# has objects. Those objects contain the data (mesh,
# curve, and LAMPS). So to access the data of the
# lamp we do
lamp = obj.data

if lamp.energy == 0:
lamp.energy = 0.8
else:
lamp.energy = 0

return {'FINISHED'}

def register():
bpy.utils.register_class(LightsOperator)

def unregister():
bpy.utils.unregister_class(LightsOperator)

if __name__ == "__main__":
register()

# test call
bpy.ops.object.lights_operator()

• The original indentation was just a result of copy+pasting. But to just make sure, I copy+pasted your indented script, and it just returns a "Python script fail". Typing directly into the console gives me a whole bunch of "unexpected indent"s. – Ollie May 23 '14 at 17:28
• It may give a "Python script fail" if the following objects are not in the current scene: 'headlight1', 'headlight2', 'headlight3', 'headlight4'. Check if there are four lamps with exactly thos names (yes capitalization matters). I know that it gives an error when run in the console. I'll update so that you can run it from console. – WorldSEnder May 23 '14 at 17:34
• Yep those exact names are definitely there :) – Ollie May 23 '14 at 17:38
• Okay the script is updated and should now work as described above – WorldSEnder May 23 '14 at 18:03
• Thanks for your help but the new script still doesn't work. :( – Ollie May 24 '14 at 10:08