// PixelWhipPro.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "PixelWhipPro.h"
#include <MFCPlatform\MFCPlatform.hpp>
#include <GosFx\GosFx.hpp>
#include <MLR\MLR.hpp>
#include <ElementRenderer\ElementRenderer.hpp>
#include <Adept\Adept.hpp>
#include <Adept\Zone.hpp>

#include "MainFrm.h"
#include "ChildFrm.h"
#include "View3DChildWindow.h"
#include "EffectListWin.h"
#include "EffectEditWin.h"
#include "CurveEditorFrame.h"
#include "MoveProps.h"
#include "Export.h"
#include "EditMLRStateDlg.h"
#include "PPLightManager.h"
#include "PP2KEffectLibrary.hpp"
#include "PP2KTexturePool.h"



extern bool gActive;
extern bool gGotFocus;

ElementRenderer::gosFXElement *EffectWrapper=NULL;
gosFX::Effect *CurrentEffect=NULL;
ElementRenderer::GroupElement *Scene=NULL;
ElementRenderer::CameraElement *Camera=NULL;
Stuff::YawPitchRange Camera_Direction(0.0f, 0.0f, 10.0f);
Stuff::Vector2DOf<Stuff::Scalar> Camera_Shift(0.0f, 0.0f);
//Stuff::Point3D Camera_Loc(0.0f,100.0f,-100.0f),
Stuff::Point3D Camera_LookAt(0.0f,0.0f,0.0f);
ElementRenderer::StateChange *Camera_State=NULL;
Stuff::RGBAColor fogColor(0.3f, 0.3f, 0.3f, 1.0f);


Vector3D FXVel=Vector3D(0,0,10.0f),FXAcc=Vector3D(0,0,0);
double LastTime,FrameTime=0.0f,MaxTime=5.0f;
bool MoveFX=false;

bool HasEmptyEffectCloud(gosFX::Effect::Specification *spec);



/////////////////////////////////////////////////////////////////////////////
// CPixelWhipProApp

BEGIN_MESSAGE_MAP(CPixelWhipProApp, CWinApp)
//{{AFX_MSG_MAP(CPixelWhipProApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_LOADSCENEBACKGROUND, OnFileLoadscenebackground)
ON_COMMAND(ID_FILE_CLEARSCENEBACKGROUND, OnFileClearscenebackground)
ON_COMMAND(ID_FILE_EXPORT, OnFileExport)
ON_COMMAND(ID_OPTIONS_SETTEXTUREPATH, OnOptionsSettexturepath)
ON_COMMAND(ID_WINDOWS_CURVEEDITOR, OnWindowsCurveeditor)
ON_COMMAND(ID_WINDOWS_EFFECTLISTWINDOW, OnWindowsEffectlistwindow)
ON_COMMAND(ID_WINDOWS_EFFECTPARAMETERWINDOW, OnWindowsEffectparameterwindow)
ON_UPDATE_COMMAND_UI(ID_WINDOWS_CURVEEDITOR, OnUpdateWindowsCurveeditor)
ON_UPDATE_COMMAND_UI(ID_WINDOWS_EFFECTLISTWINDOW, OnUpdateWindowsEffectlistwindow)
ON_UPDATE_COMMAND_UI(ID_WINDOWS_EFFECTPARAMETERWINDOW, OnUpdateWindowsEffectparameterwindow)
ON_COMMAND(ID_VIEW_RESTARTPLAYBACK, OnViewRestartplayback)
ON_COMMAND(ID_VIEW_LOOPING, OnViewLooping)
ON_COMMAND(ID_VIEW_DYNAMICWORLDSPACE, OnViewDynamicworldspace)
ON_COMMAND(ID_VIEW_LOCALSPACE, OnViewLocalspace)
ON_COMMAND(ID_VIEW_STATICWORLDSPACE, OnViewStaticworldspace)
ON_UPDATE_COMMAND_UI(ID_VIEW_STATICWORLDSPACE, OnUpdateViewStaticworldspace)
ON_UPDATE_COMMAND_UI(ID_VIEW_LOOPING, OnUpdateViewLooping)
ON_UPDATE_COMMAND_UI(ID_VIEW_LOCALSPACE, OnUpdateViewLocalspace)
ON_UPDATE_COMMAND_UI(ID_VIEW_DYNAMICWORLDSPACE, OnUpdateViewDynamicworldspace)
ON_COMMAND(ID_VIEW_MOVEMENTOPTIONS, OnViewMovementoptions)
ON_COMMAND(ID_VIEW_MOVEEFFECT, OnViewMoveeffect)
ON_UPDATE_COMMAND_UI(ID_VIEW_MOVEEFFECT, OnUpdateViewMoveeffect)
ON_COMMAND(ID_OPTIONS_CLEARREGISTRY, OnOptionsClearregistry)
ON_COMMAND(ID_VIEW_RESETCAMERA, OnViewResetcamera)
ON_COMMAND(ID_OPTIONS_SETTOFIRE, OnOptionsSettofire)
ON_COMMAND(ID_OPTIONS_SETTOSMOKE, OnOptionsSettosmoke)
ON_COMMAND(ID_OPTIONS_EDITFIREQUICKSET, OnOptionsEditfirequickset)
ON_COMMAND(ID_OPTIONS_EDITSMOKEQUICKSET, OnOptionsEditsmokequickset)
ON_COMMAND(ID_FILE_LOADTERRAIN, OnFileLoadterrain)
ON_COMMAND(ID_FILE_CLEARTERRAIN, OnFileClearterrain)
ON_COMMAND(ID_FILE_LOADLIGHTS, OnFileLoadlights)
ON_COMMAND(ID_FILE_CLEARLIGHTS, OnFileClearlights)
ON_COMMAND(ID_FILE_LOADLASTWORKSPACE, OnFileLoadlastworkspace)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPixelWhipProApp construction

CPixelWhipProApp::CPixelWhipProApp()
{
	AllowDraw=true;
	GOSActive=false;
	Window3D=NULL;
	Modified=false;
	Looping=true;
	RegNoWrite=false;
	SpaceFlag=gosFX::Effect::DynamicWorldSpaceSimulationMode;
	SceneBackground=NULL;
	TerrainGrid=NULL;
	LightState=NULL;
	fx_stream=NULL;
}

