Tutorial Introduction
Ogre Tutorial Head In this tutorial you will learn about overlays - two-dimentional entities in a three-dimentional world. We will also demonstrate how to create the begining of a very simple in-game GUI using overlays.


If you find any errors in this tutorial please send a private message to amirabiri.

Prerequisites

  • This tutorial assumes you have knowledge of C# programming and are able to setup and compile a Mogre application.
  • This tutorial also assumes that you have created a project using the Mogre Wiki Tutorial Framework.
  • This tutorial builds on the previous tutorials, and it assumes you have already worked through them.


Getting Started

As with the last tutorial, we will be using the Mogre Wiki Tutorial Framework as our starting point.

Overview

Overlays are a very simple concept in essence: they are 2D images loaded like any other texture, but instead of being used as part of a mesh, they are simply "layed over" the camera, hence their name.

In fact, you have already seen them - the tutorial framework provides you with a simple HUD (Heads Up Display) - a display of framerate and other information on the bottom left corner of the render window, and the OGRE logo on the bottom right. These are all overlays:

Image

Actually, to be precise both the framerate box an the logo are Overlay Elements, and both of them are parts of the same Overlay. So the more accurate definition is that an overlay is a collection of 2D elements arranged in some fashion on the render window. At any given point multiple overlays can be defined and loaded in Ogre, all of which, some - or none at all - can be visible.

(If you are familiar with GUI programming under Win32 or X in unix, you might already spot the similarities).

Creating Overlays

Creating an overlay is a very simple process. However, before we do that let's add a simple OgreHead to the scene to give us some orientation:

protected override void CreateScene()
{
    mSceneMgr.AmbientLight = ColourValue.White;

    var ogreHeadEntity = mSceneMgr.CreateEntity("OgreHead", "ogrehead.mesh");
    var ogreHeadNode = mSceneMgr.RootSceneNode.CreateChildSceneNode("OgreHead");
    ogreHeadNode.AttachObject(ogreHeadEntity);
}


The first thing we must do is create our overlay object. Add the following code to your CreateScene method:

var overlay = OverlayManager.Singleton.Create("TestOverlay");


If you compile and run this code now you will notice that nothing has changed. An overlay is simply a container. To actually see something we must populate it with elements.

Note that we have given our overlay a name: "TestOverlay". You may have guessed that this name is similar to the node and entity names we used in previous tutorials, i.e this is a simple descriptive string that we can use to later retrieve the same object without having to keep a reference to it. We will use this trait later.

Creating Overlay Elements

So let's add a simple overlay element to our overlay. Add the following code to your CreateScene method:

// Create a panel.
var panel = (PanelOverlayElement)OverlayManager.Singleton.CreateOverlayElement("Panel", "PanelElement");
// Set panel properties.
panel.MaterialName = "Core/StatsBlockCenter";
panel.MetricsMode = GuiMetricsMode.GMM_PIXELS;
panel.Top = 200;
panel.Left = 300;
panel.Width = 250;
panel.Height = 150;

// Add the panel to the overlay.
overlay.Add2D(panel);
        
// Make the overlay visible.
overlay.Show();


Compile and run this code. You should see a simple green rectangle appearing in the middle of your render window. However the green rectangle is displayed "on top" of the scene and is always there. You can move around and rotate the camera and the rectangle will always stay where it is. It's that simple.

Image

So what actually happened here, let's analyze the code. In the first line we created a Panel Element. A panel element is a simple rectangle element that draws one material texture. However the panel element has one other impotant characteristic: it is considered a "Container" element. Container elements are overlay elements that can also contain other overlay elements. This distinction is important because only container elements can be attached to the overlay itself.

This is the reason we had to cast the return value of CreateOverlayElement to PanelOverlayElement which we knew we are going to get back. Normally CreateOverlayElement returns a reference to OverlayElement, which is the base class of all overlay elements, both containers and non-containers. Container elements inherit from OverlayContainer, which inherits from OverlayElement. Confused? Hopefully the following class diagram will help clarify matters:

Image

The polymorphic CreateOverlayElement method returns a reference to the base class, so if we know exactly what we are going to get, and we need a subclass reference, we have to use a cast.

