This is a very minimal application that does the same thing that the Beginner Tutorial #1 does: pops up a window with nothing in it and waits for you to hit ESCAPE, at which point it exits.

To this point we have examined how the major parts of a practical Ogre-based application would be constructed, and implementation issues with each. Now, we will go ahead and start writing one. Let's start with the basics. We'll start with an uninterrupted code listing.

The Code

main()

main.cpp

#include "input.h"
#include "simulation.h"

#include "Ogre.h"

#include "OgreWindowEventUtilities.h"

#if defined(WIN32)
#include "windows.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
#else
int main (int argc, char *argv[]) {
#endif

    Ogre::Root *ogre;
    Ogre::RenderWindow *window;
    Ogre::SceneManager *sceneMgr;
    Ogre::Camera *camera;

    // fire up an Ogre rendering window. Clearing the first two (of three) params will let us 
    // specify plugins and resources in code instead of via text file
    ogre = new Ogre::Root("", "");

    // This is a VERY minimal rendersystem loading example; we are hardcoding the OpenGL 
    // renderer, instead of loading GL and D3D9. We will add renderer selection support in a 
    // future article.

    // I separate the debug and release versions of my plugins using the same "_d" suffix that
    // the Ogre main libraries use; you may need to remove the "_d" in your code, depending on the
    // naming convention you use 
    // EIHORT NOTE: All Ogre DLLs use this suffix convention now -- #ifdef on the basis of the _DEBUG 
    // define
#if defined(_DEBUG)
    ogre->loadPlugin("RenderSystem_GL_d");
#else
    ogre->loadPlugin("RenderSystem_GL");
#endif

    /* 
    ----------------------------------------------------------------------------
    [Note]: If using Ogre 1.7 the next 4 lines of code (not including comments) 
            should be changed to the following 2 lines:
	
    const Ogre::RenderSystemList &renderSystem = ogre->getAvailableRenderers();
    Ogre::RenderSystemList::const_iterator &r_it = renderSystem.begin();

    If using Ogre 1.9 the second line becomes:

    Ogre::RenderSystemList::const_iterator r_it = renderSystem.begin();

    [End Note] 
    ----------------------------------------------------------------------------
    */

    Ogre::RenderSystemList *renderSystems = NULL;
    Ogre::RenderSystemList::iterator r_it;

    // we do this step just to get an iterator that we can use with setRenderSystem. In a future article
    // we actually will iterate the list to display which renderers are available. 
    renderSystems = ogre->getAvailableRenderers();
    r_it = renderSystems->begin();
    ogre->setRenderSystem(*r_it);
    ogre->initialise(false);

    // load common plugins
#if defined(_DEBUG)
    ogre->loadPlugin("Plugin_CgProgramManager_d");        
    ogre->loadPlugin("Plugin_OctreeSceneManager_d");
#else
    ogre->loadPlugin("Plugin_CgProgramManager");        
    ogre->loadPlugin("Plugin_OctreeSceneManager");
#endif
    // load the basic resource location(s)
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "resource", "FileSystem", "General");
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "resource/gui.zip", "Zip", "GUI");
#if defined(WIN32)
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "c:\\windows\\fonts", "FileSystem", "GUI");
#endif

    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("General");
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("GUI");

    // setup main window; hardcode some defaults for the sake of presentation
    Ogre::NameValuePairList opts;
    opts["resolution"] = "1024x768";
    opts["fullscreen"] = "false";
    opts["vsync"] = "false";

    // create a rendering window with the title "CDK"
    window = ogre->createRenderWindow("CDK", 1024, 768, false, &opts);

    // since this is basically a CEGUI app, we can use the ST_GENERIC scene manager for now; in a later article 
    // we'll see how to change this
    sceneMgr = ogre->createSceneManager(Ogre::ST_GENERIC);
    camera = sceneMgr->createCamera("camera");
    camera->setNearClipDistance(5);
    Ogre::Viewport* vp = window->addViewport(camera);
    vp->setBackgroundColour(Ogre::ColourValue(0,0,0));

    // most examples get the viewport size to calculate this; for now, we'll just 
    // set it to 4:3 the easy way
    camera->setAspectRatio((Ogre::Real)1.333333);

    // this next bit is for the sake of the input handler
    unsigned long hWnd;
    window->getCustomAttribute("WINDOW", &hWnd);

    // set up the input handlers
    Simulation *sim = new Simulation();
    InputHandler *handler = new InputHandler(sim, hWnd);
    sim->requestStateChange(SIMULATION);

    while (sim->getCurrentState() != SHUTDOWN) {
        
        handler->capture();

        // run the message pump (Eihort)
        Ogre::WindowEventUtilities::messagePump();

        ogre->renderOneFrame();
    }

    // clean up after ourselves
    delete handler;
    delete sim;
    delete ogre;

    return 0;
}


