Our simulator is no different than most games in that it has two main "states": "{LEX()}GUI{LEX}" and "Game". However, one of the most confusing topics in the history of Ogre and {LEX()}CEGUI{LEX} that I have run across is in fact getting the two to work together. It actually is fairly straightforward, but there are so many incomplete examples and out-of-date articles and uneducated forum posts on it that it took me 5 times as long as it should have to get it working.

First off, the CEGUI example in this Wiki: forget it. Or at least the part that deals with {LEX()}RTT{LEX} (Render To Texture). It's unused in the example and serves only to confuse the issue hopelessly. In fact, there are only about four lines of code needed to load a GUI into an Ogre window.

But before you do that, you need to create the GUI first. If you are not picky, you can easily use the TaharezLook widget set and not worry about it. It's complete, fairly sharp and it works. For the time being, while our team is working on our project's look and feel and layouts, I am using the TaharezLook set for placeholder development of the two-state execution mentioned above, and I will gladly share with you what knowledge I painfully learned during the past few days.

First, a note about our simulator design. The first thing that happens on startup is the GUI is displayed, at the "Welcome" screen. Ours for now just has a few buttons which lead to other pages (Options) or perform command actions ("Instant Action", Quit). The Instant Action button takes the user to a page deeper in the navigational map (you do have one for your game, correct?) where he or she can select a mission or whatever to join or play. How you obtain the list of levels or missions available for your game is entirely up to you. We currently do it by reading each file in the "resource/missions" folder and obtaining the header data to populate a dropdown list of missions. You might simply use a manifest file that contains the mission names and associated filename, or you may have a completely different solution. It's up to you.

Later you will see that we use multiple scene managers. Why? Each mission will be built to use a particular scene manager, depending on whether the user is in the great outdoors, inside a cave or building, or on an aerospace or outerspace mission. The reason that the scene manager plugin system is present in Ogre is that no one single scene manager implementation is the best for all types of scenes, and as we will see, switching between them at runtime is fairly simple.

CEGUI

CEGUI is the "official" Ogre GUI library. While Ogre has 2D functionality, it quickly became apparent that going much further than simple overlays was "out of scope" and CE's GUI system was adopted. If you have not already, you should get CEGUI from the CEGUI website.

Find the "datafiles" directory in either the source tree or wherever in the binary distribution (or in the root directory of the CELayoutEditor download install), and look for the layouts/ directory. Each file you find there is a descriptions of the layout for an entire GUI page (sheet). While you certainly can create a GUI layout in code (and there are plenty of reasons why you might want to), you don't have to. 99% of CEGUI users can happily create only layout files and never create a single window in code. After all, as you'll see, the layout simply loads into a window like any other CEGUI window and can be treated no differently than any other.

The scheme referenced in each widget name (i.e. "TaharezLook/EditBox" is an EditBox in the TaharezLook scheme) can be found in the schemes/ directory, which in turn references an imageset in the imagesets/ directory, which in the end is nothing more than a glorified HTML imagemap concept: each widget (and widget state) is mapped from the TGA image for that scheme using a four-corner rectangular mapping notation. Review the files and you'll see how it all works together. I have to confess I've not delved too deeply into the looknfeel/ directory stuff, but it appears simply to address, not surprisingly, the look and feel and behavior of each widget in the scheme.

While you are there, as discussed before, feel free to remove the relative pathnames wherever you find them (i.e. "../datafiles/..."); since we provided the location of all of our resources to the ResourceManager during initialization, we don't need to keep track of what lives where — ResourceManager will find them for us.

If you want, feel free to load up a layout in the CELayoutEditor (separate {LEX()}CVS{LEX} module, separate project, available for download from CEGUI site). Play around with it, create a new one, whatever you want. You won't play with it long due to its clumsiness, but it is instructive to see how it all goes together, especially if you build one from scratch.

Keep in mind that each .layout file is the definition for a single GUI sheet/page. You will need one for each page in your GUI.

Finally, note that the extension convention for CEGUI files (.scheme, .layout, etc.) really is just that: convention. CEGUI does not look for specific extensions; in fact, you have to provide CEGUI with the whole filename when loading them, so if you don't like .layout for some reason, feel free to use whatever you like.

Handling GUI Events

If you are at all familiar with MFC programming, you are most of the way there to understanding CEGUI event handling. The major difference is that your application subscribes to GUI events by providing a handler method for CEGUI to call when an event happens on a widget. CEGUI then calls your method with an EventArgs object so that you can retrieve a pointer to the window that sourced the message (i.e. in the case of a button click handler, the args will allow you to access the window that is the button). You should understand that in CEGUI (much as in any windowing system), EVERYTHING is a window.

