Hello BA!
In most of my games I need to use animated textures, there are an function in blender to do this under the UV/Image Editor… this feature do however (according to me) suck. It gives you no control at all. This is why I have implemented an script/python library to do this exact thing, scroll and animate textures.
as for now my script allows the user to control:
- start frame/position [updated in V1.1]
- Direction [updated in V1.1]
- set speed
- change speedusing prop [NEW/updated in V1.1]
- set frame (only in python)
- Turn On/Off in real-time (controlled on the parent OR the main object) [NEW in V1.1]
The library are implemented so that multiply objects can use the same script without interfering.
Here is an guide on how to setup my UV scroll script (this guide requires basic knowledge of blender GE):
Step 1:
add an new plane (or any other object, but plane is most easy)
Step 2:
unwrap the plane
… load an sheet-image (or any image) in the UV/Image editor and position the UV-map so that it covers the bottom left square/corner of your image (as shown in the image below) THIS PART IS IMPORTANT!
Step 3:
give your plane an material (set it up as you like), go to the texture tab and add the texture. Set the texture to use the UV map that you made earlier (as in scream below):
Step 4:
open the Text Editor, create an new Text Datablock and name it UVScroll.py
past this code in the text Datablock:
#########################################################
#UV scroll by Tony Eriksson (esoneson on blenderartists)
#Use it as you like, to whatever you like, just keep this credit.
#...and if you like it, tell me :)
#########################################################
from bge import logic as GL
scrollers = {} #global dictionary to keep track of all the objects using uv-scroll
#the function to run from the bge
def Scroll_Object():
global scrollers
cont = GL.getCurrentController()
own = cont.owner
if own in scrollers: #if alredy in dictionary, run scroll function
scrollers[own].ScrollUV()
else: #if NOT in dictionary, add to dict and run needed functions
inv = False
speed = 1
if 'Invert' in own:
inv = own["Invert"]
if 'Speed' in own:
speed = own["Speed"]
scroller = Scroller(own["X"],own["Y"],own["X_Start"],own["Y_Start"],inv,speed)
scrollers[own] = scroller
scroller.firstRun()
scroller.SetStartPosition()
scroller.ScrollUV()
#the Scroller class, this is where the magic happens
#it is called as an object by the scroll_object function
class Scroller:
#init the scroller by setting needed values
def __init__(self, MX, MY, CX=1, CY=1, Inv=False,speed=1):
self.MaxX = MX
self.MaxY = MY
self.Invert = Inv
self.CurrentX = CX
self.CurrentY = CY
self.Speed = speed
self.StandardX = list()
self.StandardY = list()
self.CStep = 1
self.cont = GL.getCurrentController()
self.own = self.cont.owner
self.mesh = self.own.meshes[0]
self.array = self.mesh.getVertexArrayLength(0)
self.GotSensor = self.selfSensorChek()
#sets the speed of the scroll
def SetSpeed(self,Speed):
self.Speed = Speed
#Updating the invert chek
def UpdateInvertValues(self):
try:
self.Invert = self.own["Invert"]
except:
pass
#checking if the scroll are to be run
#return true if it is, else false
def Speed_f(self):
self.UpdateInvertValues()
if self.CStep >= self.Speed:
self.CStep = 0
return True
else:
self.CStep += 1
return False
#set the start position of the UV
def SetStartPosition(self):
for v in range(0,self.array):
vert = self.mesh.getVertex(0,v)
uv = vert.getUV()
uv[0] = self.StandardX[v] + ((1/self.MaxX) * (self.CurrentX-1))
uv[1] = self.StandardY[v] + ((1/self.MaxY) * (self.CurrentY-1))
vert.setUV(uv)
#getting the StandardX and StandardY values, this need to be run before any other UV operation
#(only need to be run once on every object)
def firstRun(self):
for v in range(0,self.array):
vert = self.mesh.getVertex(0,v)
uv = vert.getUV()
self.StandardY.append(uv[1])
self.StandardX.append(uv[0])
#This function are locking for the Controller prop in the Parent of this object
#returns 1 if the controller don't exist, 2 if the controller is False and 3 if it is True
def ParentSensorChek(self):
try:
if 'Controller' in self.own.parent:
if self.own.parent["Controller"] == True:
return 3
else:
return 2
else:
return 1
except:
return 1
#checking if the prop Controller exists , and if so, what value it holds
#returns 1 if the controller don't exist, 2 if the controller is False and 3 if it is True
def selfSensorChek(self):
try:
if self.own["Controller"] == True:
return 3
else:
return 2
except:
return 1
#the UV scroll function, this function uses the other functions in this class to move the uv.
#NOTE: the uv movement is based on percentage of the texture
def ScrollUV(self):
if self.Speed_f():
goon = 1
if self.GotSensor != 1:
if self.selfSensorChek() == 3:
goon = 3
else:
goon = 2
if goon == 1:
if self.ParentSensorChek() != 2:
goon = 3
if goon == 3:
for v in range(0,self.array):
vert = self.mesh.getVertex(0,v)
uv = vert.getUV()
if self.Invert == False: #is the uv scroll inverted?
if self.CurrentX < self.MaxX:
uv[0] += (1/self.MaxX)
else:
uv[0] = self.StandardX[v]
if self.CurrentY < self.MaxY:
uv[1] += (1/self.MaxY)
else:
uv[1] = self.StandardY[v]
else:
if self.CurrentX > 1:
uv[0] -= (1/self.MaxX)
else:
uv[0] = self.StandardX[v] + (1/self.MaxX)*(self.MaxX-1) #?
if self.CurrentY > 1:
uv[1] -= (1/self.MaxY)
else:
uv[1] = self.StandardY[v] + (1/self.MaxY)*(self.MaxY-1) #?
vert.setUV(uv)
if self.Invert == False: #is the uv scroll inverted?
if self.CurrentX < self.MaxX:
self.CurrentX += 1
else:
self.CurrentX = 1
if self.CurrentY < self.MaxY:
self.CurrentY += 1
else:
self.CurrentY = 1
else:
if self.CurrentX > 1:
self.CurrentX -= 1
else:
self.CurrentX = self.MaxX
if self.CurrentY > 1:
self.CurrentY -= 1
else:
self.CurrentY = self.MaxY
as shown in the image below (see next post):