I have lifted this code from a content-development kit I am creating for our project, hence the name "CDK". I have stripped out all of the actual useful, "fun" code in the intersts of laying bare the essentials; we'll add more later: by the end of this track, we will have an app that can move a model around a scene.

A quick tour of the code shows the initialization, resource location setup, and the main loop. The main loop, as discussed earlier, also calls the windowing system's message pump, which on Win32 enables the rendering window to be "well-behaved" (meaning, it responds well to system key combinations such as ALT+TAB, among other features). As we'll find later, it also enables the window to display its contents: without this message pump, the Ogre render window code does not get "paint" messages (WM_PAINT in Win32, which enables the window to refresh its contents regularly).

There are a few other items to take care of before building this code. First, there are a few other files we need to see. First, the "Simulation" declaration (.h) and definition (.cpp) files:

Simulation

simulation.h

#pragma once

#include <vector>
#include <map>

typedef enum {
    STARTUP,
    GUI,
    LOADING,
    CANCEL_LOADING,
    SIMULATION,
    SHUTDOWN
} SimulationState;

class Simulation {

public:
    Simulation();
    virtual ~Simulation();

public:
    bool requestStateChange(SimulationState state);
    bool lockState();
    bool unlockState();
    SimulationState getCurrentState();

    void setFrameTime(float ms);
    inline float getFrameTime() { return m_frame_time; }

protected:
    SimulationState m_state;
    bool m_locked;
    float m_frame_time;
};


simulation.cpp

#include "simulation.h"
#include "OgreStringConverter.h"

Simulation::Simulation() {
    m_state = STARTUP;
}

Simulation::~Simulation() {
}

SimulationState Simulation::getCurrentState() {
    return m_state;
}

// for the sake of clarity, I am not using actual thread synchronization 
// objects to serialize access to this resource. You would want to protect
// this block with a mutex or critical section, etc.
bool Simulation::lockState() {
    if (m_locked == false) {

        m_locked = true;
        return true;
    }
    else
        return false;
}

bool Simulation::unlockState() {
    if (m_locked == true) {
        m_locked = false;
        return true;
    }
    else
        return false;
}

bool Simulation::requestStateChange(SimulationState newState) {
    if (m_state == STARTUP) {
        m_locked = false;
        m_state = newState;

        return true;
    }

    // this state cannot be changed once initiated
    if (m_state == SHUTDOWN) {
        return false;
    }

    if ((m_state == GUI || m_state == SIMULATION || m_state == LOADING || m_state == CANCEL_LOADING) && 
            (newState != STARTUP) && (newState != m_state)) {
        m_state = newState;
        return true;
    }
    else
        return false;
}

void Simulation::setFrameTime(float ms) {
    m_frame_time = ms;
}


This "Simulation" class is a very simple example of a "state manager" class. Simulation (or game) states are nothing more than different execution contexts, and in the interests of orderly execution of your program, you will use them too. We show more states than we need here, but those states are all used in our project. There are no "official" game states; a state is just whatever you define it to be, however you intend to use it, it's game-specific. However, there are typically some very common states that all games and simulations will share, and SHUTDOWN, SIMULATION and GUI are three typical states. SHUTDOWN informs the app that a shutdown has been requested (in our case, either by the user pressing ESCAPE or clicking the "X" in the upper-right corner of the rendering window). SIMULATION is the state defined by "normal" execution of our game (we are running the simulation or processing game logic, updating and displaying the 3D scene, etc). GUI is a state of user interaction with a 2D GUI, such as that supported by CEGUI. (We have a separate GUI state to be able to tell when NOT to inject input into CEGUI, to prevent unnecessarily wasting CPU cycles).

The input handler in our example uses OIS. We leverage OIS in the input.h/.cpp files:

InputHandler

input.h

#pragma once

#include "OISEvents.h"
#include "OISInputManager.h"
#include "OISMouse.h"
#include "OISKeyboard.h"
#include "OISJoyStick.h"

class Simulation;