The oddest thing about CEGUI, but something that makes great sense once you understand it, is that CEGUI does NOT deal with input AT ALL. It does not handle any input devices, not the keyboard, not the mouse, not anything. So how does it get input from these devices?

You have to capture the input yourself (using an input {LEX()}API{LEX} like the aforementioned {LEX()}OIS{LEX}) and provide CEGUI with notification that a button was clicked or a key was pressed. Same with mouse movement. Using the injectMouseMove(), injectKeyDown(), injectKeyUp() etc. methods, you tell CEGUI that something happened and it will tell you in return if something was click or changed or whatever. Really elegant, once you understand the processing flow, and completely removes the need for CEGUI to try to horn in on the increasing number of things interested in HID input in your application. ;)

The .scheme file for the menu

So, enough already! I already have Ogre fired up and I am tired of looking at my blank rendering window, I want to see a GUI there! For purposes of demonstration, let's use the layout I created for our project:

<?xml version="1.0" ?>
<GUILayout>
    <Window Type="DefaultWindow" Name="DemoLayout">
        <Window Type="TaharezLook/FrameWindow" Name="Main">
                <Property Name="RelativeMinSize" Value="w:0.2 h:0.2" />
                <Property Name="RelativeMaxSize" Value="w:1.0 h:1.0" />
                <Property Name="Position" Value="x:0.0 y:0.0" />
                <Property Name="Size" Value="w:1.0 h:1.0" />
                <Property Name="Text" Value="MyProject" />
                <Property Name="CloseButtonEnabled" Value="False" />

            <Window Type="TaharezLook/Button" Name="cmdQuit">
                <Property Name="Text" Value="Quit" />
                    <Property Name="Position" Value="x:0.4 y:0.7" />
                    <Property Name="Size" Value="w:0.2 h:0.07" />
            </Window>
            <Window Type="TaharezLook/Button" Name="cmdOptions">
                    <Property Name="Position" Value="x:0.4 y:0.6" />
                    <Property Name="Size" Value="w:0.2 h:0.07" />
                <Property Name="Text" Value="Options" />
            </Window>
            <Window Type="TaharezLook/Button" Name="cmdInstantAction">
                    <Property Name="Position" Value="x:0.4 y:0.5" />
                    <Property Name="Size" Value="w:0.2 h:0.07" />
                <Property Name="Text" Value="InstantAction" />
            </Window>
            </Window>
        </Window>
</GUILayout>


[IMPORTANT NOTE: For users of CEGUI 0.4.x and earlier, the above layout will work fine. For users of 0.5.x and later, which at this time is CVS HEAD, you MUST move to the Unified Dimension (UDim) manner of specifying window coordinates. CVS HEAD currently has support for Position and Size and the like ENTIRELY REMOVED. You have been warned. :-) If you are not sure what version you are running, CEGUI.log will happily tell you. Find it sitting next to Ogre.log during and after your game's execution.]

This is the entire contents of the layout file for the main screen that shows up when you start our project. Notice that CEGUI likes the UVW style of "normalized" coordinates; this allows you to free yourself from worrying about different resolutions your user might choose. I have the main window set at 1.0 for width and height; this will make it take up the whole rendering window, which is what we want. The TaharezLook scheme and look/feel will tile a particular subimage from its imageset across the background of the window, so it looks good. In fact, you can cut/paste this layout into a file and load it up in CELayoutEditor and see how it looks; it looks the same in-game.

Code to use the .scheme file with CEGUI

Here is the code to load this layout into the rendering window we've created earlier, and display it:

// setup -GUI system
        mGUIRenderer = new CEGUI::OgreCEGUIRenderer(window, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, guiSceneMgr);
        mGUISystem = new CEGUI::System(mGUIRenderer);
    CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
    CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
    mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");

    CEGUI::FontManager::getSingleton().createFont("bluehighway.font");
    mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");

    // set the mouse cursor initially in the middle of the screen
    mGUISystem->injectMousePosition((float)window->getWidth() / 2.0f, (float)window->getHeight() / 2.0f);


[NOTE: The above code will not compile if you are using CEGUI 0.7.1. As this portion of the tutorial is for academics, the principles described still hold. The 0.7.1 functional code is included in the part of the tutorial that covers actual implementation of CEGUI.]

