//
// Tools_Mode_Texturing.h
//
// Created by Kevin Lea - 20/06/2001 15:01:38
// 
// Copyright (C) 2001 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_MODE_TEXTURING_H__
#define __TOOLS_MODE_TEXTURING_H__

#include "Tools_Mode.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_Handle.h"
#include "Core/Asura_Material_System.h"
#include "Mesh/Asura_Mesh.h"
#include "Misc/Tools_Polygon_Selection.h"
#include "Misc/Tools_Modal_Overlay.h"


//Maximum number of secondary textures to allow in a level.
#ifndef TOOLS_MAX_SECONDARY_TEXTURES
#define TOOLS_MAX_SECONDARY_TEXTURES 10
#endif

//Maximum total size allowed for PS2 secondary textures
#ifndef TOOLS_MAX_PS2_SECONDARY_TEXTURE_SIZE
#define TOOLS_MAX_PS2_SECONDARY_TEXTURE_SIZE (10*128*128)
#endif


///////////////////////////////////////////////////////////////////////////////////////



enum TextureWrapMode
{
	TextureWrapMode_None,
	TextureWrapMode_Spread,
	TextureWrapMode_Tile,
	TextureWrapMode_Box,
	TextureWrapMode_BoxTile,
};

enum TexturingModeEnum
{
	TexturingMode_Selection,//mode in which polygons are selected by clicking on them
	TexturingMode_NodeEdit,//mode in which the texture is drawn in the corner of the screen with the nodes
};

enum PromptedSelectionModeEnum
{
	PSM_None,//no prompted selection.. left clicking does standard selection
	PSM_PolygonForTextureWrap,
	PSM_PolygonForTextureTile,
	PSM_PolygonForTextureWrapBox,
	PSM_PolygonForTextureWrapBoxTile,
	PSM_BasePolygon_ApplyTextureAndUVs,
	PSM_BasePolygon_ApplyUVs,
	PSM_BasePolygon_NodeEdit,
	PSM_PolygonForTextureCopy,
	PSM_ObjectCopy_From,
	PSM_ObjectCopy_To,
	PSM_MultipleCopy_From1,
	PSM_MultipleCopy_From2,
	PSM_MultipleCopy_To1,
	PSM_MultipleCopy_To2,
	PSM_AlignTexture_PolyToAlter,
	PSM_AlignTexture_PolyToAlignWith,
	PSM_EditMaterialOnPolygon,
	PSM_GetMaterialOnPolygon,
	#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
	PSM_GetFirstMaterialOnPolygonForSecondary,
	PSM_GetSecondMaterialOnPolygonForSecondary,
	#endif
};

class Tools_UV_Editor;

class Tools_Mode_Texturing : public Tools_Mode
{
	public:
		
		Tools_Mode_Texturing()
		{
			Initialise();
		}
		~Tools_Mode_Texturing()
		{
			Shutdown();
		}

		

		// Kevin Lea - 20/06/2001 15:02:21 - Tools_Mode methods
		void Initialise(void);
		void RenderWorld_PostToneMap(void);
		void RenderUI(void);
		void Update(void);
		void Shutdown(void);

 		virtual bool IsModified();
		virtual void QuickSave();

		virtual void HandleMeshChange(int iModuleIndex);


		//Indicates whether UV operations should affect this channel
		static bool IsEditingChannel(int iTextureChannel);
		//gets index of texture channel that is the 'main' one , when editing several at a time
		static int GetPrimaryEditedChannel();

		//Indicates whether UV operations should affect this channel for a given material
		static bool ShouldEditUVsForChannel(int iTextureChannel,int iMaterialID);
		

		//get scale for texture channel when editing multiple at once
		static float GetUVScaleForChannel(int iTextureChannel);

		static bool IsEditingAllChannels();
		static bool IsEditingPrimaryChannel(){return IsEditingChannel(0);}

		//gets proportion of PS2 secondary texture memory used. 1 being max
		static void GetPS2SecondaryTextureUsage(int& iNumTextures,float& fTextureUse,List<int>* pxTextureList=0);
		
		//Get a material that is similar to the base material , but with the texture changed in the
		//specified channel
		static int GetMaterialWithTexture(int iBaseMaterialID,int iTextureID,int iBumpTextureID,int iSpecularTextureID,int iChannel);

		//sets the current material , but doesn't apply it
		#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void SetMaterialResponse(Asura_Hash_ID uMaterialResponse);
		static void SetSecondMaterialResponse(Asura_Hash_ID uMaterialResponse);
		#endif
		static void SetMaterialID(int iMaterialID);

		static void SetMaterialFromPolygon(const PolygonID& xPoly);

		//Sets the current material/material response based on the selected polygons
		static void SetMaterialFromSelection();

