Dynamic Framebase Texture Changer Script

hi guys, thought id post up this lil script ive built and tested. This script, when linked as a FrameChange script allows a person to easily predefine what texture is active on specific frames.

this is best descriped in an example. I’ve created an anime based character whose face is texture based. I wish to make some big animations with her, animating her mouth, eyes, nose, eyebrows, etc, on certain frames. Currently the options for this are:
I would have to create either a animated offset on a texture to do this, but since im working with higher res textures, this isnt feasible.
I would have to create an avi or a image sequence outside blender to accomodate this. but doing this would take a tonne of time and i would have to create an image for every frame. this is alot of work and time.

So. this script basically lets me change what texture is linked inside a texture channel in a material whenever i want. ie, for frames 1-25, the base texture for eyes is shown in channel3, for frames 25-30 this changes to a texture showing the lids halfclosed, 30-40 with the eyes closed, 40-45 eyes half open and then back to the base texture until the next ‘blink’. This is done easily in the script.

To allow others to use this script, ive setup directions for use inside it,some examples of the lists needed. for a single material of a single object, you have 1 line to change for each channel, and its fairly intuative. The script even allows you to manipulate more than 1 object’s material, or more than 1 material in a single object. The amount of animation is only limited by your imagination and the 10 channels per material blender gives us.

This can be easily adopted into gaming too for similar dynamic texture changing.

current limitations:
you have to go into the script to change the list… i havent quite worked out a gui for this yet. list is near the top, easy to access and easy to change tho.

There seems to be a glitch in blender with FrameChange scripts. If you use this script in blender, if you want to see the changes onscreen (and gamemode), you need to have the materials panel open…i dont know why it does this, the script works perfectly for rendering/anim, just not in game glsl materials settings properly without leaving at least some window with the material panel open. anyone know why this does this?

apoligies, i couldnt fit it all in 1 post, the actual script is in the next post:

*Updated 03/07/09
Here is the full script:

#"""
#Name: 'Dynamic Framebased Texture Changer'
#Blender: 249
#Group: 'Animation'
#Tooltip: 'Edit the values in the script below in the section User Definable Variables to work'
#"""

#__author__ = "Holly Tsukiko Grimes"
#__url__ = ["Fairytalecomics, http://www.fairytalecomics.com/"]
#__version__ = "0.9"
#__bpydoc__ = """\
#Description:

# This script is a texture changer in any animation. This accesses the textures in a materials
#channels and changes the texture in that channel depending on the frame number. 
#
# This is perfect for animations using textures. This could be adapted for Games easily by 
#incorporating the script to run from commands.. i.e, you could have it so that when a character
#'talks' in game, it would run a precompiled sequence of textures from this easily. This could
#be adapted for editing UV maps easily.
#
# Currently this is built in such a way that you need to have Textures set up prior to this script
#as this would do better for gaming and such and you dont need to reload images from files, but instead
#from memory. This does mean a little bit of setup time, but the code could be easily changed that instead
#of switching textures, you can change the filename instead the base texture and reload.
#
# I added in the feature that you can animate more than 1 object at a time, you just need to fill
#out the list correctly with more lists of channels, which is easy. 
#
# This was built out of a need to easily and quickly change textures on a material on certain
#frames, in particular for a face composed of channels with a channel for eyes, a channel for
#the mouth, 1 for eyebrows, etc.
#
# Updates since version 0.7:
# Corrected a glitch in the code which selects a channel.
# Updates since version 0.8:
# Corrected a glitch in the code which selects a material in a mesh.
#
#
# Limitations of this version:
# The channels need to be preoccupied in a material first for this to work, but, you dont need
#to have all the channels filledto use the script, only the ones you need to change need to
#have something in there first.
#
# Only allows you to change the 9 channels on a single material so far, which i guess is
#already the limit in blender per material anyway, so it doesnt matter.
#
# There seems to be a flaw in Blender that the script doesnt change using a FrameChanged link
#unless the material tab is open using Alt-A and having blender game GLSL materials active.
#This still works using Anim, previewing requires the material panel open for this to work.

#Usage:
#Edit the channel information below. examples are given above the channels. There is no limit i believe
#on how many changes you can put for a channel.
#"""

#Script: Dynamic Framebased Texture Changer
#Date:  03/07/09
#Version 0.9

import Blender
from Blender import *

######################################################
#User Definable Variables
#Edit these names for your own objects.
######################################################

#Objects, Materials, Textures and the details needed to change the texture over time.

#Here are 2 examples, these are useable if you just take out the leading hashes.