class InputHandler : 
        public OIS::MouseListener, 
        public OIS::KeyListener, 
        public OIS::JoyStickListener
{
private:
    OIS::InputManager *m_ois;
    OIS::Mouse *mMouse;
    OIS::Keyboard *mKeyboard;
    unsigned long m_hWnd;
    Simulation *m_simulation;    
public:
    InputHandler(Simulation *sim, unsigned long hWnd); 
    ~InputHandler();

    void setWindowExtents(int width, int height) ;
    void capture();

    // MouseListener
    bool mouseMoved(const OIS::MouseEvent &evt);
    bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID);
    bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID);
    
    // KeyListener
    bool keyPressed(const OIS::KeyEvent &evt);
    bool keyReleased(const OIS::KeyEvent &evt);
    
    // JoyStickListener
    bool buttonPressed(const OIS::JoyStickEvent &evt, int index);
    bool buttonReleased(const OIS::JoyStickEvent &evt, int index);
    bool axisMoved(const OIS::JoyStickEvent &evt, int index);
    bool povMoved(const OIS::JoyStickEvent &evt, int index);
};


input.cpp

#include "input.h"
#include "OgreStringConverter.h"
#include "simulation.h"

InputHandler::InputHandler(Simulation *sim, unsigned long hWnd)  {
    
    OIS::ParamList pl;
    pl.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));
    
    m_hWnd = hWnd;
    m_ois = OIS::InputManager::createInputSystem( pl );
    mMouse = static_cast<OIS::Mouse*>(m_ois->createInputObject( OIS::OISMouse, true ));
    mKeyboard = static_cast<OIS::Keyboard*>(m_ois->createInputObject( OIS::OISKeyboard, true));
    mMouse->setEventCallback(this);
    mKeyboard->setEventCallback(this);

    m_simulation = sim;
}

InputHandler::~InputHandler() {
    if (mMouse)
        m_ois->destroyInputObject(mMouse);
    if (mKeyboard)
        m_ois->destroyInputObject(mKeyboard);
        
    OIS::InputManager::destroyInputSystem(m_ois);
}

void InputHandler::capture() {
    mMouse->capture();
    mKeyboard->capture();
}

void  InputHandler::setWindowExtents(int width, int height){
    //Set Mouse Region.. if window resizes, we should alter this to reflect as well
    const OIS::MouseState &ms = mMouse->getMouseState();
    ms.width = width;
    ms.height = height;
}

// MouseListener
bool InputHandler::mouseMoved(const OIS::MouseEvent &evt) {
    return true;
}

bool InputHandler::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) {
    return true;
}

bool InputHandler::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) {
    return true;
}

        
// KeyListener
bool InputHandler::keyPressed(const OIS::KeyEvent &evt) {
    return true;
}

bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {
    if (evt.key == OIS::KC_ESCAPE)
        m_simulation->requestStateChange(SHUTDOWN);

    return true;
}

        

// JoyStickListener
bool InputHandler::buttonPressed(const OIS::JoyStickEvent &evt, int index) {
    return true;
}

bool InputHandler::buttonReleased(const OIS::JoyStickEvent &evt, int index) {
    return true;
}

bool InputHandler::axisMoved(const OIS::JoyStickEvent &evt, int index) {
    return true;
}

bool InputHandler::povMoved(const OIS::JoyStickEvent &evt, int index) {
    return true;
}


Since the ESCAPE key press is handled in a separate class, we have to let the application know somehow that it should shut down. We do this via the simulation state, and in order to do that, we need to have a reference to the simulation controller object in the input handler. We do this by passing a pointer to the object in the input handler constructor, and storing it in as a class data member.

This is actually a fairly important point, done in microcosm for clarity. Often you will see "Singleton" objects in Ogre. They are class instances, of which there can only ever be one (details on the Singleton pattern are better handled elsewhere).

Notice that we don't just change state, we "request to change state". If arbitrary parts of your program just stomped all over the state of the program, what happens to code that is in the middle of running in the context of a particular state? This is more an issue with multithreaded programs than single-threaded, and non-trivial programs often are multithreaded. If we allow state change "requests" instead of just slamming it home, as it were, we allow sections of code to complete their operation gracefully, and THEN the state can be changed. In this trivial example, of course, we just change the state on request, but we do leave ourselves the option for more elegant state management should it be necessary.

We operate OIS in buffered mode so that we can avoid missing input events. Calling InputHandler::capture() in turn calls the mouse and keyboard capture() methods, which will empty their buffers of pending events and distribute them accordingly.