	private:
		//////////////////////////////////////////////////////////////////////////////////
		// Kevin Lea - 22/06/2001 16:23:22 - data
		
		//menus and overlays
		static Asura_Handle MenuHandle;
		static Asura_Vector_2 OptionsOverlayPosition;
		static bool	OptionsOverlayOpen;
		static u_int s_uOptionsOverlayMinimised;
		static Asura_Vector_2 TileTextureOverlayPosition;
		static Asura_Vector_2 CopyOverlayPosition;
		static bool	CopyOverlayOpen;
		static u_int s_uCopyOverlayMinimised;


		static bool StandardInputDisabledForModalOverlay;

		static Asura_Vector_2 NodeEditOverlayPosition;
		static u_int s_uNodeEditOverlayMinimised;



		
		//undo
		//the main mode thing
		static enum TexturingModeEnum TexturingMode;

		static bool MultipleNodeMode;

		//enumeration of things that prompt the user to select a polygon
		//before they can continue
		static PromptedSelectionModeEnum PromptedSelectionMode;
		static void SetPromptedSelectionMode(enum PromptedSelectionModeEnum mode){PromptedSelectionMode = mode;}

		//2 normals used for defining the plane and orientation in texture wraping/tiling
		static Asura_Vector_3 TextureWrap_X;
		static Asura_Vector_3 TextureWrap_Y;
		static Asura_Vector_3 TextureWrap_Z;
		static enum TextureWrapMode WrapMode;//determines whether texture wrapping mode is on , and if so what style
		static Asura_Vector_2 TextureTile_Scale;//scaling for texture tiling (metres per texture?)
		static Asura_Vector_2 TextureTile_Offset;//offset for texture tiling 
		static float TextureTile_OffsetScale;
		static bool	TextureTile_Changed;

		//For the texture repeats overlay
		static Asura_Vector_2 TextureRepeats;
		static Asura_Vector_2 TextureRepeatsOrigin;
		static int s_iTextureRepeat_NodeAdjustment;
		static bool TextureRepeatsChanged;

		static Asura_Vector_2 s_xTextureRepeatsOverlayPosition;
		static bool s_bTextureRepeatsOverlayOpen;
		static u_int s_uTextureRepeatsOverlayMinimised;

		enum
		{
			TEXTUREREPEAT_LEAVENODES,
			TEXTUREREPEAT_NODESTOCORNER,
			TEXTUREREPEAT_SCALENODES,
		};

		//For alpha painting overlay
		static Asura_Vector_2 s_xAlphaOverlayPosition;
		static bool	s_bAlphaOverlayOpen;
		static u_int s_uAlphaOverlayMinimised;

		//polygon used for deciding how to orient textures
		//and used for taking texture coordinates from
		static PolygonID BasePolygon;

		//miscellaneous selected polygons used by different functions
		static PolygonID SelectedPolygon1;
		static PolygonID SelectedPolygon2;

		static bool s_bShowTextureUnderCursor;

		//bitfield indicating which UV channels are currently being edited
		static u_int s_uEditedChannels;
		//scaling factor for secondary UVs when editing both channels at once.
		static float s_fSecondaryUVScale;

		//For editing just those UV channels that contain a given texture
		static bool s_bLimitUVEditingToSelectedTexture;
		static int s_iTextureForUVEditing;

		//Alpha painting
		static bool s_bAlphaPainting;
		static bool s_bAlphaPaint_AffectNearestVert;
		static float s_fAlphaPaint_Radius;
		static float s_fAlphaPaint_Alpha[2];
		static bool s_bAlphaPaint_UseHoming;
		static float s_fAlphaPaint_HomingRate;
		static bool s_bAlphaPaint_SelectedOnly;
		static bool s_bAlphaPaint_ShowSphere;
		static bool s_bAlphaPaint_ButtonClickedForPaint;

		//and secondary textures
		
		static bool s_bAlphaPaint_ApplyTexture;//true if second texture is applied at same time as alpha paint
		static bool s_bAlphaPaint_AllowTextureOverwrite;//allow second texture to be applied to polygons that already have
		static bool s_bAlphaPaint_SetUVs;
		#ifndef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static int s_iAlphaPaint_TextureSlot;
		static int s_iAlphaPaint_TextureSlot_ListOffset;
		static int s_iAlphaPaint_TextureSlot_ListSelection;
		static int s_aiSecondaryTextures[3][TOOLS_MAX_SECONDARY_TEXTURES+1];
		static char* s_apszSecondaryTextureNames[3][TOOLS_MAX_SECONDARY_TEXTURES+1];
		#endif

		//for display while editing nodes
		static bool s_bShowCoordsInTexels;