Some notes on the above: first, it's basically the code from the CEGUI tutorial without the distracting and unnecessary {LEX()}RTT{LEX} stuff. Then, I chose Tahoma-12 because, well, just because. I like it. You may have to "borrow" the TTFs from the Windows or Linux fonts directories. (Alternately, you can simply reference the C:\Windows\Fonts directory as another ResourceGroup location. Neat, huh?) Third, notice the complete lack of any directory information at all with the filenames; this is taken care of by the ResourceManager, which we are leveraging by using the OgreCEGUIRenderer.

Remember the guiSceneMgr we obtained earlier (see here)? This is where it is used again to set up the GUI. That c-tor call on the OgreCEGUIRenderer is basically "boilerplate" and you'll use it similarly in your project.

The last thing to notice is the injectMousePosition() call; we do this to place the mouse in the center of the screen. Oddly enough, it takes absolute coordinates instead of the scaled 0.0-1.0 method.

(It may take absolute coordinates over the scaled method because the user's mouse may be at any location on the screen - and if I understand correctly, the scaled method would be scaling relative to its 'parent' window which may only go as high as the application's window and not the entire desktop real estate. In fullscreen this would work, but in windowed mode would limit you in possible use of the injection. Wow that sounds long winded, it's early, but figured it may help someone out there's understanding of it all.)

Subscribing to CEGUI events

Subscribing to CEGUI events is straightforward; I will not show you how our subscriptions are done because it's more complex than is necessary for purposes of demonstration. Suffice to say that your subscription code will look a lot like this:

CEGUI::Window *win;
        m_win = CEGUI::WindowManager::getSingleton().getWindow(sheetName);
        win = m_win->getChild("cmdQuit");
        win->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(Quit_OnClick, this));


getWindow() in CEGUI will get a pointer to the named window, wherever it may be. Above, we are getting a pointer to the root window of the sheet we loaded.

Handling CEGUI events

You would call this from within a class implemented to handle GUI events; in our case, there is one class per "dialog" or "sheet" or "page" (whatever you want to call it). The handler method for this event, in the handler class for the "Main" GUI sheet (that we cleverly called "GuiEventHandler_Main") is implemented as:

bool GuiEventHandler_Main::Quit_OnClick(const CEGUI::EventArgs &args) {
        // initiate system shutdown (we do this by requesting a shutdown,
        // which eventually will stop the main loop)
        m_stateManager.requestStateChange(SHUTDOWN);
        return true;
    }

Translating OGRE events to CEGUI events

The last essential thing you'll need to work with CEGUI and Ogre is translating input system events into something that CEGUI can consume. Our input system, not surprisingly, is based on DirectInput on Win32. It uses a {LEX()}MFC{LEX}-like "On*()" naming scheme for dispatching HID events, such as OnKeyDown() and OnMouseMove(). In the GUI state, these events have to be handled and then sent off to CEGUI, which is not as straightforward as it might seem. Mouse input is fine and intuitive, but for keyboard input, not only do you have to send the keyboard scancode, you have to send it the character it represents as well.

If you are reading this in a country that uses dead-key combinations, I wish you the best of luck if you are trying to roll your own input on Win32: the ToUnicode()/ToUnicodeEx() API on Win32 are so horribly done that MS devs themselves can't deal with it without complaining. The rest of us that use the Latin character set are fine, but if you plan on international support for your game then you have your work cut out for you; I suggest a long hard look at the keyboard code in GTK's Win32 port for how to handle all of this. OIS handles some of this, but as of this writing, Unicode is not yet supported.

