
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {

/// \brief The Scene class is the container object for all the data in a Mudbox scene.
///
/// All the geometry, lights, cameras, etc, are accessed and maintained through this object.
/// To get a pointer to the current Mudbox scene, call \a Kernel()->Scene()
class MBDLL_DECL Scene : virtual public TreeNode
{
	DECLARE_CLASS;

protected:
	/// \brief Do not use the constructor directly.
	///
	/// It is unlikely that you would ever create your own scene in a plug-in. If
	/// you do need to, you should not call the constructor directly.  Instead,
	/// use \a CreateInstances, like this:
	/// \code
	///		Scene *myNewScene = CreateInstance<Scene>();
	/// \endcode
	Scene( void );

public:
	/// Returns a pointer to the camera that is currently being used.
	virtual mudbox::Camera *ActiveCamera( void ) const;

	/// Sets a different camera to be active
	virtual void SetActiveCamera( mudbox::Camera *camera );

	/// Returns a pointer to the currently active light
	virtual mudbox::Light *ActiveLight( void ) const;

	/// Returns the number of cameras in the scene.
	virtual unsigned int CameraCount( void ) const;

	/// Returns the number of lights in the scene.
	virtual unsigned int LightCount( void ) const;

	/// Returns the number of Geometry objects in the scene.
	virtual unsigned int GeometryCount( void ) const;

	/// Returns the number of Geometry objects that are currently selected.
	virtual unsigned int SelectedGeometryCount( void ) const;

	/// \brief Adds a camera to the scene.  Returns a pointer to the camera you added.
	///
	/// Once you add a camera to the scene, the scene is responsible for
	/// deleting it.
	virtual mudbox::Camera *AddCamera(
		mudbox::Camera *pCamera		///< [in] a pointer to an instance of a Camera
		);

	/// \brief Adds a light to the scene.  Returns a pointer to the light you added.
	///
	/// Once you add a light to the scene, the scene is responsible for deleting it.
	virtual mudbox::Light *AddLight(
		mudbox::Light *pLight		///< [in] a pointer to an instance of a Light
		);

	/// \brief Adds a geometry object to the scene.  Returns a pointer to the object you added.
	///
	/// Once you add a geometry object to the scene, the scene is responsible for deleting it.
	virtual mudbox::Geometry *AddGeometry(
		mudbox::Geometry *pGeometry,	///< [in] a pointer to an instance of a Geometry object
		mudbox::Transformation* pTransformation = 0 ///< [in] a pointer to an instance of a Transformation for the Geometry
		);

	/// \brief Removes a geometry object from the scene.
	///
	/// Note that the removed geometry is not deleted.  Once the geometry is removed, it
	/// becomes the caller's responsibility to delete it.
	virtual void RemoveGeometry(
		mudbox::Geometry *pGeometry  ///< [in] a pointer to the object that you want removed.
		);

	/// \brief Returns a pointer to a Camera in the scene.
	///
	/// (If the index is out of range, NULL is returned.
	/// To find out how many cameras are in the scene, call \a CameraCount().)
	virtual mudbox::Camera *Camera(
		unsigned int iIndex		///< [in] the index of the camera to be returned (0-based)
		) const;

	/// \brief Returns a pointer to a Light in the scene.
	///
	/// (If the index is out of range, NULL is returned.
	/// To find out how many lights are in the scene, call \a LightCount().)
	virtual mudbox::Light *Light(
		unsigned int iIndex		///< [in] the index of the light to be returned (0-based)
		) const;

	/// \brief Returns a pointer to a selected Geometry object in the scene.
	///
	/// (If the index is out of range, NULL is returned.
	/// To find out how many geometry objects are selected in the scene, call \a SelectedGeometryCount().)
	virtual mudbox::Geometry *SelectedGeometry(
		unsigned int iIndex		///< [in] the index of the selected geometry object to be returned (0-based)
		) const;

	/// \brief Returns a pointer to a Geometry object in the scene.
	///
	/// (If the index is out of range, NULL is returned.
	/// To find out how many geometry objects are in the scene, call \a GeometryCount().)
	virtual mudbox::Geometry *Geometry(
		unsigned int iIndex		///< [in] the index of the geometry object to be returned (0-based)
		) const;

	/// \brief Returns the bounding box of the scene.
	///
	/// This bounding box is axis-aligned, and in World Space.
	virtual AxisAlignedBoundingBox BoundingBox( void ) const;

	/// \brief Render the scene to the current render target using the current OpenGL pipeline settings.
	///
	/// \b Note: This method is \b not part of the regular refresh cycle.  To force the screen to refresh after
	/// making changes, call Kernel->Refresh()
	///
	/// Use this method when you need to render the scene for purposes internal to your plug-in.  For example,
	/// you can create a custom texture, make it the render target (see the Texture class defined in material.h),
	/// set up whatever special shaders you need, then call this method to render the scene into your texture.
	///
	/// By default, objects will be rendered with their own materials.  If you want to render everything with
	/// a shader that you set up, set \c bSkipMaterials to \b true.
	virtual void Render(
		bool bSkipMaterials = false		///< [in] If \b true, then the materials attached to objects in the scene are ignored.  Everything uses the current shader.
		) const;
		
	/// Export models in the scene to an OBJ file.  Returns \b true if successful
	virtual bool Export(
		const char *sFileName,			///< [in] The path to the file to be saved (with a .obj extension)
		bool bSelectedOnly = false		///< [in] If \b true, only selected models will be saved
		);	// export data to an obj file
	
	/// Load a MUD file into this scene.  Returns \b true if successful.
	virtual bool Load(
		QString sFileName,				///< [in] The path to the MUD file to be loaded
		bool bMerge = false,			///< [in] If \b true, the file being read in is merged with the current scene.
		bool bMaterials = true,			///< [in] Set \b false to exclude materials from being loaded
		bool bLights = true				///< [in] Set \b false to exclude lights from being loaded
		);
	
	/// Save this scene.  Returns \b true if successful.
	virtual bool Save(
		QString sFileName				///< [in] The path to the MUD file to be saved (with a .mud extension )
		);
		
	/// \brief Returns a pointer to the active object (that is, the object whose layers are displayed in the UI)
	///
	/// Note that the 'active' object is unrelated to 'selected' objects.  'Active' refers to the object that is
	/// currently the focus of the user interface.  For example, only one object at a time displays its
	/// layer information --- this is the active object.
	mudbox::Geometry *ActiveGeometry() const;
	
	/// Sets the specified geometry to be active. This means that its layers will be displayed in the UI.  This is unrelated to selection.
	void SetActiveGeometry(
		mudbox::Geometry *geometry 	///< [in] a pointer to the geometry to be made active
		) const;
		
	/// Sets the specified paint layer to be active.
	virtual void SetActivePaintLayer(
		mudbox::Layer* layer	///< [in] A pointer to the layer to be made active
		);
	
	/// Sets the layer associated with the active texture pool to be active.
	virtual void SetActiveTexture(
		mudbox::TexturePool* layer	///< [in] A pointer to the texture to be made active
		);
	
	/// Returns a pointer to the currently active paint layer
	virtual mudbox::Layer *ActivePaintLayer() const;
	
	/// Returns a pointer to the currently active texture map
	virtual mudbox::TexturePool *ActiveTexture() const;
	 
	// Creates a thumbnail of the current scene
	virtual void MakeThumbnail(QImage &image, int iSize = 128);

	aevent m_eSceneRender;
};

}; // end of namespace mudbox