#Example 1: 
#1 object being changed called "TNenfaceTex"(a face as you can tell), 1 material being
#changed called "TToonSkinTex1" in the object (not necessarily material 1 in the object, the materials
#are all searched in the object). 4 channels are being used in this material, only 2 are animated
#with something. 
#
#channels 1 and 6-10 are either non-animated textures or empty in the material.
#
#channel 2's texture uses the texture "TFaceNoseBase" for the all of the animation. This
#doesn't change.
#
#channel 3's texture uses the texture "TFaceMouthBase" for the bulk of the animation. This
#changes to "TFaceMouthSmirk" at frame 100 for 10 frames (until frame 110). At frame 110, it
#changes back to the base texture "TFaceMouthBase" and stays that way until the end of the animation.
#
#channel 4's texture uses the texture "TFaceEyesBase" for the bulk of the animation. 
#This changes to "TFaceEyesHalfopen" at frame 25 for 5 frames (until frame 30). 
#At frame 30, it changes to the texture "TFaceEyesClosed" for 10 frames (until frame 40).
#At frame 40, it changes back to "TFaceEyesHalfopen" for 5 frames until frame 45.
#At frame 45, it changes back to the base texture "TFaceEyesBase" until the next change (at frame 75
#as seen in this example). This channel creates several 'blink' style animations easily.
#
#channel 5's texture uses the texture "TFaceEyeBBase" for the all of the animation. This
#doesn't change.
#
#Code:
#
#MaterialChannels=[
#[["TNenfacetex","TToonSkinTex1"],
#[["",1]],
#[["TFaceNoseBase",2]], 
#[["TFaceMouthBase",3],["TFaceMouthSmirk",100,10]],
#[["TFaceEyesBase",4],["TFaceEyesHalfopen",25,5,35,5,75,5,85,5,115,5,125,5],["TFaceEyesClosed",30,10,80,10,120,10]],
#[["TFaceEyeBBase",5]],
#[["",6]],
#[["",7]],
#[["",8]],
#[["",9]],
#[["",10]]]]


#Example 2: 
#2 objects are being changed. first is called "TNenfaceTex"(a face as you can tell), 1 material being
#changed called "TToonSkinTex1" in the object (not necessarily material 1 in the object, the materials
#are all searched in the object). 4 channels are being used in this material, only 2 are animated
#with something. channels 1 and 6-10 are either non-animated textures or empty in the material.
#This first material animation is identical to above.
#Object 2 is called "TNenHair", of which 1 material is changed called "TNenHairMaterial". In this
#material 2 channels are being animated, channels 3-10 are not being used.
#
#channel 1's texture uses the texture "THairFringeBaseTex" for the bulk of the animation. This
#changes to "THairFringeShinyTex" at frame 200 for 50 frames (until frame 250). At frame 700, it
#changes to "THairFringeDullTex" for 600 frames (until frame 1300).
#
#channel 2's texture uses the texture "THairLongHairBaseTex" for the bulk of the animation. This
#changes to "THairLongHairShinyTex" at frame 200 for 50 frames (until frame 250). At frame 700, it
#changes to "THairLongHairDullTex" for 600 frames (until frame 1300).
#
#Code:
#
#MaterialChannels=[
#[["TNenfacetex","TToonSkinTex1"],
#[["",1]],
#[["TFaceNoseBase",2]], 
#[["TFaceMouthBase",3],["TFaceMouthSmirk",100,10]],
#[["TFaceEyesBase",4],["TFaceEyesHalfopen",25,5,35,5,75,5,85,5,115,5,125,5],["TFaceEyesClosed",30,10,80,10,120,10]],
#[["TFaceEyeBBase",5]],
#[["",6]],
#[["",7]],
#[["",8]],
#[["",9]],
#[["",10]]],
#[["TNenHair","TNenHairMaterial"],
#[["THairFringeBaseTex",1],["THairFringeShinyTex",200,50],["THairFringeDullTex",700,600]],
#[["THairLongHairBaseTex",2],["THairLongHairShinyTex",200,50],["THairLongHairDullTex",700,600]], 
#[["",3]],
#[["",4]],
#[["",5]],
#[["",6]],
#[["",7]],
#[["",8]],
#[["",9]],
#[["",10]]]]

MaterialChannels=[
[["TNenfacetex","TToonSkinTex1"],
[["",1]],
[["TFaceNoseBase",2]],
[["TFaceMouthBase",3],["TFaceMouthSmirk",100,10]],
[["TFaceEyesBase",4],["TFaceEyesHalfopen",25,5,35,5,75,5,85,5,115,5,125, 5],["TFaceEyesClosed",30,10,80,10,120,10]],
[["TFaceEyeBBase",5]],
[["",6]],
[["",7]],
[["",8]],
[["",9]],
[["",10]]]]

