Thumbnail Tutorial

Abstract

Lets create a display that show a thumbnail based off a path contained in the current hoverTarget.

Prerequistes

Hover Text
Child by Name
Texture Change
Oop in Bge

Set Up

Download these four images and place them in the same directory as the .blend file. Keep the images fairly small for performance reasons. You can also precache the images to some extent by preconditioning the paths into ffObj, and passing the ffObjs to textureChange instead. Create a python file called thumb.py containg the provided code in the aforementioned directory.
square.png circle.png triangle.png x.png
Set up the scene like in the Hover Text tutorial. Give the three objects a new property.
thumb string path
Path should be either //square.png, //circle.png, or //triangle.png. Depending on the object.
thumbnail-tutorial-img0.png
Goto the Hud scene and make a plane. Uv unwrap the plane and give it a unique material, texture and image. The material should be shadeless, and have alpha transparency turned on and set to zero. The image source should be //x.png. They can all share the same image source, but you must make sure every thumbnail has a unique material, texture and image! The plane should have the following logic bricks.
Always -> thumb.sub
Message -> thumb.message
Message should have the Subject hoverTarget.
thumbnail-tutorial-img1.png

Code

import bge
import jsonCoder as json
# This could be changed to the Extended Expand Path.
# http://upbge.wikidot.com/extended-expand-path-tutioral
from bge.logic import expandPath
 
class ThumbNail(bge.types.KX_GameObject):
 
  def __init__(self, DNU):
    # self._source gets checked before its set so we need to set it here.
    self._source = None
    # We still set self.source because it makes the thumb invisible.
    self.source = None
 
  def message(self, subject, body):
    if body:
      path = body['thumb']
      path = expandPath(path)
      # Set the source as a path.
      self.source = path
    else:
      # If the received source is None, turn the thumb off.
      self.source = None
 
  @property
  # The underscore means that its an internal property that probably shouldn't be changed manually.
  def source(self):  return self._source
  @source.setter
  def source(self, ffObj):
    # Changing the image can take significant time.  Don't do it unless the image actually changes.
    if self._source != ffObj:
      self.textureChange(ffObj)
      # We store a reference to ffObj so that we can check to see if it changes.
      self._source = ffObj
 
    # If passed a None type turn off the thumb.
    if ffObj:  self.visible = True
    else:  self.visible = False
 
  # Boiler Plate
 
  # http://upbge.wikidot.com/texture-change-tutorial
  def textureChange(self, ffObj, matId=0, textuId=0, scale=None, swap=False):
    """
    changes the texture of an object
    ffObj can be a strPath, ffobj, or npArry
    Make shure self has an uniqe mesh, material, texture, and image.
    Passing the original image causes blackness
    scale is 'x' or 'y'.  scales the objs x axis so that it fits the new textures ratio
    swap switchs axises to fix the eulid scanline debate
    places the texture in a weirdly named property on the object
    """
    def doScale(scale):
      if scale == 'x':  self.localScale.x = ffObj.size[0] / ffObj.size[1]
      elif scale == 'y':  self.localScale.x = ffObj.size[1] / ffObj.size[0]
      else:  raise Exception("My hovercraft is full of eels")
 
    name = 'newTextu'+';'+str(matId)+','+str(textuId)
 
    # if its None
    if id(ffObj) == id(None): # np weirdness
      try:  del self[name]
      except KeyError:  pass
      return True
 
    # if its a path string
    try:  ffObj = bge.texture.ImageFFmpeg(ffObj)
    except TypeError:  pass
 
    self[name] = bge.texture.Texture(self, matId, textuId)
 
    # if its a ffObj
    try:
      self[name].source = ffObj
      self[name].refresh(False)
      if scale:  doScale(scale)
      return True
    except TypeError:  pass
 
    # assume its an npArray
    self[name].source = bge.texture.ImageBuff()
    self[name].source.filter = bge.texture.FilterRGBA32()
    if swap:
      from numpy import swapaxes
      ffObj = swapaxes(ffObj, 0, 1)
    buf = bytearray(ffObj)
    self[name].source.load(buf, ffObj.shape[0], ffObj.shape[1])
    self[name].refresh(False)
    if scale:  doScale(scale)
 
  # http://upbge.wikidot.com/child-by-name-tutorial
  def child(obj, child):
    name = obj.name.split('.')
    try:    suffix = '.'+name[1]
    except IndexError: suffix = ''
    return obj.childrenRecursive[name[0] +' '+child+ suffix]
 
# http://upbge.wikidot.com/oop-in-bge-tutorial
BASE_CLASS = ThumbNail
JSON_CODER = json
SEN_MESSAGE = 'Message'
 
def sub(cont):
  self = cont.owner
  if isinstance(self, BASE_CLASS):  return self
  else:  return BASE_CLASS(self)
 
def message(cont):
  sen = cont.sensors[SEN_MESSAGE]
  for i in range(sen.frameMessageCount):
    subject = sen.subjects[i]
    body = sen.bodies[i]
    body = JSON_CODER.loads(body)
    cont.owner.message(subject, body)

Questions

Log in and edit this page to ask and answer questions.

Further Reading

Extended Expand Path

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License