This is a simple example of texture switching. Most people want to do material switching, as do I, but that feature isn’t in Blender. So, there are 3 ways around it.
Make multiple meshes and use the Replace Mesh actuator (is there a replaceMesh Python function? I don’t recall). Pros: You have control over the materials and textures present on the mesh (right?). Cons: You have to make a duplicate mesh for each outfit; if you want to change something later, like change the way his elbow moves, you have to do so for all duplicated meshes.
Use 1 material and 1 texture, but use multiple UV-maps on that texture (i.e. 3 outfits on the same texture) and switch between them by moving the UV-maps around. Pros: It should work fine. Cons: It would quickly require a huge texture - if one outfit is 512x512 and you want five for the player, that would quickly become a problem.
The third way is the way that’s outlined here. Basically, you use the VideoTexture module to load an outside image, and the UV-maps stick with the mesh, meaning that you could have a hundred different player outfits, and load them each when necessary. It works very well, though there are some downsides.
The only real problem is that the textures present MUST be in an external directory - they can’t be packed in with the blend, because the VideoTexture module only loads outside files. If someone knows a way to load internal blend textures, then that would be ideal, but this method still works fine. Anyway, here’s the zip file (it includes two textures that I’m giving away to the public, free of charge, for any use, including commercial use. I know it’s simple, but hey, it’s free.)
Press A or S to switch textures. It will only update when you change texture, and that’s indicated by the obj[‘change’] variable. This works in Blender 2.5, not 2.49.
EDIT: Just tried it out, but textureObj for the Texture constructor in the VideoTexture module only works for other VideoTexture.Texture objects, not internal Blender textures. This method still works well as you don’t need to manually open each texture for external files - you could even make a game in which the player can design a character or texture for an object in-game…
There always seems to be a catch with whatever system I’ve tried.
Only mesh replace works consistently.
UV scroll won’t work on a rigged character- as far as Ive found.
And the video texture module… I heard that it is not included with the blender player. I.e. you can’t use it in
saved runtimes. Is it true?
actually you can switch any texture channel you want so you can replace also the specular channel :
# if you have more than 1 material on the mesh and you want to
# modify a texture of one particular material, get its ID
matID=VideoTexture.materialID(gameobj,"MAmat.001")
# GLSL material can have more than 1 texture channel, identify
# the texture by the texture slot where it is defined, here 2
tex=VideoTexture.Texture(gameobj, matID, 2)
I love just about everything about it, but i’m having trouble trying to get the script to work for other objects, even though i have my objects with all the same settings, can you please tell me how the texture was applied or anything else that might change the way the script behaves?
Thanks. Is the problem that the texture’s aren’t showing up at all? Do you see any errors in the console?
EDIT: Line 36 of the script specifies that it uses the material named “MAFace”. Blender cuts off the ‘MA’ part in the game engine, which you can see by the fact that the material for the red cube character in the example blend has a material named “Face”. You need to change that name to the name of your object’s material.
EDIT 2:You can change it to the name of the image with ‘IM’ in front of it, if that helps matters.
thank you, that was the problem (i didn’t know about the MA-originalimagenamehere- thing, so it just said MAFace in the data still, but item001 for the material, XD) thanks or the help
ug, i’m not having a slightly different problem. i edited the code so that it got the material id from a variable on the object that the controler is on so that i could use the script for multiple items, but it still changes ALL of the objects materials.
Yeah, that’s the way it works - it replaces the image for the material. There’s not really a fix for it - if you want to load different materials on different objects (especially duplicated ones), I would recommend making the meshes that you need and using replaceMesh() or the Replace Mesh actuator.
Actually this code can be optimized quite a bit, like this(for 2.49b):
import GameLogic as g
import VideoTexture
cont = g.getCurrentController()
obj = cont.owner
if not 'texture' in obj:
mat = VideoTexture.materialID(obj, 'IMEmptyText.png')
obj['texture'] = VideoTexture.Texture(obj, mat)
obj['files'] = ['Img1.png','Img2.png']
obj['DFrame']=0
path = g.expandPath('//'+obj['files'][obj['DFrame']])
obj['texture'].source = VideoTexture.ImageFFmpeg(path)
obj['texture'].refresh(True)
It is using two key sensors to switch a list of textures and the always sensor pulse mode is off which makes the script runs faster.
Here is the example
Here’s a sample of the code. It’s the same that’s in the blend file at the top, as it works fine in Blender 2.61
##############################
# #
# Realtime Texture Switching #
# #
# Author: SolarLune #
# Date: 11/16/10 #
# #
# You may use this script #
# however you wish for free, #
# including commercial, #
# educational, personal, etc.#
# #
##############################
# Use A and S to switch textures.
# This method works very well, except
# for the fact that the textures can't
# be included in the blend file; they have
# to be in an external directory
import bge
from bge import logic
from bge import events
import VideoTexture
cont = logic.getCurrentController()
obj = cont.owner
k = logic.keyboard
a = k.events[events.AKEY]
s = k.events[events.SKEY]
if not 'texture' in obj:
mat = VideoTexture.materialID(obj, 'MAFace')
obj['texture'] = VideoTexture.Texture(obj, mat)
obj['file'] = 'Sad.png'
obj['changed'] = 0
else:
if obj['changed']:
path = logic.expandPath('//'+obj['file'])
obj['texture'].source = VideoTexture.ImageFFmpeg(path)
obj['changed'] = 0
obj['texture'].refresh(True)
if a == 1:
obj['file'] = 'Happy.png'
obj['changed'] = 1
elif s == 1:
obj['file'] = "Sad.png"
obj['changed'] = 1