IMPORTANT: The information here is outdated. For new projects, rather see The according manual section.


This first part of this article will outline in detail the process by which resources are loaded, unloaded, reloaded and destroyed. In the second half, we will create a new resource type, and a manager to go with it.

Any problems you encounter during working with this tutorial should be posted in the Help Forum(external link).


The Lifecycle of a Resource

The OGRE API documentation explains the basic lifecycle of a resource, but is slightly washy with some of the concepts. Hopefully, things will be made clearer here.

Terminology

The following terms will be used to distinguish the various stages of loading that a resource may be in:

Unknown: OGRE is not aware of the resource. Its filename is stored in a ResourceGroup, but OGRE has no idea what to do with it.

Declared: The resource has been flagged for creation, either directly or as a side-effect of some other action. Ogre knows what type of resource it is, and what to do with it when the time comes to create it.

Created: OGRE has created an empty instance of the resource, and added it to the relevant ResourceManager.

Loaded: The created instance has been fully loaded, and the resource's full data now resides in memory. This is typically the stage at which the resource's file is actually accessed. You do not want to access the file in the Creation stage.

Resources do not take much space until they are loaded, therefore there is no harm in adding all of your resources to the resource manager first and then loading/unloading them as needed in your application.

Resource Creation, from the very beginning

  1. OGRE's native ResourceManagers are created in Root::Root.
  2. The first thing that needs to be done is to specify resource locations. This is done by calling ResourceGroupManager::addResourceLocation. This function does several things:
    1. Creates the specified ResourceGroup if this hasn't been done already.
    2. Creates a new Archive instance of the type specified
    3. Creates a new ResourceLocation, adds the Archive to it, and then adds the ResourceLocation to the ResourceGroup.
    4. The final step is to get a list of all the files in the Archive, and add them to a list in the ResourceGroup. After this step has completed, resources are in the Unknown stage.
  3. The next step is to manually declare resources. No resources have been declared as of yet, though many of them will be when the ResourceManager starts parsing scripts. If you wish to manually declare resources, call the ResourceGroupManager::declareResource function. At this point, any resources that have been manually declared are in the Declared stage. The rest are still Unknown.
  4. Next the ResourceGroups are initialized. This is done with ResourceGroupManager::initialiseResourceGroup or ResourceGroupManager::initialiseAllResourceGroups, the latter just calling the former for all ResourceGroups. This does the following:
    • Parses any scripts in the ResourceGroup. Scripts are defined by ResourceManagers which inherit from ScriptLoader. This may cause some resources to be Declared.
    • Creates any Declared resources.
    • The relevant ResourceManager creates a new instance of the resource, and adds it to itself. All resources are stored in ResourceManagers.
    • The resource is also inserted into an "ordered loading list". This allows resources to be loaded in a specific order, if you want to load an entire ResourceGroup at once. The load order for a resource is specified by its ResourceManager.
    • At this point, any Declared resources are now in the Created stage.
  5. Finally, we're done with initialization. No resources are loaded yet, but that's fine, because we're not using any. The final step - the transition from Created to Loaded - can come about in the following ways:
    • The resource was used. For example, an Entity was created which needed a specific mesh. Obviously, once a resource has been loaded in this way, it will not be loaded again if another Entity needs it. If the resource is currently in the Unknown state, it will be created and fully loaded.
    • ResourceGroupManager::loadResourceGroup is called - any Created resources are loaded.
    • The relevant ResourceManager's load method is called. This can be used to load resources which have not yet been Created, because it will automatically Create them for you first, if necessary.
    • The resource is loaded directly, by obtaining a pointer to it, and calling its load method. You can only do this if the resource is in the Created stage, of course.
    • At this point, Loaded resources are ready to use straight away.


Note: If you have created any custom ResourceManagers, you must initialize them before manually declaring resources or some of them may not be found.

In your application, this generally boils down to the following sequence of events:

  1. Create the Root object.
  2. Call ResourceGroupManager::addResourceLocation repeatedly until you have added all resource locations.
  3. Create any custom ResourceManager objects you have made and register them using ResourceGroupManager::_registerResourceManager. You should also register any ScriptLoader objects with the ResourceGroupManager::_registerScriptLoader function.
  4. Manually declare any resources you require with the ResourceGroupManager::declareResource function.
  5. Call the appropriate initialization function for your resource groups. Either use ResourceGroupManager::initialiseResourceGroup for a single group or call ResourceGroupManager::initialiseAllResourceGroups to initialize everything at once.