In the following lines of code we set the basic properties of our new panel so that Ogre knows how to render it:

panel.MaterialName = "Core/StatsBlockCenter";
panel.MetricsMode  = GuiMetricsMode.GMM_PIXELS;
panel.Top          = 200;
panel.Left         = 300;
panel.Width        = 250;
panel.Height       = 150;

  • The material name refers to any previously loaded material name, and the texture defined in this material will be displayed as the background of the panel. The material we are using here is the same one used in the framerate box, hence its name.
  • The metrics mode property tells Ogre how we intend to specify the size and location of the element. We chose pixels here.
  • The top, left, width and height properties are simple pixel coordinates telling the top left location and the desired dimensions of the element. This is very similar to other windowing systems or the HTML DOM.


Now that we have a panel object fully set, all there is left to do is attach it to the overlay, and then make the overlay visible. Overlays are set to be hidden when they are created. This is intentional - we are responsible for displaying them when they are ready, rather than having them appear prematurely before we are ready to show them. Again, this is similar to windowing APIs.

// Add the panel to the overlay.
overlay.Add2D(panel);
// Make the overlay visible.
overlay.Show();


Note that the Add2D method only accepts a reference to an OverlayContainer object, which relates to what we explained before about container elements and the need to cast. The method accepts our PanelOverlayElement reference because it is a subclass of OverlayContainer.

Your CreateScene method should now look something like this:

protected override void CreateScene()
{
    mSceneMgr.AmbientLight = ColourValue.White;

    var ogreHeadEntity = mSceneMgr.CreateEntity("OgreHead", "ogrehead.mesh");
    var ogreHeadNode = mSceneMgr.RootSceneNode.CreateChildSceneNode("OgreHead");
    ogreHeadNode.AttachObject(ogreHeadEntity);
        
    var overlay = OverlayManager.Singleton.Create("TestOverlay");

    // Create a panel.
    var panel = (PanelOverlayElement)OverlayManager.Singleton.CreateOverlayElement("Panel", "PanelElement");
    // Set panel properties.
    panel.MaterialName = "Core/StatsBlockCenter";
    panel.MetricsMode = GuiMetricsMode.GMM_PIXELS;
    panel.Top = 200;
    panel.Left = 300;
    panel.Width = 250;
    panel.Height = 150;

    // Add the panel to the overlay.
    overlay.Add2D(panel);
        
    // Make the overlay visible.
    overlay.Show();
}


Note: The transparency in this example is a property of the material, not the overlay or the overlay element. In fact the Ogre/Mogre overlay API doesn't not allow us to tinker with the transparency of overlays or overlay elements unfortunately.

Element Nesting

So if overlay elements can contain other elements, what good is that for us? Well it allows us to build clusters of GUI components and then do things with them as a group. In fact they are very similar to scene nodes in this sense. They are also very similar to controls and windows in a windowing API as we've mentioned before. This is simply a pattern that works well, and has been employed here as well.

Let's add another overlay element inside the one we already have. Add the following code to your CreateScene method:

var childPanel = (PanelOverlayElement)OverlayManager.Singleton.CreateOverlayElement("Panel", "ChildPanelElement");
childPanel.MaterialName = "Core/StatsBlockCenter";
childPanel.MetricsMode = GuiMetricsMode.GMM_PIXELS;
childPanel.Top = 50;
childPanel.Left = 50;
childPanel.Width = 150;
childPanel.Height = 50;
panel.AddChild(childPanel);


If you compile and run this code, you will notice another smaller rectangle inside the previous one. But this still doesn't give us any big advantage. However, if we add the following line:

panel.Left += 200;


And compile and run again the whole panel with the smaller panel inside it now appear more to the right of the render window. This becomes useful when you consider that real overlay GUIs are made of multiple groups of elements. Look at the framerate panel at the bottom left of the render window - it is made of roughly 10 overlay elements.

Overlay Scripts

Although the code above is relatively short and simple, there is an easier way to define the layout and elements of an overlay - overlay scripts. Overlay scripts are simple declarative syntax scripts that Ogre can use to create and set overlays and overlay elements for us. The following overlay script is the equivalent of the code we've written above:

TestScriptOverlay
{
	container Panel(TestScriptOverlay/ScriptPanelElement)
	{
		material     Core/StatsBlockCenter
		metrics_mode pixels
		top          200
		left         300
		width        250
		height       150

		element Panel(TestScriptOverlay/ScriptChildPanelElement)
		{
			material     Core/StatsBlockCenter
			metrics_mode pixels
			top          50
			left         50
			width        150
			height       50
		}
	}
}


Save this script in a file called "test.overlay" under your Media folder (or any other filename with extension ".overlay" for that matter) Ogre will then parse and load it. Now remove or comment out the code from your CreateScene method that sets up the overlay, and replace it with the following code:

var overlay = OverlayManager.Singleton.GetByName("TestScriptOverlay");
overlay.Show();


Compile and run the application. It should continue running and appear exactly the same. However the overlay script is simpler than the verbose code we used before.

let's analyze the syntax of the overlay script.

[Overlay Name]
{
	[Property 1]       [Property Value]
	[Property 1]       [Property Value]
	...

	container [Element Type]([Element Name])
	{
		[Property 1]       [Property Value]
		[Property 1]       [Property Value]
		...

		container|element [Element Type]([Element Name])
		{
			[Property 1]       [Property Value]
			[Property 1]       [Property Value]
			...
		}
		
		...
	}
	
	...
}


An overlay script starts with an overlay name followed by curly brackets. An overlay script may in fact hold multiple overlays if you wish - each one is distinguished by a different name. The body of the overlay definition is simply any number of property settings or child container element definitions you wish to have. Overlay element definitions start with either the keyword "element" or "container", followed by the element type, followed by its name in brackets and finally followed by the element definition inside curly brackets. The element definition is made of multiple property / value pairs, and optionally more child elements.

It's a very simple declarative, curly-braces based syntax. However there are a couple of small things to look out for:

  • Container elements can be declared both as "element" or "container", since they are both. However, if they appear as root elements, or if they contain children they must be declared using the "container" keyword.
  • Elements and overlays must have unique names. If you notice in the above example we chose very different names between the code example and the script example to avoid any potential conflicts. If you try to create two overlays or two overlay elements with the same name, you will get an exception. Unfortunately, as of this writing, that exception is not very descriptive and does not appear in the Ogre.log, so it can get hard to trace. For this reason we use a "namespace" notation in our overlay script where we prefix the name of every element with the names of the elements that contain it. This eliminates any potential ambiguity.

Overlays As GUIs

So now that we've learned how to create overlays, let's do something more "useful" with them. In the following example we will use what we learned in previous tutorials and make a popup appear whenever we press the enter key.

Delete the code you've written so far or start fresh with a new copy of the tutorial framework and add the Ogre head. Make sure that the overlay script you've added is removed or otherwise won't interfere with your work either.

protected override void CreateScene()
{
    mSceneMgr.AmbientLight = ColourValue.White;

    var ogreHeadEntity = mSceneMgr.CreateEntity("OgreHead", "ogrehead.mesh");
    var ogreHeadNode = mSceneMgr.RootSceneNode.CreateChildSceneNode("OgreHead");
    ogreHeadNode.AttachObject(ogreHeadEntity);
}


Now we'll add a keyboard handler as we've seen in previous tutorials:

protected override void InitializeInput()
{
    base.InitializeInput();
    mKeyboard.KeyPressed += new MOIS.KeyListener.KeyPressedHandler(KeyPressedHandler);
}


But before we move on to writing our handler, let's prepare our overlay using an overlay script. Create an overlay script file in your Media folder with the following contents:

HelloWorldOverlay
{
	container BorderPanel(HelloWorldOverlay/MessageBox)
	{
		metrics_mode          pixels
		width                 250
		height                150
		material              Core/StatsBlockCenter
		border_material       Core/StatsBlockBorder
		border_size           1 1 1 1

		element TextArea(HelloWorldOverlay/MessageBox/Body)
		{
			metrics_mode  pixels
			left          125
			top           75
			font_name     BlueHighway
			char_height   16
			alignment     center
			colour        0.5 0.7 0.5
		}
	}
}


This overlay script introduces two new element types:

  • BorderPanel: an overlay element similar to the panel you've seen expect it has a border (which should also be part of the material's image).
  • TextArea: an overlay element that contains text.


