cycles image texture sequence?

@gummifer

After being frustrated that I couldn’t get a textured video/image sequence to render with Cycles, your script saved the day.

Weird that Cycles doesn’t have this functionality by default, oh well… :no:

Thanks champ!

Made an account to say thanks for the script!

Is there a way to set this script to start pulling the ‘animation images’ at a certain frame? I’m having a hard time getting the animation timed right in my project since it appears mid way through and not at the very beginning. Any tips on that?

Thanks again!

@gummifer
I improved you script because it wasn’t working for me in the correct way:
I have two image sequence one for displacement and the other showing the image/movieclip
using your script on render time the displacement didn’t got updated, so I start to find an alternative solution, I tried atom’s frame change addon (and modal timer) to see if was a thread related problem but unfortunately with a separated thread it’s not possible to change a node texture.
The solution is to start the render on the script, in that case everything works!!!
I made other changes for efficiency, well I mostly rewrite it but the principle is the same… without further words here is the updated script!
to use it choose at the beginning of the script which dir contains the image sequence, and if you want to render an animation or a still image,
the press run and check the console.
enjoy



############ setup global variables
# set the directory relative to the blend file
moviedirectory = "movieclip/c/" #end it with a trailing slash i.e "movieclip/c/" will be /home/foo/blenderprj/movieclip/c/ absolute path
# set if you want to render a still or an animation
#animate = True
animate = False

# cycleImage.py 
# c ~ 2012 ~ gummifer, elaser

# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****


'''
The script loads all the images from a folder, and puts them in a list. It then looks for an object in the scene that has a custom property named "anim", and checks for image texture nodes named "anim" on that object's material. 
Then it just change the texture on the "frame change" event.
'''

import bpy

import os
import re

anim_texture_nodes = []
sequence_images = {}

def load_images():
    print('#load images from folder ')
    moviedir = bpy.path.abspath('//') + moviedirectory
    files = os.listdir(moviedir)
    for f in files:
        valid_frame = re.compile(r"(\d){4}") #assumes to find frames numbers with 4 digits C_1000.jpg is valid
        try:
            frameNumber = valid_frame.search(f).group()
            if not f in bpy.data.images: #don't load the image if is already opened
                bpy.ops.image.open(filepath = moviedir + f)
            sequence_images[frameNumber] = f
        except AttributeError:
            print("skipped " + f)
    
    #search for objects with custom property "anim"
    anim_texture_objects = []
    for obj in bpy.data.objects:
        if "anim" in obj:
            print(obj.name)
            anim_texture_objects.append(obj)
                
    #search for image texture nodes named "anim"
    for obj in anim_texture_objects:
        for node in obj.active_material.node_tree.nodes:
            if node.name == "anim":
                anim_texture_nodes.append(node)
    print("DONE preloading")

from bpy.app.handlers import persistent

@persistent
def frameRefesh (scene):
    #print('-----Update on frame # %04d'% scene.frame_current )
    frameNumber = str(scene.frame_current).zfill(4)
    for node in anim_texture_nodes:
        f =  sequence_images[frameNumber]
        # for some reason if rendering a still image,  the framenumber is not appended to the path
        if not animate : #check we are rendering a still image and we haven't changed the path yet
            if not scene.render.filepath[-4:].isdigit(): 
                scene.render.filepath+=frameNumber 
            else:
                scene.render.filepath=scene.render.filepath[:-4]+frameNumber
        print("changing texture to "+f)
        if f in bpy.data.images:
            node.image = bpy.data.images[f]
        else:
            print("Can't find the image" + f)


bpy.app.handlers.frame_change_pre.append(frameRefesh)
'''
#### bug: frameRefesh event is appended and fired multiple times (everytime the script is ran)
def unset_frameRefesh(scene):
    bpy.app.handlers.frame_change_pre.remove(frameRefesh)
bpy.app.handlers.render_complete.append(unset_frameRefesh)
bpy.app.handlers.render_cancel.append(unset_frameRefesh)
'''


load_images()
print ("********************** START rendering")
bpy.ops.render.render(animation=animate, write_still=True)
print ("**********************  DONE rendering")

Oh man, this script just eliminated a huge headache in the making. THANK YOU for taking the time to write this script. I got it hand to you, Such a gift to others that you take the time to learn how to write code as well as others out there doing the same. Took me a couple hours of poking Bl and the web to see if there was a work-around and here it is. It works great. Thanks again!