Resource Unloading and Destruction

  • ResourceManager::unload reverts a resource from Loaded to Created.
  • To completely remove a resource, call ResourceManager::remove. This returns the resource all the way back to the Unknown stage, from whichever stage it was in previously. You can get a pointer to the resource with ResourceManager::getByName and unload or remove it manually, if you wish.
  • Any existing resources are removed when a ResourceManager is destructed.

Reloading Resources

Reloading resources is a very useful feature for editors. Essentially, the resource is unloaded, and then loaded. It moves from Loaded, to Created and then back to Loaded again. Resources must be in the Loaded stage to be reloaded.

  • ResourceManager::reloadAll reloads all resources of one type.
  • Resources can be individually reloaded with Resource::reload

Creating a new Resource type, and the accompanying ResourceManager

Now that we know how OGRE's resource system works, creating a new resource type is actually pretty easy. Your application will almost certainly use extra resources, be they sound files, XML or just plain text. In this example, we'll create a simple text file loader. The code is neatly compartmentalized, and easy to extend to any file type - the only thing that will need to change is the Resource::load method, and the TextFile resource's public interface to access the data we have loaded.

There are two caveats to this: script resources, and manual resource loaders. This example will use neither, but they will be explained.

The first file to create is TextFile.h. This declares our resource, TextFile, and creates a shared pointer implementation for it. This is what it looks like:

#ifndef __TEXTFILE_H__
 #define __TEXTFILE_H__
 
 #include <OgreResourceManager.h>
 
 class TextFile : public Ogre::Resource
 {
     Ogre::String mString;
 
 protected:
 
     // must implement these from the Ogre::Resource interface
     void loadImpl();
     void unloadImpl();
     size_t calculateSize() const;
 
 public:
 
     TextFile(Ogre::ResourceManager *creator, const Ogre::String &name, 
         Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual = false, 
         Ogre::ManualResourceLoader *loader = 0);
 
     virtual ~TextFile();
 
     void setString(const Ogre::String &str);
     const Ogre::String &getString() const;
 };
 
 class TextFilePtr : public Ogre::SharedPtr<TextFile> 
 {
 public:
     TextFilePtr() : Ogre::SharedPtr<TextFile>() {}
     explicit TextFilePtr(TextFile *rep) : Ogre::SharedPtr<TextFile>(rep) {}
     TextFilePtr(const TextFilePtr &r) : Ogre::SharedPtr<TextFile>(r) {} 
     TextFilePtr(const Ogre::ResourcePtr &r) : Ogre::SharedPtr<TextFile>()
     {
         if( r.isNull() )
             return;
         // lock & copy other mutex pointer
         OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
         OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
         pRep = static_cast<TextFile*>(r.getPointer());
         pUseCount = r.useCountPointer();
         useFreeMethod = r.freeMethod();
         if (pUseCount)
         {
             ++(*pUseCount);
         }
     }
 
     /// Operator used to convert a ResourcePtr to a TextFilePtr
     TextFilePtr& operator=(const Ogre::ResourcePtr& r)
     {
         if(pRep == static_cast<TextFile*>(r.getPointer()))
             return *this;
         release();
         if( r.isNull() )
             return *this; // resource ptr is null, so the call to release above has done all we need to do.
         // lock & copy other mutex pointer
         OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
         OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
         pRep = static_cast<TextFile*>(r.getPointer());
         pUseCount = r.useCountPointer();
         useFreeMethod = r.freeMethod();
         if (pUseCount)
         {
             ++(*pUseCount);
         }
         return *this;
     }
 };
 
 #endif


Here is the accompanying .cpp file. We are using a simple string to store our data, and as such it needs no special initialisation. If you are using more complex objects, they must be initialised appropriately.

