/****************************************************************************************************

		Basic3DEditorHost.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	pascalc
		Date:	12/13/2005

****************************************************************************************************/

#ifndef __Basic3DEditorHost__
#define __Basic3DEditorHost__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "BasicMCFCOMImplementations.h"
#include "CountedRenderingCallback.h"
#include "IEx3DEditorHostPart.h"
#include "IChangeManagement.h"
#include "IPreviewMaker.h"
#include "IShThreadUtilities.h"
#include "ProgressHelper.h"

/// \addtogroup BaseClass
/// \{

class TBasicPreviewPart;

/// Basic 3D editor host pane class.  Derive from this for a default implementation of an IEx3DEditorHostPanePart.
/// \see IEx3DEditorHostPanePart
class TBasic3DEditorHostPanePart: public TBasicPart,
								  public IEx3DEditorHostPanePart
{
public:
	virtual ~TBasic3DEditorHostPanePart();

	// IMCUnknown
	virtual MCErr			MCCOMAPI QueryInterface	(const MCIID& riid, void** ppvObj);
	virtual uint32			MCCOMAPI AddRef() {return TBasicPart::AddRef();}
	STANDARD_RELEASE;

	// IMFExPart
	virtual boolean			MCCOMAPI Receive			(int32 message, IMFResponder* source, void* data) { return false; }
	virtual TMFEventResult	MCCOMAPI SelfMouseDown		(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent);
	virtual void			MCCOMAPI SelfDraw			(IMCGraphicContext* graphicContext, const TMCRect& inZone);
	virtual boolean			MCCOMAPI SelfKeyDown		(TMCPlatformEvent* event) { return false; }

	virtual void			MCCOMAPI SelfPrepareToDestroy	();
	virtual void			MCCOMAPI SetShown				(boolean inShown);
	virtual void			MCCOMAPI BaseWindowBecameVisible(boolean inShown) { SetShown(inShown); }

	//	IEx3DEditorHostPanePart
	virtual void			MCCOMAPI Set3DEditorHostPanePart	(I3DEditorHostPanePart* editorHostPanePart);
	virtual MCCOMErr		MCCOMAPI InvalidateRender			(boolean invalidate = true, boolean cameraChanged=false);
//	virtual MCCOMErr		MCCOMAPI SelfRenderDraw				(TRenderable2DArray& renderables2D);
	virtual MCCOMErr		MCCOMAPI SelfRenderPickDraw			(I3DExPickRenderer* pickRenderer) { return MC_E_NOTIMPL; }
	virtual MCCOMErr		MCCOMAPI GetLocationOfSelectionInGlobal(TVector3& outGlobalLocation) { return MC_S_OK; }
	virtual boolean			MCCOMAPI GetHitLocationInGlobal		(const TMCPoint& inWindowPoint, TVector3& outGlobalLocation) {return false;}
	virtual void			MCCOMAPI GetCurrentScene			(I3DShScene **scene, boolean createIfNone);
	virtual void			MCCOMAPI GetCameraToolsStatus		(TCameraToolsStatus& outStatus, boolean& outAllowSavePos);
	virtual I3DEditorHostPanePart* MCCOMAPI  Get3DEditorHostPanePart() const { return f3DEditorHostPanePart; };
	virtual void			MCCOMAPI BeginAreaRender();
	virtual void			MCCOMAPI EndAreaRender() {}
	virtual void			MCCOMAPI CameraMoved() {}

	// Other functions
	void						InternalSelfDraw(IMCGraphicContext* graphicContext, TMCRect* inZone);
	void						SetPreviewPart(TBasicPreviewPart* inPart);
	virtual ISceneDocument*		GetAssociatedSceneDocument() = 0;
protected:

	TMCCountedPtr<TBasicPreviewPart>			fPreviewPart;
	TMCCountedPtr<IMFPart>						fPart;
	TMCCountedPtr<I3DEditorHostPanePart>		f3DEditorHostPanePart;

};

