//
// Tools_Mode_Smoothing.h
//
// Created by Kevin Lea - 16/07/2001 16:22:33
// 
// Copyright (C) 2001 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_MODE_SMOOTHING_H__
#define __TOOLS_MODE_SMOOTHING_H__

#include "Tools_Mode.h"
#include "Core/Asura_Handle.h"
#include "Misc/Tools_Polygon_Selection.h"
#include "Misc/list_tem.hpp"

class ModulePolygonAdjacencies;
#define NotCurvedSmoothingFlag 0x80000000
///////////////////////////////////////////////////////////////////////////////////////
struct SmoothingUndoData
{
	enum UndoType
	{
		//only 1 type of undo at the moment
		UndoType_SmoothingChanged,
		UndoType_ForceInt = 0xffffffff,
	};
	
	enum UndoType undo_type;
	PolygonID polygon;
	int smoothing_groups;
};

class SmoothingModeUndo : public FixedSizeUndo
{
public :
	SmoothingModeUndo()
	:FixedSizeUndo(10000,sizeof(SmoothingUndoData)){}

	void ProcessUndoData(void*);
	
	void LogSmoothingChanged(const PolygonID& polygon);
};

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

class Tools_Mode_Smoothing : public Tools_Mode
{
	public:

		Tools_Mode_Smoothing()
		{
			Initialise();
		}
		~Tools_Mode_Smoothing()
		{
			Shutdown();
		}

		void Initialise(void);

		void Update(void);
		void RenderWorld_PostToneMap(void);
		void RenderUI(void);
		
		void Shutdown(void);

 		virtual bool IsModified();

		//resets render meshes for this polygon , and the meshes for adjacent polygons
		static void ResetMeshesAroundPolygon(const PolygonID& xPolygon);

		virtual void HandleMeshChange(int iModuleIndex);

	
	private:
		static void TransferModeData(int mode);

		static void Tools_Mode_Smoothing::HandleKeyboard(void);

		static void Tools_Mode_Smoothing::ApplySmoothingGroup(void);
		static void Tools_Mode_Smoothing::RemoveSmoothingGroup(void);
		static void Tools_Mode_Smoothing::ClearAllSmoothingGroups(void);
		static void Tools_Mode_Smoothing::ApplyCurveFlag(void);
		static void Tools_Mode_Smoothing::RemoveCurveFlag(void);
		static void Tools_Mode_Smoothing::SetSmoothingGroup(int smooth_bit,bool add);

		static void SelectGroup();
		static void DeselectGroup();
		static void SelectGroupMain(bool bSelect);
		

		static void ToggleSmoothingOverlay(void);
		static bool SmoothingOverlayIsOn(void);
		static void CreateSmoothingOverlay(void);
		
		//gives each polygon a colour coded outline
		static void HighlightSmoothing(void);

		//logs current state of selection for undo
		static void PrepareUndo();
		static void Undo();
		static void Redo();

		static void DetermineSmoothGroupOverlayPosition();
		static bool MouseIsOverSmoothGroupOverlay();
		static void HandleSmoothGroupOverlay();
		static void RenderSmoothGroupOverlay();

		//autosmoothing
		static void Autosmooth();


		
		///////////////////////////
		//data
		static Asura_Handle MenuHandle;

		static Asura_Vector_2 SmoothingOverlayPosition;
		static bool	SmoothingOverlayOpen;
  
		static int CurrentSmoothingGroup;//selected smoothing group from 1 to 32

		//some viewing options
		static bool HighlightAll;
		static bool HighlightCurrentGroup;
		static bool s_bDiscoLights;

		static SmoothingModeUndo SmoothingUndo;

		//coordinates for the smoothing group selection 'overlay'	
		static Asura_Vector_2 SmoothGroupOverlayMin;
		static Asura_Vector_2 SmoothGroupOverlayMax;

		static ModulePolygonAdjacencies** Adjacencies;
		static float AutosmoothAngle;//in degrees

};

///////////////////////////////////////////////////////////////////////////////////////
//structures for working out the polygon adjacencies , for the autosmoothing

struct PolygonAndAngle
{
	PolygonAndAngle(){}
	PolygonAndAngle(int m,int p,Asura_Angle a)
	:Polygon(m,p),Angle(a)
	{}
	
	PolygonID Polygon;
	Asura_Angle Angle;
};

struct PolygonAdjacencies
{
	List<PolygonAndAngle> AdjacencyList;
};


class ModulePolygonAdjacencies
{
	public :
		ModulePolygonAdjacencies(int module);
		~ModulePolygonAdjacencies();
			
		int ModuleIndex;
		int NumPolygons;
		List<PolygonAndAngle>* AdjacencyLists;

};

struct PolyAutosmoothInfo
{
	PolyAutosmoothInfo(){smooth_groups=0;allowed_groups = 0x7fffffff;done=false;in_queue=false;}

	int smooth_groups;//assigned smoothing group flags
	int allowed_groups;//currently allowed smoothing group flags
	bool done;
	bool in_queue;
};

#endif//__TOOLS_MODE_SMOOTHING_H__