But I digress. You want to see some code on injecting input into CEGUI, not a rant on stupid Microsoft implementations (which could keep us here 'til Christmas). So, here is some:

// event data container
        typedef struct {
            int x, y, z;
            int button;
        } MouseData;

        typedef struct {
            unsigned char keyCode;    // hardware keyboard scan code
            unsigned long mbcc;    // multi-byte character code (UNICODE)
            bool alt;
            bool ctrl;
            bool shift;
        } KeyData;

    void InputProcessor::OnMouseMove(Input::MouseData &evt) {
        int x = evt.x;
        int y = evt.y;
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiMouseEvent(x, y, 0, 0);
    }

    void InputProcessor::OnMouseMoveZ(Input::MouseData &evt) {
        int z = evt.z;
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiMouseEvent(0, 0, z, 0);
    }

    void InputProcessor::OnMouseButtonDown(Input::MouseData &evt) {
        int button = evt.button;
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiMouseEvent(evt.x, evt.y, 0, -button);
    }

    void InputProcessor::OnMouseButtonUp(Input::MouseData &evt) {
        int button = evt.button;
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiMouseEvent(evt.x, evt.y, 0, button);
    }
    void InputProcessor::OnKeyDown(Input::KeyData &evt) {
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiKeyboardEvent((long)evt.keyCode, evt.mbcc, true, evt.alt, evt.ctrl, evt.shift);
    }

    void InputProcessor::OnKeyUp(Input::KeyData &evt) {
        if (m_stateManager.getCurrentState() == GUI)
            m_video.guiKeyboardEvent((long)evt.keyCode, evt.mbcc, false, evt.alt, evt.ctrl, evt.shift);
    }


Note that our video subsystem handles GUI and game input command differently, and therefore different methods need to be called (also note that there are no "game" input calls here yet). On the receiving end of that call, you'll find:

void video::guiKeyboardEvent(long keycode, long ch, bool down, bool alt, bool ctrl, bool shift) {
    if (down) {
        mGUISystem->injectKeyDown(keycode);
        mGUISystem->injectChar(ch);
    }
    else
        mGUISystem->injectKeyUp(keycode);
}

static CEGUI::MouseButton guiButton[3] = {
    CEGUI::LeftButton,
    CEGUI::MiddleButton,
    CEGUI::RightButton
};

// x, y are 0 to N-1 where N=screen dimensions
// z is any integral number
// button indicates which button was pressed/released; negative 
//   numbers are "down" events, and zero indicates no button event
void video::guiMouseEvent(int x, int y, int z, int button) {

    if (button == 0)
        mGUISystem->injectMouseMove(x, y);
    else {
        if (button > 0)
            mGUISystem->injectMouseButtonUp(guiButton[button-1]);
        else
            mGUISystem->injectMouseButtonDown(guiButton[(-button)-1]);
    }
}


It's that simple, really. On Win32, ToUnicodeEx() usually will give you the Unicode character that corresponds to the keystroke indicated by the keycode, as it is laid out on the current keyboard you have set in Windows (not sure how locales are handled on Linux), and you pass that into CEGUI so it can display the character you typed.

Switching From -GUI To Game And Vice Versa

Remember the showGui() method mentioned in the Initialization article? Here's its definition:

if (window)
        window->removeAllViewports();

    if (guiSceneMgr)
        guiSceneMgr->removeAllCameras();
    else
        guiSceneMgr = ogre->getSceneManager(ST_GENERIC);

    if (sceneMgr)
        sceneMgr->removeAllCameras();

    camera = guiSceneMgr->createCamera("Main");
        camera->setPosition(0, 0, 300);
        camera->lookAt(0, 0, 0);
        window->addViewport(camera);


This is how you switch scene managers in Ogre. First, you need to remove all of a window's viewports, then you need to remove all cameras a scene manager may be using, then you can start operating on the alternate scene manager and create cameras from it (and add viewports using those cameras). The code above is for the general case, and will deal with switching out of the "Game" state as well as starting up from scratch. For the sake of completeness, the showScene() method is

window->removeAllViewports();

    if (guiSceneMgr)
        guiSceneMgr->removeAllCameras();


The conventional usage of these two methods is such that each will be followed up by a call to load content into the scene; for the GUI, it will be the layout loading code above, and for the scene, it will be whatever code you have to load a world and geometry into that scene (we'll visit this part later). For now, it's enough to know that showScene() is called from the code that handles our app's "Launch" GUI button press event.

And what of those events? Not much, really. If you've ever done MFC programming or VB forms programming, you know how little there can be to do in response to some events. In fact, the entire code we have in response to the Launch button press is

Mission::MissionFile mf;
        std::ifstream mfile("demo.xxx");
        mf.deserialize(mfile, 0);
        mfile.close();

        m_stateManager.requestStateChange(NORMAL);
        m_video.showScene();

        m_video.loadWorld(mf);


This code loads our binary mission file format, deserializes it into something that can be used later, requests a state change from the state manager, calls the showScene() to switch scene managers, and loads the world and geometry into the scene, and then off it goes. At some point there will be a loader progress bar updated while the scene and geometry all load, and that will complete the appearance of a "professional" game. ;)

State Management

State Manager? What's that? Does that come with Ogre?

Nope, it's just a small "gatekeeper" class that allows us to synchronize the input dispatching loop with game states (GUI input is handled much differently and by a different class than game input is handled; we'll show that later). You'll be perfectly able to write your own state manager, since every game has its own personal states; what works for one might not work for another. At this stage, ours has STARTUP, SHUTDOWN, GUI and NORMAL; others might be implemented at a later date depending on what the needs are.

Prev <<< Practical Application - InitializationPractical Application - Let's Get Started >>> Next

<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.