		static int s_iSelectedMaterialID;
		#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static Asura_Hash_ID s_uSelectedMaterialResponse;
		static Asura_Hash_ID s_uSelectedMaterialResponse2;
		#endif

		static bool s_bApplyMaterialOnTextureWrap;
		
		static Asura_Angle s_fRotationAngle;//angle to use when rotating nodes

		static class Tools_UVEdit* s_pxUVEdit;


	public :
		
		//details of texture currently being used
		static Tools_UV_Editor* s_pxTextureEdit;

	private :

		////////////////////////////////////////////////////////////////////////////////////
		
		// Kevin Lea - 22/06/2001 15:36:39 - by making functions static, their pointers
		// can be passed to other routines (for callback by menus/overlays etc.)
		// However, any data that needs to be accessed by these functions needs to be static
		// also - not a problem, but large arrays should be allocated
		

		static void ToggleOptionsOverlay(void);
		static bool OptionsOverlayIsOn(void);
		static void CreateOptionsOverlay(void);

		static void CreateTextureTileOverlay(void);
		static void CreateNodeEditOverlay(void);

		static void SetMenubarForMode();

		static void ToggleCopyOverlay(void);
		static bool CopyOverlayIsOn(void);
		static void CreateCopyOverlay(void);

		static void ToggleAlphaOverlay(void);
		static bool AlphaOverlayIsOn(void);
		static void CreateAlphaOverlay(void);

		static void CreateTextureRepeatsOverlay();
		static void ToggleTextureRepeatsOverlay();
		static bool IsTextureRepeatsOverlayOpen();
		static void UpdateTextureRepeats();
		static void SetSingleTextureRepeat();

		static void ToggleUVEditOverlay();
		static bool IsUVEditOverlayOpen();

		//mode switching
		static void SwitchToNodeEditMode();
		static void SwitchToSelectionMode();
		
		//glowy polygon outline highlight thing
		static void HighlightPolygon(PolygonID& polygon);
		
		//checks for keyboard shortcuts being pressed
		static void HandleKeyboard();

		//for handling general polygon selection using the mouse
		static void HandleNormalSelection();
		//handles cases where the user has been asked to select a polygon
		static void UpdatePromptedSelection();
		static void RenderPromptedSelection();
				
		//handle mouse control in node edit
		static void HandleMouseForNodeEdit();
				
		static void ShowStatusText();

		
		static void ApplyTextureAndUVs();
		static void ApplyTextureAndUVs(bool bPrepareUndo);
		static void ApplyUVs();
		static void ApplyUVs(bool bPrepareUndo);
		//places the current texture and all polygons , leaving coordinates alone
		static void ApplyTexture();
		static void ApplyTexture(bool bPrepareUndo);
		
		//functions for handling wrapping a texture across multiple polygons
		static void TextureWrapBox_Start();
		static void TextureWrapBoxTile_Start();
		static void TextureWrapSpread_Start();
		static void TextureWrap_PolygonSelected(PolygonID polygon);
		static void TextureWrap_Apply();
		static void TextureWrap_Stop();

		static void TextureWrapBox_Apply();

		//copying texturing
		static void TextureCopyPolygon_Start();
		static void TextureCopyPolygon_Apply(PolygonID polygon);
		static void TextureCopyObject_Start();
		static void TextureCopyObject_Apply();
		

		//for tiling a texture across polygons to give a specified number of pixels per distance
		static void TextureWrapTile_Start();

		//aligning texturing
		static void TextureAlign_Start();
		static void TextureAlign_PolygonSelected(PolygonID polygon);
		static bool TextureAlign_Apply();


		//simple uv adjustment
		static void AdjustUV_XFlip();
		static void AdjustUV_YFlip();
		static void AdjustUV_Rotate();
		static void AdjustUV_Cycle();
		static void AdjustUV_Reverse();
		static void AdjustUV_RotateNodeCentre();
		static void AdjustUV_Shift();
		static void AdjustUV_Scale();

		static void SyncUVChannelsPriToSec();
		static void SyncUVChannelsSecToPri();

		static void NodesToCorners();

		static void ClampNodes();
		static void FitUsedAreaToNodes();
		static void EvenlyDistributeUVs();
		static void SnapNodesToNearestTexel();

#if !defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void NextMaterial();
		static void PreviousMaterial();
#endif




		//texture selection
#if !defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void ChooseMaterial();
#else
		static void ChooseMaterialResponse();
#endif
		static void EditTextureFlags();
		

		//some things get reset when the polygon selection is cleared
		static void SelectionIsNowEmpty();


		//functions for undo
		static void PrepareUndo();
		static void Undo();
		static void Redo();