Basically we've defined a simple message box window in this script - a simple panel with a border like a GUI window with some text in the middle. However, there are a couple of things missing here still:

  • The message box has no top and left properties defined in the script, which means that if we show the overlay, the box will appear in the top left corner of the render window.
  • The text area element has no text defined for it. We could do it in the script using he "caption" property, but we will do it in code instead.


So now let's add the missing key press handler and "pop up" our message box when the user presses the enter button:

protected bool KeyPressedHandler(MOIS.KeyEvent arg)
{
    if (arg.key == MOIS.KeyCode.KC_RETURN)
    {
        var messageBox = OverlayManager.Singleton.GetOverlayElement("HelloWorldOverlay/MessageBox");
        messageBox.Left = (mWindow.Width  - messageBox.Width)  / 2;
        messageBox.Top  = (mWindow.Height - messageBox.Height) / 2;

        var messageBody = OverlayManager.Singleton.GetOverlayElement("HelloWorldOverlay/MessageBox/Body");
        messageBody.Caption = "Hello World!";
            
        OverlayManager.Singleton.GetByName("HelloWorldOverlay").Show();
    }
        
    return true;
}


What we are doing here is very simple. When the user presses the enter button, we:

  1. Acquire the message box border panel element and position it in the middle of the render window.
  2. Acquire the message box text area element and set its caption property to the message that we would like to display.
  3. Acquire the overlay and display it by calling it's Show method.


Compile and run this code. If you press the enter button, you should see the message popup in the middle of the render window with the message "Hello World". See how simple it is?

Image

Z Order

We've mentioned previously that many overlays can be loaded and displayed at the same time. This immediately triggers the question of which overlays should appear above others and which should appear "below" or "behind" other overlays. This is where Z-Order comes in.

Again, you might be familiar with this concept from other areas as it is also very common. The idea is very simple: each overlay has a property called "Z Order" Which is a simple numeric value (in Ogre this value limited to the range of 0 to 650). The higher the number, the "closer" the overlay is to the camera. This does not affect the overlay's size or shape, it simply means that an overlay with a Z Order of 500 will appear above an overlay with a Z Order of 400, if they happen to appear in the same part of the render window.

Let's demonstrate this with a simple example. A common practice in first person shooter games is to flash the screen red when the player character is hit. We will create this effect in our program when the user presses the spacebar button using an overlay.

Add the following overlay definition to your project (you can either add it to a new .overlay file in your Media folder, or to an existing one).

Red
{
	zorder 650
	
	container Panel(Red/Panel)
	{
		width                 1
		height                1
		material              Red
	}
}


This very simple overlay simply covers the whole render window in a red transparent color using the "Red" material which is included in the tutorial framework's Media folder. Note that we've given it a Z order value of 650 - the highest possible Z order value.

Another thing that this script demonstrates is how to use the "relative" metrics mode, which is also the default mode (which is why we have omitted the property altogether). In "relative" mode coordinates are measured in a relative float value between 0 and 1. This value is in turn translated to pixels relative to the current resolution. The result is an overlay element that maintains the same visual size in the render window in all resolutions. Therefore values of 1,1 for width and height mean the full size of the render window.

All we have left to do now is to show this overlay for a short period of time when the user presses the space button. Let's add a simple timer member variable to our tutorial class as we've seen before:

float mHitTimer = 0;


And now let's add some code to our input handler that displays the red overlay if the key is the space key. Add the following code to your KeyPressedHandler method (before the return statement, of course):

if (arg.key == MOIS.KeyCode.KC_SPACE)
{
    OverlayManager.Singleton.GetByName("Red").Show();
    mHitTimer = 1;
}


We want the red flash to appear briefly for one second, so we need a frame listener that will implement this. As you've seen in previous tutorials, frame logic can be easily defined in the tutorials framework in an overridden UpdateScene method:

protected override void UpdateScene(FrameEvent evt)
{
    if (mHitTimer > 0)
    {
        mHitTimer -= evt.timeSinceLastFrame;
        if (mHitTimer <= 0)
            OverlayManager.Singleton.GetByName("Red").Hide();
    }
}


And that's it. Compile and run this code. If you hit the spacebar button, you should see a brief red flash all over the render window:

Image

Now press the enter key to show the message box and hit the spacebar button again:

Image

The red overlay which has the highest possible Z order value, higher than the default which the message box overlay would have, appears above the message box. Therefore the red flash covers the message box as well.

If instead we gave the message box overlay the higher value, what would happen? Modify the overlay script(s) so that the red overlay has a lower value than the message box:

Red
{
	zorder 600 // lower this value from 650 to 600.
	
	container Panel(Red/Panel)
	{
		width                 1
		height                1
		material              Red
	}
}

HelloWorldOverlay
{
	zorder 650 // Add this line
	
	container BorderPanel(HelloWorldOverlay/MessageBox)
	{
	...


If you run the code again, this time the message box should appear "above" the red flash. It is as if the Game's GUI is detached from the character's vision, which in turn is covered in red haze by the pain:

Image

Overlay Templates

In all examples so far we created the overlays we needed and used them. However, at some point you will start seeing certain patterns repeat themselves in your overlay definitions. These patterns could represent a "theme" which you may want to swap, or simply represent basic common settings.

One simple option is to repeat these property assignments everywhere. Another is to create methods that generate overlay elements based on some parameters. But there is actually another powerful tool in Ogre/Mogre's overlay system to accomplish this: overlay templates.

Overlay templates, as the name implies, are not real overlays but rather they are templates that can be used to create other elements from, but are not rendered themselves. It is possible to inherit new overlay elements from previously defined templates.

Let's look at an example. Start again from a fresh copy of the code or delete your current changes:

protected override void InitializeInput()
{
    base.InitializeInput();

    mKeyboard.KeyPressed += new MOIS.KeyListener.KeyPressedHandler(KeyPressedHandler);
}

protected override void CreateScene()
{
    mSceneMgr.AmbientLight = ColourValue.White;

    var ogreHeadEntity = mSceneMgr.CreateEntity("OgreHead", "ogrehead.mesh");
    var ogreHeadNode = mSceneMgr.RootSceneNode.CreateChildSceneNode("OgreHead");
    ogreHeadNode.AttachObject(ogreHeadEntity);
}

bool KeyPressedHandler(MOIS.KeyEvent arg)
{
    return true;
}


In this example we will create multiple message boxes. Each time the user presses the enter button, we will create a message box with a random number for its contents, in a random location on the render window.

First we need a simple overlay to place all these message boxes on. Add the following code to your CreateScene method:

var overlay = OverlayManager.Singleton.Create("TestOverlay");
overlay.Show();


Next we will create a simple template of a panel which contains a text area, similar to our previous message boxes except without a border. In code, templates are created with the same CreateOverlayElement method of the OverlayManager Singleton, except the last argument we pass is set to true, which tells the method that it is a template and not an overlay element. Later we will see how to define templates in overlay scripts. For now add the following code to your CreateScene method:

var msgBoxTpl = (PanelOverlayElement)OverlayManager.Singleton.CreateOverlayElement("Panel", "Templates/MessageBox", true);
msgBoxTpl.MaterialName = "Core/StatsBlockCenter";
msgBoxTpl.MetricsMode = GuiMetricsMode.GMM_PIXELS;
msgBoxTpl.Width = 250;
msgBoxTpl.Height = 150;
var text = (TextAreaOverlayElement)OverlayManager.Singleton.CreateOverlayElement("TextArea", "Templates/MessageBox/Body", true);
text.MetricsMode = GuiMetricsMode.GMM_PIXELS;
text.Left = 125;
text.Top = 75;
text.FontName = "BlueHighway";
text.CharHeight = 16;
text.SetAlignment(TextAreaOverlayElement.Alignment.Center);
text.Colour = new ColourValue(0.5f, 0.7f, 0.5f);
msgBoxTpl.AddChild(text);


This code creates a template of a panel element called "Templates/MessageBox", sets its properties, and adds a text area called "Templates/MessageBox/Body" in the middle of it.

We can now define our input handler. If the pressed key is enter, we will generate a random message (a number) and place a new message box in a random location on the screen. Add the following code to your KeyPressedHandler method before the return statement:

if (arg.key == MOIS.KeyCode.KC_RETURN)
{
    var rand = new System.Random();
    var id = rand.Next();
    var newbox = (BorderPanelOverlayElement)OverlayManager.Singleton.CreateOverlayElementFromTemplate("Templates/MessageBox", "BorderPanel", "MessageBox" + id);
    newbox.Left = rand.Next((int)mWindow.Width - 250);
    newbox.Top = rand.Next((int)mWindow.Height - 150);
    newbox.GetChild("MessageBox" + id + "/Templates/MessageBox/Body").Caption = id.ToString();
    OverlayManager.Singleton.GetByName("TestOverlay").Add2D(newbox);
}


What this code does is very simple: First, it generates a random ID for the new message box. Then it creates a new overlay element based on the template we defined previously by using the CreateOverlayElementFromTemplate method. It then sets the left and top values of the newly created element randomly, and sets the caption of the text area to the generated ID. Finally it attaches the new element to the overlay we created before so that it is displayed.

Note that CreateOverlayElementFromTemplate requries us to supply a new unique name for the new element that will be created. We simply used the string "MessageBox" followed by the random ID that we have generated. However, note what happens next - every new child element copied from the template gets this same name prefixed to its name. So the text area that is named "Templates/MessageBox/Body" in the template, is named "MessageBoxrandom id/Templates/MessageBox/Body". Ogre's uses the same slash-based notation internally to prefix names of elements created this way, so the notation we used isn't completely arbitrary.

That's all there is to creating overlay templates, as you can see it's pretty simple in essence. As we mentioned previous it is possible to also define templates in overlay scripts, which is preferable of course if we use overlay scripts for our overlays anyway. Here is the overlay script equivalent of the above:

template container Panel(Templates/MessageBox)
{
	metrics_mode          pixels
	width                 250
	height                150
	material              Core/StatsBlockCenter

	element TextArea(Templates/MessageBox/Body)
	{
		metrics_mode  pixels
		left          125
		top           75
		font_name     BlueHighway
		char_height   16
		alignment     center
		colour        0.5 0.7 0.5
	}
}


The differences are very simple:

  1. The "template" keyword precedes the "container" or "element" keywords.
  2. Overlay templates don't need to be enclosed in an overlay, they can be defined at the top level of the overlay script.


In addition to using templates from code, we can also use them in the overlay scripts themselves. They can be used as "base classes". Here is an example:

template container BorderPanel(BaseWindow)
{
	metrics_mode          pixels
	width                 250
	height                150
	material              Core/StatsBlockCenter
	border_material       Core/StatsBlockBorder
	border_size           1 1 1 1
}

HelloWorldOverlay
{
	container BorderPanel(HelloWorldOverlay/MessageBox) : BaseWindow
	{
		element TextArea(HelloWorldOverlay/MessageBox/Body)
		{
			metrics_mode  pixels
			left          125
			top           75
			font_name     BlueHighway
			char_height   16
			alignment     center
			colour        0.5 0.7 0.5
		}
	}
}


At the top of this overlay script we define a template called "BaseWindow", which as the name implies defines the base properties common to any window we may want to use. Then we create our familiar messagebox. We inherit the BaseWindow properties by using the ":" operator, and then move on to define the unique characteristics of he message box, including additional sub-elements.

Conclusion

In this tutorial we have covered almost all aspects of using overlays in Mogre/Ogre. At this point you should be able to add HUDs to your applications using overlays, and even produce a basic GUI if you wish. However, for a real in-game GUI you should look into dedicated libraries like Myiagi or MyGUI.

<HR>
Creative Commons Copyright -- Some rights reserved.


THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

  • "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
  • "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
  • "Licensor" means the individual or entity that offers the Work under the terms of this License.
  • "Original Author" means the individual or entity who created the Work.
  • "Work" means the copyrightable work of authorship offered under the terms of this License.
  • "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
  • "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.

2. Fair Use Rights

Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.

3. License Grant

Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

  • to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
  • to create and reproduce Derivative Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
  • For the avoidance of doubt, where the work is a musical composition:
    • Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
    • Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
    • Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).


The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.

4. Restrictions

The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

  • You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
  • You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
  • If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability.

EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

  • This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
  • Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

  • Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
  • Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
  • If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
  • No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
  • This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.