#include "TextFile.h"
 #include "TextFileSerializer.h"
 
 TextFile::TextFile(Ogre::ResourceManager* creator, const Ogre::String &name, 
                     Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, 
                     Ogre::ManualResourceLoader *loader) :
 Ogre::Resource(creator, name, handle, group, isManual, loader)
 {
     /* If you were storing a pointer to an object, then you would set that pointer to NULL here.
     */
 
     /* For consistency with StringInterface, but we don't add any parameters here
     That's because the Resource implementation of StringInterface is to
     list all the options that need to be set before loading, of which 
     we have none as such. Full details can be set through scripts.
     */ 
     createParamDictionary("TextFile");
 }
 
 TextFile::~TextFile()
 {
     unload();
 }
 
 // farm out to TextFileSerializer
 void TextFile::loadImpl()
 {
     TextFileSerializer serializer;
     Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(mName, mGroup, true, this);
     serializer.importTextFile(stream, this);
 }
 
 void TextFile::unloadImpl()
 {
     /* If you were storing a pointer to an object, then you would check the pointer here,
     and if it is not NULL, you would destruct the object and set its pointer to NULL again.
     */
 
     mString.clear();
 }
 
 size_t TextFile::calculateSize() const
 {
     return mString.length();
 }
 
 void TextFile::setString(const Ogre::String &str)
 {
     mString = str;
 }
 
 const Ogre::String &TextFile::getString() const
 {
     return mString;
 }

You will have noticed the reference to "TextFileSerializer" in the includes. This is a helper class which does the actual loading. It is not vital, especially for a resource this simple, but it allows us to serialize an object without having to wrap a Resource around it, should we want to. The Serializer base class contains lots of useful utility functions. We won't use them, but we'll subclass from it anyway.

TextFileSerializer.h:

#ifndef __TEXTSERIALIZER_H__
 #define __TEXTSERIALIZER_H__
 
 #include <OgreSerializer.h>
 
 class TextFile; // forward declaration
 
 class TextFileSerializer : public Ogre::Serializer
 {
 public:
     TextFileSerializer();
     virtual ~TextFileSerializer();
 
     void exportTextFile(const TextFile *pText, const Ogre::String &fileName);
     void importTextFile(Ogre::DataStreamPtr &stream, TextFile *pDest);
 };
 
 #endif

TextFileSerializer.cpp:

#include "TextFileSerializer.h"
 #include "TextFile.h"
 
 TextFileSerializer::TextFileSerializer()
 {
 }
 
 TextFileSerializer::~TextFileSerializer()
 {
 }
 
 void TextFileSerializer::exportTextFile(const TextFile *pText, const Ogre::String &fileName)
 {
     std::ofstream outFile;
     outFile.open(fileName.c_str(), std::ios::out);
     outFile << pText->getString();
     outFile.close();
 }
 
 void TextFileSerializer::importTextFile(Ogre::DataStreamPtr &stream, TextFile *pDest)
 {
     pDest->setString(stream->getAsString());
 }

The last class we need to write is of course the TextFileManager.

TextFileManager.h:

#ifndef __TEXTFILEMANAGER_H__
 #define __TEXTFILEMANAGER_H__
 
 #include <OgreResourceManager.h>
 #include "TextFile.h"
 
 class TextFileManager : public Ogre::ResourceManager, public Ogre::Singleton<TextFileManager>
 {
 protected:
 
     // must implement this from ResourceManager's interface
     Ogre::Resource *createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, 
         const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, 
         const Ogre::NameValuePairList *createParams);
 
 public:
 
     TextFileManager();
     virtual ~TextFileManager();
 
     virtual TextFilePtr load(const Ogre::String &name, const Ogre::String &group);
 
     static TextFileManager &getSingleton();
     static TextFileManager *getSingletonPtr();
 };
 
 #endif

And finally, TextFileManager.cpp

#include "TextFileManager.h"
 
 template<> TextFileManager *Ogre::Singleton<TextFileManager>::ms_Singleton = 0;
 
 TextFileManager *TextFileManager::getSingletonPtr()
 {
     return ms_Singleton;
 }
 
 TextFileManager &TextFileManager::getSingleton()
 {  
     assert(ms_Singleton);  
     return(*ms_Singleton);
 }
 
 TextFileManager::TextFileManager()
 {
     mResourceType = "TextFile";
 
     // low, because it will likely reference other resources
     mLoadOrder = 30.0f;
 
     // this is how we register the ResourceManager with OGRE
     Ogre::ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this);
 }
 
 TextFileManager::~TextFileManager()
 {
     // and this is how we unregister it
     Ogre::ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType);
 }
 
 TextFilePtr TextFileManager::load(const Ogre::String &name, const Ogre::String &group)
 {
     TextFilePtr textf = getByName(name);
 
     if (textf.isNull())
         textf = create(name, group);
 
     textf->load();
     return textf;
 }
 
 Ogre::Resource *TextFileManager::createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, 
                                             const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, 
                                             const Ogre::NameValuePairList *createParams)
 {
     return new TextFile(this, name, handle, group, isManual, loader);
 }