		static void DisableInputForModalOverlay(){StandardInputDisabledForModalOverlay = true;}
		
			
		//loads/saves data for this mode
		static void TransferModeData(int mode);


		//alpha painting
		static bool IsAlphaPainting();
		static bool IsUsingAlphaHoming();
		static bool IsEnabled_AlphaPaintRadius();

		static void UpdateAlphaOverlay();
		static void UpdateAlphaPainting();
		static void RenderAlphaPainting();
		static void SetAlphaOnSelected();
		#ifdef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void SelectSecondMaterial();
		static void SetSecondMaterialOnSelected();
		static void SetSecondMaterialOnSelected(Asura_Hash_ID uMaterial);
		static void RemoveSecondMaterialFromSelected();
		#else
		static void SetSecondTextureOnSelected();
		static void SetSecondTextureOnSelected(int iSlot);
		static void RemoveSecondTextureFromSelected();
		#endif
		//One off scan when entering texturing mode for polygons with invalid secondary textures
		//or those that have alpha values without a secondary texture.
		static void FixSecondaryTextureAnomalies();

		#ifndef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void InitialiseSecondaryTextureArray();
		static void BuildSecondaryTextureNames();
		static void DeleteSecondaryTextureNames();
		#endif //ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		
		
		#ifndef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static bool CanEditSecondaryTexture();
		static void EditSecondaryTexture();
		static void EditSecondaryBumpTexture();
		static void ClearSecondaryBumpTexture();
		static void EditSecondarySpecularTexture();
		static void ClearSecondarySpecularTexture();
		#endif //ASURA_USE_MATERIAL_RESPONSE_SYSTEM

		//prompts for polygon , and shows material editing overlay
		static void EditMaterialOnPolygon();
		static void EditMaterialOnPolygon_PolygonSelected(PolygonID xPolygon);

		static void GetMaterialOnPolygon();
		static void GetMaterialOnPolygon_PolygonSelected(PolygonID xPolygon);

		#ifdef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static void GetFirstMaterialOnPolygonForSecondary();
		static void GetFirstMaterialOnPolygonForSecondary_PolygonSelected(PolygonID xPolygon);
		static void GetSecondMaterialOnPolygonForSecondary();
		static void GetSecondMaterialOnPolygonForSecondary_PolygonSelected(PolygonID xPolygon);
		#endif

		static void LimitUVEditingToSelectedTextureClicked();
		static bool IsEnabled_EditTexture();

		#ifdef ASURA_USE_MATERIAL_RESPONSE_SYSTEM
		static bool s_bMaterialResponseOverlayWasOpenBeforeMode;
		#endif


		static enum DialogID
		{
			DialogID_PS2Usage,
			DialogID_SecondaryMaterial,
		};
		
		friend class Tools_Texturing_Copy;
		friend class Tools_UV_Editor;
};

class UVShiftOverlay : public Tools_Modal_Overlay
{
	public :
		UVShiftOverlay(int iWidth,int iHeight);
		bool DoModal();

		float GetUShift(){return m_fShiftU/m_iWidth;}
		float GetVShift(){return m_fShiftV/m_iHeight;}

	private :
		void InitialiseOverlay(class Asura_Overlay* pxOverlay);

		static void OkaySelected(int iData);
		static void CancelSelected(int iData);


		float m_fShiftU;
		float m_fShiftV;

		int m_iWidth;
		int m_iHeight;

		bool m_bReturnValue;
};

class UVScaleOverlay : public Tools_Modal_Overlay
{
	public :
		UVScaleOverlay();
		bool DoModal();

		float m_fScaleU;
		float m_fScaleV;

	private :
		void InitialiseOverlay(class Asura_Overlay* pxOverlay);
		void Update();

		static void OkaySelected(int iData);
		static void CancelSelected(int iData);

		bool m_bReturnValue;
		bool m_bUniformScale;
		bool m_bUChanged;
		bool m_bVChanged;
};

//main undo data for this mode
class Tools_Texturing_UndoData_TextureInfo : public RootUndoData
{
public :
	static void Create(const PolygonID& xPoly);
	static void Create(const PolygonID& xPoly,VariableSizeUndo* pxUndoSystem);

	virtual RootUndoData* ProcessUndoData();

	virtual const char* GetDescription() const{return "Texturing";}
	virtual int GetPriority() const {return 0;}

private :
	Tools_Texturing_UndoData_TextureInfo(const PolygonID& xPoly);

	PolygonID m_xPoly;
	Asura_Mesh_TextureInfo m_xTextureInfo;

};


extern void Tools_UpdateTexturingOnSurfaces(Asura_Mesh* mesh, bool bInvalidateCollisionMesh = true);

#endif//__TOOLS_MODE_TEXTURING_H__