######################################################
#function
# change the Textures based on the current frame
######################################################

import Blender
def main():

    global MaterialChannels
    MatIndex=-10

    scn= Blender.Scene.GetCurrent()
    frame=str(Blender.Get('curframe'))

    #find material index of the object
    for Onum in range (0,len(MaterialChannels)):
        FaceObj = Blender.Object.Get(MaterialChannels[Onum][0][0])
        #FaceObj.select(1)
        MatList = FaceObj.getData().getMaterials()
        if MatIndex < 0:
            for mnum in range(0,len(MatList)):
                if MatList[mnum].getName() == MaterialChannels[Onum][0][1]:
                    MatIndex=mnum
        MatFace=MatList[MatIndex]
        TexSlotList = MatFace.getTextures()


        #channels
        for Cnum in range(1,11):
            if len(MaterialChannels[Onum][Cnum])>1:        
                channelTex=TexSlotList[Cnum-1]
                channeltexBase = Blender.Texture.Get(MaterialChannels[Onum][Cnum][0][0])  
                channelTex.tex = channeltexBase
                for Lnum in range(1, len(MaterialChannels[Onum][Cnum])):
                    for Fnum in range(0,(len(MaterialChannels[Onum][Cnum][Lnum])-1)/2):
                        if int(frame) in range(MaterialChannels[Onum][Cnum][Lnum][1+(Fnum*2)],MaterialChannels[Onum][Cnum][Lnum][1+(Fnum*2)]+MaterialChannels[Onum][Cnum][Lnum][2+(Fnum*2)]):
                            channelTex.tex = Blender.Texture.Get(MaterialChannels[Onum][Cnum][Lnum][0])
main()

Edit:
Here is a zip containing the py file if the indentation doesnt show above:
http://www.fairytalecomics.com/3d/TexAnim.zip

You can try to use code tags (

 ... you get the idea) instead.

Looks highly specific.

well, when i started the script it was very specialised, but i edited it since then so it works for any object and texture. basically, its easy to take this and create easy texture animations in games and animations using just a few lines instead of multiple image sequences or similar (its also the first real python script i made for blender tehe)

i just need to make it a little more user friendly i guess ^^ maybe have it read in a file with the information. currently working on a function that will implement this that anyone can throw into a python script in their game and it will work.

this looks quite useful, thank you for your hard work and for sharing the script with the blender community.

There seems to be a glitch in blender with FrameChange scripts. If you use this script in blender, if you want to see the changes onscreen (and gamemode), you need to have the materials panel open…i dont know why it does this, the script works perfectly for rendering/anim, just not in game glsl materials settings properly without leaving at least some window with the material panel open. anyone know why this does this?

many thanks about that ! I was wondering why my script didn’t work

looking at your script, I’m wondering how do you ask for a reflesh to GE or the preview window, I don’t get it…

ok I assume there’s no need for it for still images. video image need (?)

hey this script seems to be what i was looking for! i ll give it a try.
thank you very much for sharing your work with us.
Could you post a video showing the results of the script? i tried to get some in your web page but ven´t find. Anyway, you look nice in the cosplay :wink:
thanks again

thanks guys, sorry for the delay in this response, ive been busy for the last while with an animation that im building which makes use of this script alot.

lets see.
littleneo:
well, i dont ask for a refresh in the script, i set it as a frame script in the script tab in the buttons window. That way it changes the textures based on the frame.

second part: the reason why still images is the fact that in texturing faces, you reuse alot of frames, the same info. its a lot of wasted space, in a video or even just to have 1 image per frame.

thats why i built this, so for example i can simply create 3 textures for the eyes (closed, halfopen, open) and by using this script, i can easily create a blinking texture by only changing a few values in the script. you can still use movies in the texture channel as long as you have set it up prior (say, run one movie texture for X frames, then switch to another movie texture for Y frames). mew, hope i explained that correctly.

pablow: hehe, the main animation using this script is still a wip, and i wanted to keep most of it hidden off the net until i get it done, but ive uploaded a section of it below :3 i post alot of my new 3D model renders on my DA page from my site :open_mouth: nya!

below is an example vid of me using this script(for you pablow :3 ). i’m only animating the mouth and eyes in this, but i have channels for the eyebrows, nose, cheeks and other layers of the face :open_mouth: im still working on this video (this is like 30seconds into the vid and got another 1-2mins after this, half of that ive done and still working on).