CPixelWhipProApp::~CPixelWhipProApp()
{
	//if(Window3D) delete Window3D;
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CPixelWhipProApp object

CPixelWhipProApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CPixelWhipProApp initialization

BOOL CPixelWhipProApp::InitInstance()
{
	AfxEnableControlContainer();
	
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.
	
#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif
	
	// Change the registry key under which our settings are stored.
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Microsoft\\ArtTools"));
	
	
	// To create the main window, this code creates a new frame window
	// object and then sets it as the application's main window object.
	
	CMDIFrameWnd* pFrame = new CMainFrame;
	m_pMainWnd = pFrame;
	
	// create main MDI frame window
	if (!pFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	
	// try to load shared MDI menus and accelerator table
	//TODO: add additional member variables and load calls for
	//	additional menu types your application may need. 
	
	HINSTANCE hInst = AfxGetResourceHandle();
	//m_hMDIMenu  = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
	m_hMDIAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
	
	
	
	// The main window has been initialized, so show and update it.
	pFrame->ShowWindow(m_nCmdShow);
	pFrame->UpdateWindow();
	
	WINDOWPLACEMENT wpl;
	ZeroMemory(&wpl,sizeof(WINDOWPLACEMENT));
	wpl.length=sizeof(WINDOWPLACEMENT);
	wpl.flags=WPF_RESTORETOMAXIMIZED;   
	wpl.showCmd=SW_SHOWMAXIMIZED;   
	
	pFrame->SetWindowPlacement(&wpl);
	
	Window3D=new CView3DChildWindow;
	Window3D->Create(NULL,
		"3D View Window",
		WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU,
		CRect(0,0,640,480+GetSystemMetrics(SM_CYCAPTION)),
		pFrame);
	
	
	GetTexturePath();
	InitGameOS(  m_hInstance , Window3D->m_hWnd,m_lpCmdLine);
	LastTime=gos_GetElapsedTime();
	FrameTime=0.0f;
	
	Window3D->ShowWindow(SW_SHOW);
	Window3D->GOSActive=GOSActive=true;
	Window3D->PostGosInit();
	Window3D->Fix3DView();
	
	EListWin=new CEffectListWin;
	CurveWin=new CCurveEditorFrame(m_pMainWnd);
	ParamWin=new CEffectEditWin;
	
	EListWin->Create(CEffectListWin::IDD,m_pMainWnd);
	ParamWin->LoadFrame(IDR_PARAMMENU,WS_OVERLAPPEDWINDOW,m_pMainWnd);
	
	
	CurveWin->SetWindowText("Curve Editor");
	ParamWin->SetWindowText("Effect Parameters");
	EListWin->SetWindowText("Effect List");
	
	LoadWindowStates();
	
	ParamWin->UpdateWindow();
	
	LightState = new ElementRenderer::StateChange;
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive ;new_index++)
		LightState->m_lights[new_index]=NULL;
	
	Register_Object(LightState);
	
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	Scene->AdoptStateChange(LightState);
	gosFX::LightManager::Instance=new CPPLightManager;
	gos_PopCurrentHeap();	
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CPixelWhipProApp message handlers

int CPixelWhipProApp::ExitInstance() 
{
/*
if (m_hMDIMenu != NULL)
FreeResource(m_hMDIMenu);
if (m_hMDIAccel != NULL)
FreeResource(m_hMDIAccel);
	*/
	return CWinApp::ExitInstance();
}



/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
	
	// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA
	
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	// No message handlers
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CPixelWhipProApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}


void __stdcall TerminateGameEngine();

void CPixelWhipProApp::GOSCleanUp()
{
	if(Scene)
	{
		Unregister_Object(Scene);
		delete Scene;
	}
	
	TerminateGameEngine();
	ExitGameOS();
	GOSActive=0;
}

BOOL CPixelWhipProApp::OnIdle(LONG lCount) 
{
	static bool inhere=false;
	
	gActive = true;
	gGotFocus= true;
	if(GOSActive && AllowDraw)
		if(RunGameOSLogic()) PostQuitMessage(0);
		
		inhere=false;
		//	  return AllowDraw;
		HRESULT res;
		res=CWinApp::OnIdle(lCount);
		if(res || AllowDraw) return 1;
		else
			return 0;
}


void CPixelWhipProApp::OnFileLoadscenebackground() 
{
	CFileDialog dlg1(TRUE,"erf",NULL,NULL,"ERF Geometry(*.erf)|*.erf||",m_pMainWnd);
	if(dlg1.DoModal()==IDOK)
	{
		LoadBackground(dlg1.GetPathName());
	}
}

void CPixelWhipProApp::OnFileClearscenebackground() 
{
	if(SceneBackground==NULL) return;
	
	StopEffects();	
	
	Scene->DetachChild(SceneBackground);
	delete SceneBackground;
	SceneBackground=NULL;
	
	StartEffects();	
}



void __stdcall InitializeGameEngine()
{
	//
	//---------------------
	// Initialize libraries
	//---------------------
	//
	Stuff::InitializeClasses();
	MidLevelRenderer::InitializeClasses(NULL, 8192*4*2, 1024*2);
	//	MidLevelRenderer::InitializeStatistics();
	
	gosFX::InitializeClasses();
	ElementRenderer::InitializeClasses();
	
	
	theApp.GetTexturePath();
	
	gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
	Scene = new ElementRenderer::GroupElement;
	Register_Object(Scene);
	Scene->SetRootMode();
	Scene->LockBounds();
	gos_PopCurrentHeap();
	
	//
	//------------------------
	// Set up the texture pool
	//------------------------
	//
	if(theApp.TexturePath.GetLength())
	{
		gos_PushCurrentHeap(MidLevelRenderer::TexturePoolHeap);
		PP2KTexturePool *pool = new PP2KTexturePool((LPCSTR)theApp.TexturePath);
		Register_Object(pool);
		MidLevelRenderer::MLRTexturePool::Instance = new MidLevelRenderer::MLRTexturePool(pool);
		Check_Object(MidLevelRenderer::MLRTexturePool::Instance);
		gos_PopCurrentHeap();
		
		Register_Object(MidLevelRenderer::MLRTexturePool::Instance);
		/*		
		Stuff::MString effects_name = (LPCSTR)theApp.TexturePath;
		int content_root_length = effects_name.GetLength() - 9;
		Verify(!_stricmp(&((char*)effects_name)[content_root_length], "Textures\\"));
		((char*)effects_name)[content_root_length] = '\0';
		*/	
		gos_PushCurrentHeap(gosFX::Heap);
		gosFX::EffectLibrary::Instance = new PP2KEffectLibrary;
		Register_Object(gosFX::EffectLibrary::Instance);
		gosFX::LightManager::Instance = new gosFX::LightManager;
		Register_Pointer(gosFX::LightManager::Instance);
		gos_PopCurrentHeap();
	}
	else
	{
		// fatal warning 
	}
	
	//---------------
	// Build a camera
	//---------------
	//
	gos_PushCurrentHeap(ElementRenderer::g_Heap);
	Camera_State = new ElementRenderer::StateChange();
	Register_Object(Camera_State);
	Camera_State->EnableBackfaceCulling();
	Camera_State->EnableDithering();
	Camera_State->EnablePerspectiveCorrection();
	Camera_State->EnableZBufferWrite();
	Camera_State->EnableZBufferCompare();
	//	Camera_State->SetFogMode(LightFogMode);
	Camera_State->SetFogColor(fogColor);
	Camera_State->SetFogMode(ElementRenderer::StateChange::DisableFogMode);
	
	Camera = new ElementRenderer::CameraElement(Camera_State);
	Register_Object(Camera);
	Scene->AttachChild(Camera);
	Camera->SetPerspective(1.0f, 1000.0f, Stuff::Pi_Over_3);
	Camera->SetViewport(1.0f, 1.0f, 0.0f, 0.0f);
	Camera->SetScene(Scene);
	Stuff::LinearMatrix4D origin;
	origin.BuildRotation(
		Stuff::EulerAngles(Camera_Direction.pitch, Camera_Direction.yaw, 0.0f)
		);
	origin.BuildTranslation(Stuff::Point3D(Camera_Direction));
	Camera->SetLocalToParent(origin);
	//	Camera->SetFogColor(fogColor);
	
	
	// Sync the matrices of the scene and load the textures
	Scene->Sync();
	
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
	gos_PopCurrentHeap();
	
}


void __stdcall DoGameLogic()
{
	if(!Camera_State) return;
	
	Check_Object(Camera_State);
	MidLevelRenderer::MLRState mlr_state = Camera_State->GetMLRState();
	
	Stuff::LinearMatrix4D mat(true);
	
	
	if(EffectWrapper!=NULL)
	{
		if(MoveFX)
		{
			double curtime=gos_GetElapsedTime();
			
			Point3D FXLoc;
			FrameTime+=curtime-LastTime;
			LastTime=curtime;
			if(FrameTime>MaxTime) 
			{
				theApp.StopEffects();
				theApp.StartEffects();
				FrameTime=0.0;
			}
			
			FXLoc.x=(float)(FrameTime*FrameTime*FXAcc.x+FXVel.x*FrameTime);
			FXLoc.y=(float)(FrameTime*FrameTime*FXAcc.y+FXVel.y*FrameTime);
			FXLoc.z=(float)(FrameTime*FrameTime*FXAcc.z+FXVel.z*FrameTime);
			
			mat.BuildTranslation(FXLoc);
		}
		EffectWrapper->SetLocalToParent(mat);
	}
	
	//
	//---------------
	// Read the mouse
	//---------------
	//
	int
		x_delta,
		y_delta;
	Stuff::Scalar 
		n_xdelta,
		n_ydelta;
	
	DWORD
		buttons;
	gos_GetMouseInfo(NULL, NULL, &x_delta, &y_delta, NULL, &buttons);
	Stuff::Scalar
		x_speed = x_delta * 0.01f,
		y_speed = y_delta * 0.01f;
	
	n_xdelta=(Stuff::Scalar)x_delta/Environment.screenWidth;
	n_ydelta=(Stuff::Scalar)y_delta/Environment.screenHeight;
	
	//
	//------------------------------------------------------
	// If the left Ctrl button is held down, move the camera
	//------------------------------------------------------
	//
	gosEnum_KeyStatus status = gos_GetKeyStatus(KEY_LCONTROL);
	if (status != KEY_FREE && status != KEY_RELEASED)
	{
		Camera_Direction.pitch += y_speed;
		Camera_Direction.yaw -= x_speed;
	}
	
	//
	//------------------------------------------------------
	// If the left Shift button is held down, pan the camera
	//------------------------------------------------------
	//
	status = gos_GetKeyStatus(KEY_LSHIFT);
	if (status != KEY_FREE && status != KEY_RELEASED)
	{
		Camera_Shift.x += n_xdelta*Camera_Direction.range;
		Camera_Shift.y += n_ydelta*Camera_Direction.range;
	}
	
	//
	//-----------------------------------------------------
	// If the left Alt button is held down, zoom the camera
	//-----------------------------------------------------
	//
	status = gos_GetKeyStatus(KEY_LMENU);
	if (status != KEY_FREE && status != KEY_RELEASED)
	{
		Camera_Direction.range *=(Stuff::Scalar)pow(2, n_ydelta);
	}
	
	
	Stuff::LinearMatrix4D TransMat(Stuff::Point3D(0.0f,0.0f,-Camera_Direction.range));
	Stuff::LinearMatrix4D RotMat(Stuff::EulerAngles(Camera_Direction.pitch,Camera_Direction.yaw , 0.0f));
	Stuff::LinearMatrix4D PanMat(Stuff::Point3D(Camera_Shift.x,Camera_Shift.y,0.0f));
	Stuff::LinearMatrix4D ViewMat,CameraMatrix;
	
	RotMat.BuildTranslation(Camera_LookAt);
	ViewMat.Multiply(PanMat,TransMat);
	CameraMatrix.Multiply(ViewMat,RotMat);
	Camera->SetLocalToParent(CameraMatrix);
	//	gosFX::Effect::s_LastCameraPosition=Stuff::Point3D(0.0f,0.0f,Camera_Direction.range);
	
	
	//
	//-------------------------------------------------------
	// Now that we have moved everything, update the matrices
	//-------------------------------------------------------
	//
	Camera->Sync();
	
	
	if(EffectWrapper!=NULL)
	{
		if(EffectWrapper->GetEffect()->HasFinished())
		{
			theApp.Set3DWindowTitle();
		}
		
		if(CurrentEffect->GetClassID()==gosFX::BeamClassID)
		{
			gosFX::Beam::ExecuteInfo info(gos_GetElapsedTime(),&mat,&theApp.TargetLoc,NULL);
			info.m_bounds = &EffectWrapper->m_localOBB;
			Start_Timer(gosFX::Animation_Time);
			if (
				EffectWrapper->GetEffect()->IsExecuted()
				&& ((gosFX::Beam *)EffectWrapper->GetEffect())->Execute(&info)
				&& EffectWrapper->m_localOBB.sphereRadius > 0.0f
				)
				EffectWrapper->NeedNewBounds();
			else
				EffectWrapper->SetAlwaysCullMode();
			
		}
		else
		{
			gosFX::Effect::ExecuteInfo info(gos_GetElapsedTime(),&mat,NULL);
			info.m_bounds = &EffectWrapper->m_localOBB;
			Start_Timer(gosFX::Animation_Time);
			if (
				EffectWrapper->GetEffect()->IsExecuted()
				&& EffectWrapper->GetEffect()->Execute(&info)
				&& EffectWrapper->m_localOBB.sphereRadius > 0.0f
				)
				EffectWrapper->NeedNewBounds();
			else
				EffectWrapper->SetAlwaysCullMode();
		}
		Stop_Timer(gosFX::Animation_Time);
		
		
		EffectWrapper->Sync();
	}
}

void __stdcall UpdateDisplay()
{
	Camera->DrawScene();
}

void __stdcall TerminateGameEngine()
{
	//--------------------
	// Turn off libraries
	//--------------------
	ElementRenderer::TerminateClasses();
	gosFX::TerminateClasses();
	MidLevelRenderer::TerminateClasses();
	Stuff::TerminateClasses();
}


void __stdcall GetGameOSEnvironment(char *CommandLine)
{
	
	//------------------------------------------------
	// gosEnvironment struct documented in GameOS.hpp
	//------------------------------------------------
	Environment.applicationName		= "PixelPro2000";
	// setup application title (window caption)
	Environment.version					= "01.01.04.0101";
	Environment.directoryPath			= ""; //"\\Binaries\\PixelWhip;\\Tools\\PixelWhip";
	Environment.screenWidth				= 640;
	Environment.screenHeight			= 480;
	Environment.bitDepth					= 16;		// 8 or 16
	Environment.fullScreen				= FALSE;
	Environment.Key_FullScreen			= NULL;	// Default is KEY_F4	(Enter/exit full screen mode)
	Environment.Key_Exit					= NULL;	// Default is KEY_ESC	(Exit full screen mode or exit game)
	Environment.debugLog					= "";		//"DebugLog.txt";	// File to dump info to, or "debugger" to the debug console
	
	
	Environment.spew						= "";	// List of groups to dump to debuglog - eg: GameOS_Texture, GameOS_DirectDraw
	Environment.TimeStampSpew			= FALSE;		// adds the current time stamp to all spews
	
	Environment.FullScreenDevice		= 0;			// 0=Primary, 1=2nd video card (ie: 3Dfx) etc...
	Environment.Renderer					= 0;			// 0=Try hardware, fallback to software, 1=RGB, 2=Refrast
	Environment.AntiAlias				= FALSE;		// true/false - Enable full screen antialiasing
	
	Environment.MaxTimeDelta			= 0.25f;
	Environment.MinimumTimeDelta		= 0.25f;
	
	//--------------------
	// Texture infomation
	//--------------------
	Environment.Texture_S_256			= 5;	// Number of 256*256 Solid texture heap pages
	Environment.Texture_S_128			= 9;	// Number of 128*128 Solid texture heap pages
	Environment.Texture_S_64			= 4;	// Number of   64*64 Solid texture heap pages
	Environment.Texture_S_32			= 8;	// Number of   32*32 Solid texture heap pages
	Environment.Texture_S_16			= 4;	// Number of   16*16 Solid texture heap pages
	
	Environment.Texture_K_256			= 2;	// Number of 256*256 Keyed texture heap pages
	Environment.Texture_K_128			= 1;	// Number of 128*128 Keyed texture heap pages (GameOS uses one 128*128 Keyed page)
	Environment.Texture_K_64			= 1;	// Number of   64*64 Keyed texture heap pages
	Environment.Texture_K_32			= 1;	// Number of   32*32 Keyed texture heap pages
	Environment.Texture_K_16			= 1;	// Number of   16*16 Keyed texture heap pages
	
	Environment.Texture_A_256			= 4;	// Number of 256*256 Alpha texture heap pages
	Environment.Texture_A_128			= 8;	// Number of 128*128 Alpha texture heap pages
	Environment.Texture_A_64			= 1;	// Number of   64*64 Alpha texture heap pages
	Environment.Texture_A_32			= 1;	// Number of   32*32 Alpha texture heap pages
	Environment.Texture_A_16			= 1;	// Number of   16*16 Alpha texture heap pages
	
	//------------------------
	// Application call-backs
	//------------------------
	Environment.InitializeGameEngine	= InitializeGameEngine;
	Environment.DoGameLogic				= DoGameLogic;
	Environment.UpdateRenderers		= UpdateDisplay;
	Environment.TerminateGameEngine	= TerminateGameEngine;
	Environment.soundDisable			= true;
	Environment.NetworkGame				= false;
	
}


void CPixelWhipProApp::GetTexturePath()
{
	
	TexturePath=GetProfileString("PixelPro2000","TexturePath");
	if(TexturePath.GetLength()==0) 
	{
		NewTexturePath();
	} // end if string in Registry
	
	
	if(TexturePath.GetLength())
	{
		if(MidLevelRenderer::MLRTexturePool::Instance)
		{
			Unregister_Object(MidLevelRenderer::MLRTexturePool::Instance);
			delete MidLevelRenderer::MLRTexturePool::Instance;
			
			MidLevelRenderer::TGAFilePool *pool = new MidLevelRenderer::TGAFilePool((LPCSTR)TexturePath);
			Register_Object(pool);
			MidLevelRenderer::MLRTexturePool::Instance = new MidLevelRenderer::MLRTexturePool(pool);
			Check_Object(MidLevelRenderer::MLRTexturePool::Instance);
			Register_Object(MidLevelRenderer::MLRTexturePool::Instance);
		}
	}
	
}

void myILFree(LPITEMIDLIST pidl) 
{ 
	LPMALLOC pMalloc; 
	
    if (pidl) 
    { 
#ifdef DEBUG 
		UINT cbSize = ILGetSize(pidl); 
		VALIDATE_PIDL(pidl); 
		
		// Fill the memory with some bad value... 
		_fmemset(pidl, 0xE5, cbSize); 
		
		// If large enough try to save the call return address of who 
		// freed us in the 3-6 byte of the structure. 
		if (cbSize >= 6) 
			*((UINT*)((LPSTR)pidl + 2)) =  *(((UINT*)&pidl) - 1); 
		
#endif 
		SHGetMalloc(&pMalloc); 
		pMalloc->Free( pidl); 
		pMalloc->Release(); 
		
    } 
} 

void CPixelWhipProApp::NewTexturePath()
{
	char pname[MAX_PATH];
	BROWSEINFO bi; 
	if(m_pMainWnd==NULL)
		bi.hwndOwner =NULL;
	else
		bi.hwndOwner = m_pMainWnd->m_hWnd; 
	
	bi.pidlRoot = NULL; 
	bi.pszDisplayName = NULL; 
	bi.lpszTitle = "Choose Texture Path..."; 
	bi.ulFlags = BIF_RETURNONLYFSDIRS; 
	bi.lpfn = NULL; 
	bi.lParam = (LPARAM)this; 
	
	LPITEMIDLIST pidl = SHBrowseForFolder(&bi); 
	
	if (SHGetPathFromIDList(pidl,pname))  
	{
		TexturePath=pname;
		TexturePath+="\\";
		
		
		WriteProfileString("PixelPro2000","TexturePath",TexturePath);
	}
	
	if (bi.pidlRoot) 
	{ 
		myILFree( const_cast< ITEMIDLIST* >( bi.pidlRoot ) );
	} 
	
}

void CPixelWhipProApp::OnOptionsSettexturepath() 
{
	NewTexturePath();	
	MessageBox(NULL,"You Must Restart for this Change to Take Effect","Restart",MB_OK);
}

void CPixelWhipProApp::RefreshAllWins()
{
	if(EListWin) EListWin->Refresh();
	if(ParamWin) ParamWin->Refresh();
	if(CurveWin) CurveWin->m_wndView.Refresh();
}

void CPixelWhipProApp::OnWindowsCurveeditor() 
{
	if(CurveWin)
	{
		CurveWin->ShowWindow(CurveWin->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}	
	
}

void CPixelWhipProApp::OnWindowsEffectlistwindow() 
{
	if(EListWin)
	{
		EListWin->ShowWindow(EListWin->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}	
	
}

void CPixelWhipProApp::OnWindowsEffectparameterwindow() 
{
	if(ParamWin)
	{
		ParamWin->ShowWindow(ParamWin->IsWindowVisible()?SW_HIDE:SW_SHOW);
	}	
	
}

void CPixelWhipProApp::OnUpdateWindowsCurveeditor(CCmdUI* pCmdUI) 
{
	if(CurveWin)
		pCmdUI->SetCheck(CurveWin->IsWindowVisible()?1:0);
	
}

void CPixelWhipProApp::OnUpdateWindowsEffectlistwindow(CCmdUI* pCmdUI) 
{
	if(EListWin)
		pCmdUI->SetCheck(EListWin->IsWindowVisible()?1:0);
	
}

void CPixelWhipProApp::OnUpdateWindowsEffectparameterwindow(CCmdUI* pCmdUI) 
{
	if(ParamWin)
		pCmdUI->SetCheck(ParamWin->IsWindowVisible()?1:0);
	
}


void CPixelWhipProApp::SaveWindowStates()
{
	if(RegNoWrite) return;	
	WriteProfileInt("PixelPro2000","CurveWinVis",CurveWin->IsWindowVisible());
	WriteProfileInt("PixelPro2000","ParamWinVis",ParamWin->IsWindowVisible());
	WriteProfileInt("PixelPro2000","EListWinVis",EListWin->IsWindowVisible());
	WriteProfileInt("PixelPro2000","Window3DVis",Window3D->IsWindowVisible());
	
	CRect rct;
	/*
	pFrame->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","pFrameXPos",rct.left);
	WriteProfileInt("PixelPro2000","pFrameYPos",rct.bottom);
	WriteProfileInt("PixelPro2000","pFrameXSize",rct.Width());
	WriteProfileInt("PixelPro2000","pFrameYSize",rct.Height());
	*/
	
	CurveWin->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","CurveWinXPos",rct.left);
	WriteProfileInt("PixelPro2000","CurveWinYPos",rct.top);
	WriteProfileInt("PixelPro2000","CurveWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","CurveWinYSize",rct.Height());
	
	ParamWin->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","ParamWinXPos",rct.left);
	WriteProfileInt("PixelPro2000","ParamWinYPos",rct.top);
	WriteProfileInt("PixelPro2000","ParamWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","ParamWinYSize",rct.Height());
	
	EListWin->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","EListWinXPos",rct.left);
	WriteProfileInt("PixelPro2000","EListWinYPos",rct.top);
	WriteProfileInt("PixelPro2000","EListWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","EListWinYSize",rct.Height());
	
	Window3D->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","Window3DXPos",rct.left);
	WriteProfileInt("PixelPro2000","Window3DYPos",rct.top);
	WriteProfileInt("PixelPro2000","Window3DXSize",rct.Width());
	WriteProfileInt("PixelPro2000","Window3DYSize",rct.Height());
	gos_SaveDataToRegistry("FireState",&FireState,sizeof(FireState));
	gos_SaveDataToRegistry("SmokeState",&SmokeState,sizeof(SmokeState));
}

void CPixelWhipProApp::LoadWindowStates()
{
	
	
	
	CRect rct;
	CurveWin->GetWindowRect(&rct);
	rct.left=(int)GetProfileInt("PixelPro2000","CurveWinXPos",0);
	rct.top=(int)GetProfileInt("PixelPro2000","CurveWinYPos",0);
	rct.right=rct.left+(int)GetProfileInt("PixelPro2000","CurveWinXSize",0);
	rct.bottom=rct.top+(int)GetProfileInt("PixelPro2000","CurveWinYSize",0);
	if(rct.Width()>0)
		CurveWin->SetWindowPos(NULL,rct.left,rct.top,rct.Width(),rct.Height(),SWP_NOZORDER);   
	
	
	
	rct.left=(int)GetProfileInt("PixelPro2000","ParamWinXPos",0);
	rct.top=(int)GetProfileInt("PixelPro2000","ParamWinYPos",0);
	rct.right=rct.left+(int)GetProfileInt("PixelPro2000","ParamWinXSize",0);
	rct.bottom=rct.top+(int)GetProfileInt("PixelPro2000","ParamWinYSize",0);
	if(rct.Width()>0)
		ParamWin->SetWindowPos(NULL,rct.left,rct.top,rct.Width(),rct.Height(),SWP_NOZORDER);   
	
	rct.left=(int)GetProfileInt("PixelPro2000","EListWinXPos",0);
	rct.top=(int)GetProfileInt("PixelPro2000","EListWinYPos",0);
	rct.right=rct.left+(int)GetProfileInt("PixelPro2000","EListWinXSize",0);
	rct.bottom=rct.top+(int)GetProfileInt("PixelPro2000","EListWinYSize",0);
	if(rct.Width()>0)
		EListWin->SetWindowPos(NULL,rct.left,rct.top,rct.Width(),rct.Height(),SWP_NOZORDER);   
	
	rct.left=(int)GetProfileInt("PixelPro2000","Window3DXPos",0);
	rct.top=(int)GetProfileInt("PixelPro2000","Window3DYPos",0);
	rct.right=rct.left+(int)GetProfileInt("PixelPro2000","Window3DXSize",0);
	rct.bottom=rct.top+(int)GetProfileInt("PixelPro2000","Window3DYSize",0);
	//	m_pMainWnd->ScreenToClient(&rct);
	/*
	rct.top-=GetSystemMetrics(SM_CYCAPTION);
	rct.bottom-=GetSystemMetrics(SM_CYCAPTION);
	rct.top-=GetSystemMetrics(SM_CYFRAME)*2;
	rct.bottom-=GetSystemMetrics(SM_CYFRAME)*2;
	*/
	//	rct.left-=GetSystemMetrics(SM_CXFRAME);
	//	rct.right-=GetSystemMetrics(SM_CXFRAME);
	if(rct.Width()>0)
		Window3D->SetWindowPos(NULL,rct.left,rct.top,rct.Width(),rct.Height(),SWP_NOZORDER);   
	
	
	CurveWin->ShowWindow(GetProfileInt("PixelPro2000","CurveWinVis",1)==0?SW_HIDE:SW_SHOW);
	ParamWin->ShowWindow(GetProfileInt("PixelPro2000","ParamWinVis",1)==0?SW_HIDE:SW_SHOW);
	EListWin->ShowWindow(GetProfileInt("PixelPro2000","EListWinVis",1)==0?SW_HIDE:SW_SHOW);
	Window3D->ShowWindow(GetProfileInt("PixelPro2000","Window3DVis",1)==0?SW_HIDE:SW_SHOW);
	
	unsigned long DatSize;
	DatSize=sizeof(FireState);
	gos_LoadDataFromRegistry("FireState",&FireState,&DatSize);
	if(DatSize!=0)
		if(DatSize!=sizeof(FireState))
		{
			MidLevelRenderer::MLRState tmpstate;
			FireState=tmpstate;
			gos_SaveDataToRegistry("FireState",&tmpstate,sizeof(tmpstate));
		}
		
		DatSize=sizeof(SmokeState);
		gos_LoadDataFromRegistry("SmokeState",&SmokeState,&DatSize);
		if(DatSize!=0)
			if(DatSize!=sizeof(FireState))
			{
				MidLevelRenderer::MLRState tmpstate;
				SmokeState=tmpstate;
				gos_SaveDataToRegistry("SmokeState",&tmpstate,sizeof(tmpstate));
			}
			
			
}

void CPixelWhipProApp::StopEffects()
{
	if(EffectWrapper)
	{
		Check_Object(EffectWrapper);	
		if(CurrentEffect)
		{
			//			CurrentEffect->Stop();
			CurrentEffect->Kill();
		}
		
		Unregister_Object(EffectWrapper);
		delete EffectWrapper;
		EffectWrapper=NULL;
		CurrentEffect=NULL;
	}
	
}

void CPixelWhipProApp::StartEffects()
{
	
	gosFX::Effect::Specification *spec;
	
	HTREEITEM CurItem;
	CurItem=EListWin->m_EffectList.GetSelectedItem();
	if(CurItem==NULL) return;
	
	spec=(gosFX::Effect::Specification *)EListWin->m_EffectList.GetItemData(CurItem);
	
	if(HasEmptyEffectCloud(spec)) return;
	
	CurrentEffect =
		gosFX::EffectLibrary::Instance->MakeEffect(
		spec->m_effectID,
		gosFX::Effect::ExecuteFlag |
		(Looping?gosFX::Effect::LoopFlag:0) |
		SpaceFlag
		//gosFX::Effect::DynamicWorldSpaceSimulationMode
		);
	Register_Object(CurrentEffect);
	
	gos_PushCurrentHeap(ElementRenderer::gosFXElement::s_Heap);
	EffectWrapper = new ElementRenderer::gosFXElement(CurrentEffect);
	Register_Object(EffectWrapper);
	gos_PopCurrentHeap();
	Scene->AttachChild(EffectWrapper);
	EffectWrapper->NeedNewBounds();
	
	if(CurrentEffect->GetClassID()==gosFX::BeamClassID)
	{
		gosFX::Beam::ExecuteInfo info(gos_GetElapsedTime(),&EffectWrapper->GetLocalToWorld(),&theApp.TargetLoc,NULL);
		((gosFX::Beam *)CurrentEffect)->Start(&info);
	}
	else
	{
		gosFX::Effect::ExecuteInfo info(gos_GetElapsedTime(),&EffectWrapper->GetLocalToWorld(),NULL);
		CurrentEffect->Start(&info);
	}
	
	Set3DWindowTitle();
}

void CPixelWhipProApp::ClearEffects()
{
	gosFX::EffectLibrary::Instance->m_effects.SetLength(0);
}



void CPixelWhipProApp::OnViewRestartplayback() 
{
	StopEffects();
	FrameTime=0.0f;
	StartEffects();
}


void CPixelWhipProApp::OnFileExport() 
{
	
	CFileDialog dlg1(FALSE,"txtfx",NULL,NULL,"Text Effects (*.txtfx)|*.txtfx||",m_pMainWnd);
	
	if(dlg1.DoModal()==IDOK)
	{
		FILE *fl;
		fl=fopen(dlg1.GetPathName(),"w");
		fprintf(fl,"NumberOfEffects=%i\n",gosFX::EffectLibrary::Instance->m_effects.GetLength());
		CString prefix="";
		LPCSTR prx=(LPCSTR)prefix;
		
		
		int effnum;
		
		for(effnum=0;effnum<gosFX::EffectLibrary::Instance->m_effects.GetLength();effnum++)
			
		{
			gosFX::Effect::Specification *spec=gosFX::EffectLibrary::Instance->m_effects[effnum];
			if(IsRootEffect(spec))
				ExportEffect(fl,spec,prefix);
		}
		
		fclose(fl);
	}
}



bool HasEmptyEffectCloud(gosFX::Effect::Specification *spec)
{
	if(spec->GetClassID()==gosFX::EffectCloudClassID)
	{
		gosFX::EffectCloud__Specification *tspec;
		tspec=Cast_Pointer(gosFX::EffectCloud__Specification *,spec);
		Check_Object(tspec);
		if(tspec->m_particleEffectID==BADINDEX) return true;
		else
			return HasEmptyEffectCloud(gosFX::EffectLibrary::Instance->m_effects[tspec->m_particleEffectID]);
		
	}
	else
	{
		
		Stuff::ChainIteratorOf<gosFX::Event*> eitr(&(spec->m_events));
		gosFX::Event *tmpevent;
		
		eitr.First();
		while(NULL!=(tmpevent=eitr.ReadAndNext()))
		{
			if(HasEmptyEffectCloud(gosFX::EffectLibrary::Instance->m_effects[tmpevent->m_effectID])) 
				return true;
		}
		
	}
	
	return false;
}

bool CPixelWhipProApp::CurrentFXIsValid()
{
	gosFX::Effect::Specification *spec;
	
	HTREEITEM CurItem;
	CurItem=EListWin->m_EffectList.GetSelectedItem();
	if(CurItem==NULL) return false;
	
	spec=(gosFX::Effect::Specification *)EListWin->m_EffectList.GetItemData(CurItem);
	
	if(HasEmptyEffectCloud(spec)) return false;
	return true;
}

void CPixelWhipProApp::OnViewLooping() 
{
	StopEffects();	
	Looping=!Looping;
	StartEffects();	
}

void CPixelWhipProApp::OnUpdateViewLooping(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(Looping?1:0);
}

void CPixelWhipProApp::OnViewDynamicworldspace() 
{
	StopEffects();	
	SpaceFlag=gosFX::Effect::DynamicWorldSpaceSimulationMode;
	StartEffects();	
}

void CPixelWhipProApp::OnViewLocalspace() 
{
	StopEffects();	
	SpaceFlag=gosFX::Effect::LocalSpaceSimulationMode;
	StartEffects();	
	
}

void CPixelWhipProApp::OnViewStaticworldspace() 
{
	StopEffects();	
	SpaceFlag=gosFX::Effect::StaticWorldSpaceSimulationMode;
	StartEffects();	
}

void CPixelWhipProApp::OnUpdateViewStaticworldspace(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(SpaceFlag==gosFX::Effect::StaticWorldSpaceSimulationMode?1:0);
}


void CPixelWhipProApp::OnUpdateViewLocalspace(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(SpaceFlag==gosFX::Effect::LocalSpaceSimulationMode?1:0);
	
}

void CPixelWhipProApp::OnUpdateViewDynamicworldspace(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(SpaceFlag==gosFX::Effect::DynamicWorldSpaceSimulationMode?1:0);
	
}


void CPixelWhipProApp::OnViewMovementoptions() 
{
	CMoveProps dlg;
	dlg.m_accx=FXAcc.x;
	dlg.m_accy=FXAcc.y;
	dlg.m_accz=FXAcc.z;
	dlg.m_velx=FXVel.x;	
	dlg.m_vely=FXVel.y;	
	dlg.m_velz=FXVel.z;	
	dlg.m_rtime=MaxTime;
	
	if(dlg.DoModal()==IDOK)
	{
		
		FXAcc.x=dlg.m_accx;
		FXAcc.y=dlg.m_accy;
		FXAcc.z=dlg.m_accz;
		FXVel.x=dlg.m_velx;	
		FXVel.y=dlg.m_vely;	
		FXVel.z=dlg.m_velz;	
		MaxTime=dlg.m_rtime;
	}
	
}

void CPixelWhipProApp::OnViewMoveeffect() 
{
	MoveFX=!MoveFX;	
	FrameTime=0.0f;
}

void CPixelWhipProApp::OnUpdateViewMoveeffect(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(MoveFX?1:0);
	
}

void CPixelWhipProApp::OnOptionsClearregistry() 
{
	WriteProfileInt("PixelPro2000","CurveWinVis",TRUE);
	WriteProfileInt("PixelPro2000","ParamWinVis",TRUE);
	WriteProfileInt("PixelPro2000","EListWinVis",TRUE);
	WriteProfileInt("PixelPro2000","Window3DVis",TRUE);
	
	CRect rct;
	/*
	pFrame->GetWindowRect(&rct);
	WriteProfileInt("PixelPro2000","pFrameXPos",rct.left);
	WriteProfileInt("PixelPro2000","pFrameYPos",rct.bottom);
	WriteProfileInt("PixelPro2000","pFrameXSize",rct.Width());
	WriteProfileInt("PixelPro2000","pFrameYSize",rct.Height());
	*/
	
	rct=CurveWin->rectDefault;
	WriteProfileInt("PixelPro2000","CurveWinXPos",rct.left);
	WriteProfileInt("PixelPro2000","CurveWinYPos",rct.top);
	WriteProfileInt("PixelPro2000","CurveWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","CurveWinYSize",rct.Height());
	
	rct=ParamWin->rectDefault;
	WriteProfileInt("PixelPro2000","ParamWinXPos",rct.left);
	WriteProfileInt("PixelPro2000","ParamWinYPos",rct.top);
	WriteProfileInt("PixelPro2000","ParamWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","ParamWinYSize",rct.Height());
	
	WriteProfileInt("PixelPro2000","EListWinXPos",10);
	WriteProfileInt("PixelPro2000","EListWinYPos",10);
	WriteProfileInt("PixelPro2000","EListWinXSize",rct.Width());
	WriteProfileInt("PixelPro2000","EListWinYSize",rct.Height());
	
	rct=Window3D->rectDefault;
	WriteProfileInt("PixelPro2000","Window3DXPos",rct.left);
	WriteProfileInt("PixelPro2000","Window3DYPos",rct.top);
	WriteProfileInt("PixelPro2000","Window3DXSize",rct.Width());
	WriteProfileInt("PixelPro2000","Window3DYSize",rct.Height());
	WriteProfileString("PixelPro2000","TexturePath","");
	RegNoWrite=true;
	
	MidLevelRenderer::MLRState tmpstate;
	gos_SaveDataToRegistry("FireState",&tmpstate,sizeof(tmpstate));
	gos_SaveDataToRegistry("SmokeState",&tmpstate,sizeof(tmpstate));
	
	MessageBox(NULL,"You Must Restart for this Change to Take Effect","Restart",MB_OK);
	
}


void CPixelWhipProApp::OnViewResetcamera() 
{
	Camera_Shift.x=0.0f;
	Camera_Shift.y=0.0f;
	Camera_LookAt.x=0.0f;
	Camera_LookAt.y=0.0f;
	Camera_LookAt.z=0.0f;
	Camera_Direction.yaw=0.0f;
	Camera_Direction.pitch=0.0f;
	Camera_Direction.range=10.0f;
	
}

void CPixelWhipProApp::OnOptionsSettofire() 
{
	MidLevelRenderer::MLRState EffState;
	
	if(CurrentEffect)
	{
		
		gosFX::Effect::Specification *spec=CurrentEffect->GetSpecification();
		spec->m_state=FireState;
		/*
		spec->m_state.SetAlphaMode(FireState.GetAlphaMode());
		spec->m_state.SetPriority(FireState.GetPriority());
		
		  if(FireState.GetZBufferWriteMode()==MidLevelRenderer::MLRState::ZBufferWriteOnMode)
		  spec->m_state.SetZBufferWriteOn();
		  else
		  spec->m_state.SetZBufferWriteOff();
		  
			if(FireState.GetZBufferCompareMode()==MidLevelRenderer::MLRState::ZBufferCompareOnMode)
			spec->m_state.SetZBufferCompareOn();
			else
			spec->m_state.SetZBufferCompareOff();
			
		*/
	}
	
}

void CPixelWhipProApp::OnOptionsSettosmoke() 
{
	if(CurrentEffect)
	{
		
		gosFX::Effect::Specification *spec=CurrentEffect->GetSpecification();
		spec->m_state=SmokeState;
		/*
		spec->m_state.SetAlphaMode(FireState.GetAlphaMode());
		spec->m_state.SetPriority(FireState.GetPriority());
		
		  if(FireState.GetZBufferWriteMode()==MidLevelRenderer::MLRState::ZBufferWriteOnMode)
		  spec->m_state.SetZBufferWriteOn();
		  else
		  spec->m_state.SetZBufferWriteOff();
		  
			if(FireState.GetZBufferCompareMode()==MidLevelRenderer::MLRState::ZBufferCompareOnMode)
			spec->m_state.SetZBufferCompareOn();
			else
			spec->m_state.SetZBufferCompareOff();
		*/
		
	}	
}

void CPixelWhipProApp::OnOptionsEditfirequickset() 
{
	CEditMLRStateDlg dlg1;
	Stuff::DynamicArrayOf<	MidLevelRenderer::MLRState> States(1);
	States[0]=FireState;
	
	dlg1.SetStates(&States);
	if(dlg1.DoModal()==IDOK)
	{
		FireState=States[0];
	}	
}

void CPixelWhipProApp::OnOptionsEditsmokequickset() 
{
	CEditMLRStateDlg dlg1;
	Stuff::DynamicArrayOf<	MidLevelRenderer::MLRState> States(1);
	States[0]=SmokeState;
	
	dlg1.SetStates(&States);
	if(dlg1.DoModal()==IDOK)
	{
		SmokeState=States[0];
	}	
}

void CPixelWhipProApp::OnFileLoadterrain() 
{
	
	CFileDialog dlg1(TRUE,"erf",NULL,NULL,"Terrain Geometry(*.erf)|*.erf||",m_pMainWnd);
	if(dlg1.DoModal()==IDOK)
	{
		LoadTerrain(dlg1.GetPathName());
		
	}
	
	
	
	
}

void CPixelWhipProApp::OnFileClearterrain() 
{
	if(TerrainGrid==NULL) return;
	StopEffects();	
	
	Scene->DetachChild(TerrainGrid);
	delete TerrainGrid;
	TerrainGrid=NULL;
	
	StartEffects();	
	
}

void CPixelWhipProApp::OnFileLoadlights() 
{
	
	CFileDialog dlg1(TRUE,"lights",NULL,NULL,"MLR Lights(*.lights)|*.lights||",m_pMainWnd);
	if(dlg1.DoModal()==IDOK)
	{
		CString light_file_name=dlg1.GetPathName();
		
		LoadLights(light_file_name);
		
	}
}

void CPixelWhipProApp::OnFileClearlights() 
{
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive ;new_index++)
		if(LightState->m_lights[new_index])
		{
			Unregister_Object(LightState->m_lights[new_index]);
			delete LightState->m_lights[new_index];
			LightState->m_lights[new_index]=NULL;
		}
}

void CPixelWhipProApp::OnFileLoadlastworkspace() 
{
	BackGroundFilePath=GetProfileString("PixelPro2000","BackGround","");
	LightFilePath=GetProfileString("PixelPro2000","Lights","");
	TerrainFilePath=GetProfileString("PixelPro2000","Terrain","");
	
	if(BackGroundFilePath.GetLength()>0)
		LoadBackground(BackGroundFilePath);
	
	if(LightFilePath.GetLength()>0)
		LoadLights(LightFilePath);
	
	if(TerrainFilePath.GetLength()>0)
		LoadTerrain(TerrainFilePath);
	
		/*
		Stuff::MString erf_name("C:\\temp\\Test.erf");
		
		  Scene->SetRootMode();
		  
			Stuff::FileStream element_stream(erf_name, Stuff::FileStream::WriteOnly);
			ElementRenderer::WriteERFVersion(&element_stream);
			Scene->Save(&element_stream);
	*/
	
	
}


void CPixelWhipProApp::LoadLights(CString light_file_name)
{
	LightFilePath=light_file_name;
	SaveWorkSpaceInfo();
	
	SetCurrentDirectory(light_file_name.Left(light_file_name.ReverseFind('\\')));
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	
	Stuff::NotationFile light_file((char *)(LPCSTR)LightFilePath);
	Stuff::NotationFile::PageIterator *light_page_list = light_file.MakePageIterator();
	
	OnFileClearlights();
	int last_slot=0;
	
	Page *light_page_entry;
	while ((light_page_entry = light_page_list->ReadAndNext()) != NULL)
	{
		const char *tmpchr;
		
		light_page_entry->GetEntry("LightType",&tmpchr);
		CString ltype(tmpchr);
		if(ltype.CompareNoCase("LookUp"))
		{
			LightState->m_lights[last_slot]=
				MidLevelRenderer::MLRLight::Make(light_page_entry);
			Check_Object(LightState->m_lights[last_slot]);
			last_slot++;
		}
	}
	
	gos_PopCurrentHeap();
	
	Check_Object(light_page_list);
	delete light_page_list;
	
	
}

void CPixelWhipProApp::LoadTerrain(CString terrain_file_name)
{
	TerrainFilePath=terrain_file_name;
	SaveWorkSpaceInfo();
	
	if(	TerrainGrid!=NULL ) OnFileClearterrain();
	TerrainGrid=new ElementRenderer::GroupElement;
	
	StopEffects();	
	CString tstr(TerrainFilePath);
	MString *erf_name=new Stuff::MString;
	*erf_name=Stuff::MString((LPCSTR)tstr);
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream *erf_file=new Stuff::FileStream(*erf_name);
	
	ElementRenderer::Element *tmpele;
	
	while(erf_file->GetBytesRemaining() > 0)
	{
		tmpele =
			ElementRenderer::Element::Create(
			erf_file,
			ElementRenderer::ReadERFVersion(erf_file)
			);
		TerrainGrid->AttachChild(tmpele);
		tmpele->ClearAlignX();
		tmpele->SetNeverCullMode();
		tmpele->SetLocalToParent(Stuff::LinearMatrix4D::Identity);
		
	}
	
	Scene->AttachChild(TerrainGrid);
	
	
	
	Scene->Sync();
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();	
	
	delete erf_name;
	StartEffects();	
	
}

void CPixelWhipProApp::LoadBackground(CString background_file_name)
{
	BackGroundFilePath=background_file_name;
	SaveWorkSpaceInfo();
	if(	SceneBackground!=NULL ) OnFileClearscenebackground();
	
	StopEffects();	
	CString tstr(BackGroundFilePath);
	MString *erf_name=new Stuff::MString;
	*erf_name=Stuff::MString((LPCSTR)tstr);
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream *erf_file=new Stuff::FileStream(*erf_name);
	
	SceneBackground =
		ElementRenderer::Element::Create(
		erf_file,
		ElementRenderer::ReadERFVersion(erf_file)
		);
	
	ElementRenderer::StateChange *state;
	state=Scene->GetStateChange();
	state->SetLightingMode(MidLevelRenderer::MLRState::VertexLightingMode|MidLevelRenderer::MLRState::FaceLightingMode);
	Scene->AttachChild(SceneBackground);
	
	Scene->Sync();
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();	
	
	
	delete erf_name;
	StartEffects();	
	
	
}

void CPixelWhipProApp::SaveWorkSpaceInfo()
{
	
	WriteProfileString("PixelPro2000","BackGround",BackGroundFilePath);
	WriteProfileString("PixelPro2000","Lights",LightFilePath);
	WriteProfileString("PixelPro2000","Terrain",TerrainFilePath);
	
}

void CPixelWhipProApp::Set3DWindowTitle()
{
	if(CurrentFXIsValid())
	{
		Stuff::Vector3D vect;
		Stuff::Point3D FXLoc,CameraLoc;
		FXLoc=EffectWrapper->GetLocalToParent();
		CameraLoc=Camera->GetLocalToParent();
		vect.Subtract(FXLoc,CameraLoc);
		
		CString wintitle;
		wintitle.Format("3D View - Distance to Effect = %5.3f",vect.GetLength());
		theApp.Window3D->SetWindowText(wintitle);
	}
}


Stuff::Scalar CPixelWhipProApp::GetEffectDistance()
{
	if(CurrentFXIsValid())
	{
		Stuff::Vector3D vect;
		Stuff::Point3D FXLoc,CameraLoc;
		FXLoc=EffectWrapper->GetLocalToParent();
		CameraLoc=Camera->GetLocalToParent();
		vect.Subtract(FXLoc,CameraLoc);
		return vect.GetLength();
	}
	return -1;
}

void CPixelWhipProApp::FixEffectNameTable()
{
	int effnum;
	gosFX::EffectLibrary::Instance->m_effectNames.SetLength(gosFX::EffectLibrary::Instance->m_effects.GetLength());
	for(effnum=0;effnum<gosFX::EffectLibrary::Instance->m_effects.GetLength();effnum++)
	{
		Verify(gosFX::EffectLibrary::Instance->m_effects[effnum]->m_effectID==effnum);
		//	gosFX::EffectLibrary::Instance->m_effects[effnum]->m_effectID=effnum;
		gosFX::EffectLibrary::Instance->m_effectNames[effnum] = gosFX::EffectLibrary::Instance->m_effects[effnum]->m_name;
	}
	
	
}


void CPixelWhipProApp::VerifyEffectLib()
{
	int *ref_array;
	int effecttot=gosFX::EffectLibrary::Instance->m_effects.GetLength();
	
	
	ref_array=new int[effecttot];
	
	int cureff,j;
	
	for(j=0;j<effecttot;j++) ref_array[j]=0;
	
	for(cureff=0;cureff<effecttot;cureff++)
	{
		Stuff::ChainIteratorOf<gosFX::Event*> eitr(&(gosFX::EffectLibrary::Instance->m_effects[cureff]->m_events));
		gosFX::Event *tmpevent;
		eitr.First();
		
		while(NULL!=(tmpevent=eitr.ReadAndNext()) )
		{
			
			if(	ref_array[tmpevent->m_effectID]>0)
			{
				PAUSE(("effect %s is childed twice,Reference Deleted from %s",
					(char *)gosFX::EffectLibrary::Instance->m_effects[tmpevent->m_effectID]->m_name,
					(char *)gosFX::EffectLibrary::Instance->m_effects[cureff]->m_name));
				Unregister_Pointer(tmpevent);
				delete tmpevent;
				
				if(EListWin) EListWin->Refresh();
				cureff=-1;	
				for(j=0;j<effecttot;j++) ref_array[j]=0;
				break;
			}
			else
				ref_array[tmpevent->m_effectID]++;
			
			
			
		}
		
	}
	
	
	/*
	for(cureff=0;cureff<effecttot;cureff++) 
	{
	if(ref_array[cureff]>1)
	{
	gosFX::Effect::Specification *debugspec=gosFX::EffectLibrary::Instance->m_effects[cureff];
	CString str;
	str.Format("effect %s is childed twice",(char *)gosFX::EffectLibrary::Instance->m_effects[cureff]->m_name);
	m_pMainWnd->MessageBox(str,"Hiearchy Corruption",MB_OK);
	}
	}
	
	  ref_array[cureff]=0;
	*/
	
	
}

bool TranslateName(CString &tname,NotationFile &hint_file)
{
	
	const char *tstr;
	Page*page=hint_file.FindPage(tname);
	if(page && page->GetEntry("alias",&tstr))
	{
		tname=tstr;
		return true;
	}
	else
		return false;
	
	
}

void CPixelWhipProApp::TranslateTextureNames()
{
	NotationFile hint_file(TexturePath+"Textures.hint");
	
	for(int effnum=0;effnum<gosFX::EffectLibrary::Instance->m_effects.GetLength();effnum++)
	{
		gosFX::Effect::Specification *spec=gosFX::EffectLibrary::Instance->m_effects[effnum];
		if(spec->m_state.GetTextureHandle()!=0)
		{
			
			CString tname(((*MidLevelRenderer::MLRTexturePool::Instance)[&spec->m_state])->GetTextureName());
			if(TranslateName(tname,hint_file))
			{
				MidLevelRenderer::MLRTexture *tex=MidLevelRenderer::MLRTexturePool::Instance->Add((LPCSTR)tname);
				spec->m_state.SetTextureHandle(tex->GetTextureHandle());
				Modified=true;
			}
		}
	}	
	
	
}