I left the joystick event handler methods in there to show how joystick support is implemented. We are short only a single data member (joystick device pointer) of having stick support as well. We don't need it now, but it will be implemented in a later article.

Building and Running the Code

Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "resource", "FileSystem", "General");
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
        "resource/gui.zip", "Zip", "GUI");


As you can see in the initialization section, we define and populate two resource groups: General and GUI. General actually is always present, and is the default resource group for Ogre. GUI is a group we create to hold GUI content, and everything in the gui.zip file is loaded into this group.

In order for this to work without crashing, you must have a directory called "resource" containing a zip file called "gui.zip" in the working directory of the app. If you grab the ZIP file at the end of this article, you will find these in the Debug/ folder after unpacking. These can be anywhere you want; as you can see, we reference the Windows "fonts" directory as well (we'll see why in the next article).

We also need to have the proper include and library directories set up for this to build. You'll need to grab OIS from the SourceForge page above (unless you use the ZIP at the end of the article, which includes OIS), and obviously you'll need the Ogre headers and libraries as well (which come with the Ogre SDK). You'll also need the usual Ogre dependencies listed on the Ogre site if you are building Ogre from source (the Ogre SDK includes the needed dependency DLLs and headers).

I assume you know how to set directories in Visual C++ (or your particular IDE); if not, visit the docs for your IDE of choice and then come back. If you have installed the Ogre SDK, then you do not need to do anything else. If you have built from source, you'll need the following:

C++:

Additional Include Directories: (paths to the Ogre headers and the OIS headers)


Linker:

Additional Library Directories: (paths to the Debug Ogre .lib files and the Debug OIS static library)
Input: OgreMain_d.lib OIS_d.lib dxguid.lib dinput8.lib


You will also need to set the Working Directory under "Debugging" to point to the Debug/ folder. I've not included the .suo that inexplicably contains this per-project setting; if you get errors trying to execute that complain of not being able to find the "resource" directory, this is the problem: set the working directory properly and all should be well.

We need the DX libs because OIS builds as a static library and it has dependency on these libs. Note that we are using the Debug versions of the libs; remove the "_d" if you want the release.

The VC++ project is just a normal empty Win32 project. Alternately, you can unpack the ZIP below and just build it (after fixing up the directories mentioned above to reflect your setup). I used VC++ 2003 (VC 7.1) to build this code.

Sample Code Package

Download the code for this article

[NOTE: This code will still compile and execute with Ogre 1.7. It will work as advertised (that is a blank screen you can hit escape to exit from). The major changes occur when dealing with CEGUI and are covered in the next section.]

Building and Execution Notes

  • This code has been updated for Eihort, and was tested against the Ogre SDK 1.4RC1 (Eihort) for VC71; this means it will build and run against any Ogre 1.4.x SDK installation.
    • The ZIP file has further been updated to Ogre 1.6.x and includes VC9 sln/vcproj files
  • The code download is ~1MB in a ZIP file. It contains the source from this article; since Eihort provides the proper version of OIS as a Dependency, it no longer is needed in the source distribution for this article.
  • You will need to install the SDK in order to build this code (unless you have built Ogre from source and don't mind hacking around in the project files to point include and lib directories to the proper places). If you have installed the Ogre SDK 1.4.x, you should be able simply to unzip this ZIP file, open the PracticalApp.sln, click "Build Solution" for the Debug configuration and have it complete with no problems.
  • You will want to add $OGRE_HOME/bin/Debug to your PATH before running the PracticalApp.exe executable; how you do this is up to you (when testing, I opened a Cygwin Bash shell and typed "export PATH=$OGRE_HOME\bin\Debug:$PATH" before running PracticalApp.exe from the Bash prompt — your mileage may vary; you can just as easily add it to the Windows environment variables if you want). This is because the Ogre libs are "over there", and the tutorial executable is "over here" (along with the resource/ directory it expects to have in the same directory as the executable).
    • You can also set it directly in the project settings under Debugging; any environment variables you set here will be merged with the environment that Visual Studio has. The VC9 project files also include a .vcproj.user file that contains these settings, so if you have installed the SDK or have set OGRE_HOME properly, it will *just work* out of the box.
  • Additional notes regarding building the source code with Visual Studio 2005 Pro are in the discussions section of this article

Prev <<< Practical Application - GUIPractical Application - Something With A Bit More Meat >>> 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.