http://www.fairytalecomics.com/3d/LenCMVTest3b.jpg

I plan to upgrade this script in the near future to make it a little more useful and easier to use. i prob wont start this til i finish the above animation as im using it to control 2 character’s facial textures. I plan to using this in conjunction with another python script and some stencil masks so that i can control the eye textures from a bone (i intend to be able to move an ‘eyes’ bone and when the texture updates for the render or ingame part, her eyes will move to look at the bone. i think this is possible by comparing angles between 2 bones and choosing the X offset of the eye texture based on this).

I have updated the script at the start of the thread(2ndpost) to correct for a glitch i found while working on my animation. I set the indexing for the channels wrong initially, so it was reading from channel 0 when there was no channel 0. Corrected.

Edit:
i forgot to mention. Blender deletes unused textures you make when you close down, so make sure that when you create all the textures needed for facial animation or whatnot, make sure to click the lil ‘f’ button beside the texture name in the texture window, that way the texture will always stay in the file and wont be deleted on cleanup. I learnt this the hard way lol.

cool demo animation holly, thanks for sharing.

Updated version of this script is now in this thread in Material Node form. This version is much easier to use, more uses than just textures and can be used many times in the 1 material channel. This version (non-nodal version that is) is probably better for use in realtime gaming and glsl textures as teh nodal one seems to be too slow updating than this version. dont know why.

thanks for the script update :slight_smile:

hello,

i have the script working fine in render, but i can’t see changes in viewport until I press the texture buttons. I have material panel opened and GLSL materials activated… I’m doing something wrong?

Thanks a lot!

Enrique

hi nexo,

Ive given the script a bit more testing there now, trying to find a way to make it refresh easier for previewing like you want. after pulling my hair out for a while, i found the solution is simple. After you change frame and have a window open with glsl texture shading on (most usually camera), press f6 ^^ it brings a button window to the texture window and forces a redraw on the textures, so your glsl texture shading window updates to the new textures for a quick preview!

Im kinda fuming, i just read the changelog for blender 2.49 and this script becomes defunct for the gameengine since they have now introduced a new python api to allow you to animate textures in the gameengine. (see the notes here)

This still works fine for use as rendering outside the gameengine (this and the node version of this script), ill look into adapting this with the new api for 2.49 so that you still get the benefits of changing texture channels ingame (unless the new api does this, i need to read up more on it).

Hello Holly, can I ask for a blend having this working for the renderer?
I’m not understanding it well 3_3
No need for complex textures nor models.
Thanks.

hi cloudgl,
sorry for the delay in replying, i was very preoccupied with running part of a convention for the past 2 weeks and havent been paying attention to the forum or had time to work on 3d stuff.

below is a test file i made up quickly from the one i made for the nodal script^^ i have checked and this is working ok, it includes all files needed just in case. just press up or down to go through the frames, use f6 to update the mesh, and you will see the textures change from frames 51 onwards.
http:www.fairytalecomics.com/3d/TexAnimExample.zip

During making this i came across a glitch i really shouldve seen earlier in the script, for selecting the right material channel in the mesh. its working now and i think this script is now as complete as it can be.

remember, f6 forces an update on what you see on screen with the mesh ^^

Hmm… I finally see what you are doing there with switching the channels. It does not refresh on my Windows XP 64 machine with nVidia unless I click the reload button. I am just wondering how this is any better than simply having a PNG image sequence? I guess it gives you the ability to tweak the changes right in Blender (via editing the text script data) rather than having to go back out to a compositing package and re-generate the image sequence.

I get the F6 thing now, too… you have to drag the time line, then repeatedly press F6 to force the update.

sadly that is a flaw in this. blender doesnt give access in python to physically update the textures outside the gameengine, and theres no point using this in the game engine(i think) since the texture nodes can do things. need to check up on that.

why not png sequences?
it saves space (for a highquality texture like the eyes, i only need 3 images whereas imgseq would need an image per frame/ Ximages for X frames at worst. with high quality, the size would be huge), time (i dont need to leave blender to get it to work, i just edit a few frame range values to tweak what happens), gives an almost ‘programmers’ feel to animating (you code in times quickly and easily rather than creating/rebuilding an img sequence outside blender, rather cumbersome working with so many images) and is closer to how animators actually animate little things like that in studios (using still on clear acetate and simply swapping them around for what frames they are on, they dont make a unique image for every frame).

hope that helps^^ im gonna look into the texture node version of this for the gameengine.

Thanks Holly, the file works perfect! Now I understand what does the script and how to use it ^^.