class TBasicPreviewThread;
class TBasicPreviewCallbacks;

enum ERenderMode
{
	kRenderPreview		= 0,
	k3DView				= 1,
};

class TBasicPreviewPart: public TBasicPart, public IChangeListener
{
public:
	TBasicPreviewPart(uint32 inPartID, uint32 inPaneExtensionID);
	virtual ~TBasicPreviewPart();

	// IMCUnknown
	virtual MCErr			MCCOMAPI QueryInterface	(const MCIID& riid, void** ppvObj);
	virtual uint32			MCCOMAPI AddRef() {return TBasicPart::AddRef();}
	STANDARD_RELEASE;

	// TBasicPart
	virtual TMFEventResult	MCCOMAPI SelfMouseDown			(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent);
	virtual void			MCCOMAPI SelfPrepareToDestroy	();
	virtual void			MCCOMAPI FinishRead				();
	virtual boolean			MCCOMAPI ParentChangedBounds	(const TMCRect& oldBounds,const TMCRect& newBounds,boolean inval);
	
	// IChangeListener
	virtual void			MCCOMAPI DataChanged(IChangeChannel* channel, IDType changeKind, IMCUnknown* changedData);

	// Other functions
	virtual void			Make3DView			();
	virtual boolean			BuildPreview		()=0;

	void		ValidatePreview		() { fIsPreviewValid=true; };
	void		InvalidatePreview	();
	void		MarkPreviewInvalid(boolean invalid);

	virtual void			DrawRenderedPreview	(IMCGraphicContext* inGC, const TMCRect* zone);
	virtual void			DrawChecker			(IMCGraphicContext* inGC, const TMCRect* zone);

	TMCOffscreen*		CheckAndGetOffscreen	();
	I3DShCamera*		GetCurrentCameraNoAddRef();
	virtual I3DEditorHostPanePart* MCCOMAPI  Get3DEditorHostPanePart() { return fPreviewPanePart->Get3DEditorHostPanePart(); };
	virtual IMFPart*	GetRenderPart			() { return fRenderPart; };
	
	IMFPart*			GetIMFPartNoAddRef		() { return fInteractiveNode; };
	void				GetSize					(TMCPoint& size) const { fInteractiveNode->GetSize(size); };
	IPreviewMaker*		GetPreviewMaker			() { return fPreviewer; };
	I3DShScene*			GetSceneToPreview		() { if (!fPreviewScene) BuildPreview(); return fPreviewScene; };

	void				LaunchPreviewThread		();
	TMCArray<TMCRect>&	GetZonesToRender		() { return fZoneToBlit;};
	void				FlushZoneToRender		();
	void				AbortRendering			();

	void				ReleaseThread			(); //This call is ONLY for TBasicPreviewThread::Work()
	void				InvalidateOffscreen		(boolean launchTread, const TMCRect& rect = TMCRect::kInvalid);

	boolean									fOffscreenInvalid;
	TMCCountedPtr<TBasicPreviewCallbacks>	fRenderingCallbacks;

	ERenderMode	GetRenderMode		() { return fRenderMode; }
	void		SetRenderMode		(ERenderMode m) { fRenderMode = m; }
	virtual boolean		IsAutoRefresh		() { return false; }

	virtual	void		CreateRenderingCallbacks(TBasicPreviewCallbacks** outCallbacks);

protected:
	virtual void		ResetCamera			() = 0;
	boolean				RenderPreview		();
	boolean				LoadPreviewScene	(const TMCString& fullPathname);
	void				BuildPreviewScene	(TTransform3D* cameraTransform3D=nil);

	// Offscreen
	TMCSmartPtr<TMCOffscreen>				fOffscreen;
	TMCArray<TMCRect>						fZoneToBlit;

	TMCCountedPtr<TBasicPreviewThread>		fPreviewThread;

