bw logo

Chapter 3. Dynamically loading resources

There are times when you will need to dynamically load resources for an entity, instead of just when they enter the world. This might be due to a property change causing the entity's model to change, or perhaps the entity switches an item it is holding to one not yet seen before. In these cases, you will need to load and display a new model or other resource, and you will need load them in the background thread.

The BigWorld.loadResourceListBG() method works just like a dynamic version of Entity.prerequisites, it returns an object which existence ties the lifetime of the requested resources to itself. The actual resource loaded can be retrieved from the PyResourceRefs instance that is passed into the callback function. The types of Python resources that can be retrieved are:

  • Models ( type : PyModel )

  • Particle Systems ( type : PyMetaParticleSystem)

  • Textures ( type : PyTextureProvider )

  • XML files ( type : PyDataSection )

  • FX files ( type : PyMaterial )

The Pixie.loadBG method can be used to asynchronously load a PyMetaParticleSystem. For details on this method, see the Client Python API.

Additionally BigWorld.loadResourceListBG() can be used to hold onto C++ only resources, when you know that these are causing a problem. Here are the following types that can be loaded, and held onto, but not retrieved in Python:

  • Visuals

  • Lens Effects

3.1. Using Entity.prerequisites and BigWorld.loadResourceListBG()

The BigWorld.loadResourceListBG() method is useful for more complicated entities. For example, say you have an entity that can change its look at anytime to any of a large number of combinations. In this case, you can setup your initial look using prerequisites, but there is no way of knowing at which resources will be required in the future.

In order to implement this case, load the model asynchronously when needed, as in the following example:

class PickableFlower( BigWorld.Entity ):
  ASSETS = {
    'lili' : ('models\lili.model', 'effects\sparkles.xml')
    'daisy' : ('models\daisy.model', 'effects\spirits.xml')
    'orchid' : ('models\orchid.model', 'effects\petals.xml')
  }

  PICK_SOUND = 'sounds\pick_flower.wav'

  def __init__(self):
    pass


  # This event handler is called after the entity is initialised,
  # and its initial properties have been set.  We should return
  # a list of resources that must be loaded into memory before
  # onEnterWorld is called.
  def prerequisite(self):
    prereqs = []
    prereqs += PickableFlower.PICK_SOUND
    prereqs += PickableFlower.ASSETS[self.type]
    return prereqs


  # This event handler is called when the entity is first visible to
  # the client, and when the prerequisite resources have been loaded.
  # The prerequisites parameter is a PyResourceRefs instance, and
  # can be used both to access the loaded resources, and to manage
  # their lifetime.
  def onEnterWorld(self, prerequisites):
    self.set_type(-1, prerequisites)


  # This event handler is called whenever the entity type property
  # is changed.  This can occur at anytime.  If we are calling this
  # directly from onEnterWorld, the resources are already loaded and
  # we can use them directly.  Otherwise we must queue up an
  # asynchronous load of the required resources.
  def set_type( self, old_type, prerequisites = None ):
    if self.type != old_type:
        if prerequisites == None:
            resourceList = PickableFlower.ASSETS[self.type]
            BigWorld.loadResourceListBG( resourceList, self.onLoad )
        else:
            self.onLoad( prerequisites )


  # This user-defined callback function is called either when the
  # loadResourceListBg method has finished, or is called by ourselves
  # from enterWorld.
  def onLoad( self, resourceRefs ):
    self.model = resourceRefs[ PickableFlower.ASSETS[self.type][0] ]
    self.particles = resourceRefs[ PickableFlower.ASSETS[self.type][1] ]
    self.model.root.attach( self.particles )


  def onPickEvent(self):
    # picking sound effect is constant between types
    self.model.playSound(PickableFlower.PICK_SOUND)
    self.particles.force(1)

Asynchronously loading the model