Skip to content

Content Substitution

Cole Campbell edited this page Mar 3, 2018 · 2 revisions

As part of its support for cross-platform development, version 1.1 of the Ultraviolet Framework introduced content substitution, which allows an instance of ContentManager to automatically substitute one asset for another depending on the properties of the runtime operating environment.

DPI Substitution

Currently, the only variable which Ultraviolet cares about when performing content substitution is the display's pixel density, measured in dots per inch (DPI). Following the conventions set by Android, Ultraviolet places each display into one of a number of "density buckets" which represent a range of DPI values. These buckets are exposed by the ScreenDensityBucket enumeration:

public enum ScreenDensityBucket
{
    Desktop,
    Low,
    Retina,
    Medium,
    RetinaHD,
    High,
    ExtraHigh,
    ExtraExtraHigh,
    ExtraExtraExtraHigh,
}

As mentioned previously, most of these buckets match those used by Android; see the Android documentation for more information on the DPI ranges that they encompass.

Each of the above density buckets has a corresponding "short name" which is used when performing content substitution. These are:

  • pcdpi
  • ldpi
  • retina
  • mdpi
  • retinahd
  • hdpi
  • xhdpi
  • xxhdpi
  • xxxhdpi

When Ultraviolet loads a content asset, it will check to see if there are any possible alternative versions of that asset which are a better match for the current DPI. It does this by looking for copies of the asset which have the same name, but which are also suffixed with a DPI name.

As an example, consider the following directory, which contains an asset called Example.png:

  • Textures
    • Example.png
    • Example-hdpi.png
    • Example-xhdpi.png

Assume that we are loading the asset for a display in the ExtraHigh density bucket. When we call content.Load<Texture2D>("Textures/Example"), Ultraviolet will check for the existence of the following assets, in order:

  1. Textures/Example-xxxhdpi
  2. Textures/Example-xxhdpi
  3. Textures/Example-xhdpi

Since Textures/Example-xhdpi is the first asset which actually exists, Ultraviolet will stop there. Otherwise, it would continue to search through each of the density buckets before eventually giving up and loading Textures/Example.png if no DPI-specific assets could be found.

Note that substitution is only performed if no file extension is specified in Load<T>(); specifying a fully-qualified file name will always retrieve exactly the file that was specified.

Per-Display DPI Awareness

If necessary, Ultraviolet can simultaneously load multiple versions of each asset for various screen densities. You can force a content manager to load a specific version of an asset using the overloads of the Load<T>() method which take a ScreenDensityBucket value as a parameter.

The Ultraviolet Presentation Foundation makes use of this functionality to automatically adjust its assets when views are moved between displays on a system with multiple monitors.

Clone this wiki locally