	boolean									fShouldInvalidatePreview;
	boolean									fIsPreviewValid;
	boolean									fPreviewSceneUnavailable;
	ERenderMode								fRenderMode;	

	TMCCountedPtr<TBasic3DEditorHostPanePart>	fPreviewPanePart;

	TMCCountedPtr<I3DShScene>				fPreviewScene;
	TMCCountedPtr<IPreviewMaker>			fPreviewer;

	TMCCountedPtr<IChangeChannel>			fImmediateUpdateChannel;
	TMCCountedPtr<I3DEditorHostPart>		fEditorHostPart;

	TMCCountedPtr<IMFPart>					fThisPart;
	TMCCountedPtr<IMFPart>					fInteractiveNode;
	TMCCountedPtr<IMFPart>					fRenderPart;
	uint32									fPartID;
	uint32									fPaneExtensionID;
};


class TBasicPreviewCallbacks : public TCountedRenderingCallbacks
{
	public:
	static void Create(	TBasicPreviewCallbacks** callbacks);
	static void Create(	TBasicPreviewCallbacks** callbacks, 
						TProgressBarHelper* progressHelper, 
						I3DRenderHelper* renderHelper,
						IShRasterLayer** rasterLayer);

protected:
	TBasicPreviewCallbacks();
	TBasicPreviewCallbacks(	TProgressBarHelper* progressHelper, 
							I3DRenderHelper* renderHelper,
							IShRasterLayer** rasterLayer);
	~TBasicPreviewCallbacks();

public:
	// I3DRenderingCallbacks
	virtual MCCOMErr MCCOMAPI EndFrame(uint32 frameNumber);
	virtual MCCOMErr MCCOMAPI RectCompleted(const TMCRect & rect);
	virtual MCCOMErr MCCOMAPI UpdateProgress(real progress, real progressMax);

	// general methods
	void Init(TBasicPreviewPart *part,IPreviewMaker* previewMaker);

protected:
	TMCCountedPtr<TBasicPreviewPart>	fPreviewPart;
	TMCCountedPtr<IMFPart>						fPart;
	IPreviewMaker*								fPreviewMaker;
	
	// For preset export only
	I3DRenderHelper*							fRenderHelper;
	TMCString255								fProgressTitle;
	TProgressBarHelper*							fProgressHelper;
	IShRasterLayer**							fRasterLayer;
};

class TBasicPreviewThread : public TMCCountedObject, public IExThread
{
public:
	static void Create(TBasicPreviewThread ** outThread, TBasicPreviewPart* part )
	{
		TMCCountedCreateHelper<TBasicPreviewThread> result(outThread);
		result = new TBasicPreviewThread( part );
	}
protected:
	TBasicPreviewThread( TBasicPreviewPart* part );
	virtual ~TBasicPreviewThread();
public:
	MCCOMErr	MCCOMAPI QueryInterface(const MCIID& riid, void** ppvObj);
	uint32		MCCOMAPI AddRef () {return TMCCountedObject::AddRef();}
	uint32		MCCOMAPI Release() {return TMCCountedObject::Release();}
	

	//IExThread
	virtual MCCOMErr MCCOMAPI Work();
	
	void	Init	(I3DShCamera* camera);
	void 	Launch	();
	void 	SoftKill(); //Aborts rendering and waits for termination or just kill the thread.
	void 	KillNow	(); //just calls gShellThreadUtilities->KillThread

protected:
	void 	AbortRendering		() 		{ fPreviewer->AbortRendering(); }
	boolean GetRenderingStarted	() 		{ return fRenderingStarted; }
	
private:
	TMCPtr<TBasicPreviewPart>			fPreviewPart;
	TMCCountedPtr<IPreviewMaker>		fPreviewer;
	TMCPtr<TMCOffscreen>				fOffscreen;
	int32								fThreadID;
	boolean								fRenderingStarted;
};

/// \}


#endif