ScriptLoader

Some resources, such as materials, are loaded from scripts, and in these cases, the ResourceManager will derive from ScriptLoader. It will then set up its 'script patterns' - the filetypes that it considers as scripts (*.material, *.compositor, etc) - in the constructor. It will also call
ResourceGroupManager::_registerScriptLoader at this point to register itself as a script loading ResourceManager. Later, when ResourceGroupManager::initialiseResourceGroup is called, any registered script files will be parsed.

If you wish to write a script-loading ResourceManager, you will need to derive from ScriptLoader, and implement the parseScript method. It is parseScript that gets called on the resources during ResourceGroupManager::initialiseResourceGroup, and this is where you should declare any resources that you want created.

ManualResourceLoader

When a resource is declared with ResourceGroupManager::declareResource, it may be given an optional ManualResourceLoader. ManualResourceLoaders can be used for resources which are not loaded from file - they may be created programmatically. Here is a simple example, using TextFile:

// Do not add this to the project
 class ManualTextFileLoader : public Ogre::ManualResourceLoader
 {
 public:
 
    ManualTextFileLoader() {}
    virtual ~ManualTextFileLoader() {}
 
    void loadResource(Ogre::Resource *resource)
    {
        TextFile *tf = static_cast<TextFile *>(resource);
        tf->setString("manually loaded");
    }
 };

The TextFile is then declared as follows:

// Do not add this to the project
 ManualTextFileLoader *mtfl = new ManualTextFileLoader;
 Ogre::ResourceGroupManager::getSingleton ().declareResource("hello.txt", "TextFile", "General", mtfl);

Usage

To use our new resource manager, we create an instance before Root::initialise or any ResourceGroups have been initialized.

TextFileManager *tfm = new TextFileManager();

And we destruct it when we shutdown - before we destroy the Ogre::Root object, of course. OGRE does not destruct it itself, it's your responsibility:

delete Ogre::ResourceGroupManager::getSingleton()._getResourceManager("TextFile");


The last thing we will do is look at an example of what we have created in action. Create a file called "hello.txt" and place it in a media directory where Ogre can find it. Since there really isn't a location for custom scripts, I suggest putting the file in "media/materials/scripts". Add the following to that text file:

Hello world!

Now create a file called main.cpp and add the following code to it. Be sure to read through the createScene function to see some of the things we can do with this:

#include <ExampleApplication.h>
 
 #include "TextFileManager.h"
 #include "TextFileSerializer.h"
 
 class TutorialApplication : public ExampleApplication
 {
 private:
     TextFileManager *mTFM;
 public:
     TutorialApplication()
         : mTFM(0)
     {
     }
 
     ~TutorialApplication()
     {
         delete mTFM;
     }
 
     void setupResources()
     {
         mTFM = new TextFileManager();
 
         // hello.txt will be created when initialiseResourceGroup is called
         ResourceGroupManager::getSingleton().declareResource("hello.txt", "TextFile");
         ExampleApplication::setupResources();
     }
 
     void createScene(void)
     {
         // Load the file, get the data
         TextFilePtr textfile = mTFM->load("hello.txt", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
         String str = textfile->getString();
 
         // Reload the file
         textfile->reload();
 
         // export the file
         TextFileSerializer serializer;
         serializer.exportTextFile(static_cast<TextFile *>(textfile.getPointer()), "hello.out.txt");
 
         // unload/remove the file
         mTFM->unload("hello.txt");
         mTFM->remove("hello.txt");
     }
 };
 
 #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include "windows.h"
 
 INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
 #else
 int main(int argc, char **argv)
 #endif
 {
     // Create application object
     TutorialApplication app;
 
     try {
         app.go();
     } catch(Exception& e) {
 #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
         MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
 #else
         fprintf(stderr, "An exception has occurred: %s\n",
             e.getFullDescription().c_str());
 #endif
     }
 
     return 0;
 }


If you step through this function with a debugger, you will see that see that calling getString will indeed return the contents of hello.txt. While this may not be the most useful thing in its current state, you can easily expand this to create your own resources and resource loaders.


Alias: Advanced Tutorial 1
Alias: Advanced_Tutorial_1

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