/** 
 * @file llselectmgr.h
 * @brief A manager for selected objects and TEs.
 *
 * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
 * $License$
 */

#ifndef LL_LLSELECTMGR_H
#define LL_LLSELECTMGR_H

#include "llcharacter.h"
#include "lldarray.h"
#include "lleditmenuhandler.h"
#include "llstring.h"
#include "llundo.h"
#include "lluuid.h"
#include "llmemory.h"
#include "llsaleinfo.h"
#include "llcategory.h"
#include "v3dmath.h"
#include "llquaternion.h"
#include "llcoord.h"
#include "llframetimer.h"
#include "llbbox.h"
#include "llpermissions.h"

#include <deque>

class LLMessageSystem;
class LLViewerImage;
class LLViewerObject;
class LLColor4;
class LLVector3;
class LLSelectNode;

const S32 SELECT_ALL_TES = -1;
const S32 SELECT_MAX_TES = 32;

// Do something to all objects in the selection manager.
// The bool return value can be used to indicate if all
// objects are identical (gathering information) or if
// the operation was successful.
class LLSelectedObjectFunctor
{
public:
	virtual ~LLSelectedObjectFunctor() {};
	virtual bool apply(LLViewerObject* object) = 0;
};

// Do something to all select nodes in the selection manager.
// The bool return value can be used to indicate if all
// objects are identical (gathering information) or if
// the operation was successful.
class LLSelectedNodeFunctor
{
public:
	virtual ~LLSelectedNodeFunctor() {};
	virtual bool apply(LLSelectNode* node) = 0;
};

typedef enum e_send_type
{
	SEND_ONLY_ROOTS,
	SEND_INDIVIDUALS,
	SEND_ROOTS_FIRST, // useful for serial undos on linked sets
	SEND_CHILDREN_FIRST // useful for serial transforms of linked sets
} ESendType;

typedef enum e_grid_mode
{
	GRID_MODE_WORLD,
	GRID_MODE_LOCAL,
	GRID_MODE_REF_OBJECT
} EGridMode;

typedef enum e_action_type
{
	SELECT_ACTION_TYPE_BEGIN,
	SELECT_ACTION_TYPE_PICK,
	SELECT_ACTION_TYPE_MOVE,
	SELECT_ACTION_TYPE_ROTATE,
	SELECT_ACTION_TYPE_SCALE,
	NUM_ACTION_TYPES
}EActionType;

typedef enum e_selection_type
{
	SELECT_TYPE_WORLD,
	SELECT_TYPE_ATTACHMENT,
	SELECT_TYPE_HUD
}ESelectType;

class LLSelectNodeList : public std::list<LLSelectNode*>
{
public:
	LLSelectNodeList();
	virtual ~LLSelectNodeList();

	void updateEffects();

	BOOL isEmpty();

	S32 getOwnershipCost(S32 &cost);

	LLSelectNode* getFirstNode();
	LLSelectNode* getCurrentNode(); // Warning!  This is NOT the same as the linked_list getCurrentNode
	LLSelectNode* getNextNode();

	LLSelectNode *getFirstRootNode();
	LLSelectNode *getNextRootNode();

	// iterate through objects
	LLViewerObject* getFirstObject();
	LLViewerObject* getNextObject();

	// iterate through root objects
	LLViewerObject *getFirstRootObject();
	LLViewerObject *getNextRootObject();

	// iterate through texture entries
	void getPrimaryTE(LLViewerObject* *object, S32 *te);
	void getFirstTE(LLViewerObject* *object, S32 *te);
	void getNextTE(LLViewerObject* *object, S32 *te);
	void getCurrentTE(LLViewerObject* *object, S32 *te);

	void addNode(LLSelectNode *nodep);
	void addNodeAtEnd(LLSelectNode *nodep);
	void removeNode(LLSelectNode *nodep);
	void deleteAllNodes();			// Delete all nodes
	S32 getNumNodes();
	LLSelectNode* findNode(LLViewerObject* objectp);
private:
	const LLSelectNodeList &operator=(const LLSelectNodeList &);

	std::list<LLSelectNode*>::iterator mCurrentNode;
	S32 mCurrentTE;
	std::map<LLViewerObject*, LLSelectNode*> mSelectNodeMap;
};

struct LLSelectAction
{
public:
	EActionType	mActionType;
	LLVector3	mPosition;
	LLVector3	mScale;
	LLQuaternion	mRotation;
	LLUUID		mObjectID;
	BOOL		mIndividualSelection;
};

class LLSelectMgr : public LLEditMenuHandler
{
public:
	static BOOL					sRectSelectInclusive;	// do we need to surround an object to pick it?
	static BOOL					sRenderHiddenSelections;	// do we show selection silhouettes that are occluded?
	static BOOL					sRenderLightRadius;	// do we show the radius of selected lights?
	static F32					sHighlightThickness;
	static F32					sHighlightUScale;
	static F32					sHighlightVScale;
	static F32					sHighlightAlpha;
	static F32					sHighlightAlphaTest;
	static F32					sHighlightUAnim;
	static F32					sHighlightVAnim;
	static LLColor4				sSilhouetteParentColor;
	static LLColor4				sSilhouetteChildColor;
	static LLColor4				sHighlightParentColor;
	static LLColor4				sHighlightChildColor;
	static LLColor4				sContextSilhouetteColor;
public:
	LLSelectMgr();
	~LLSelectMgr();

	// LLEditMenuHandler interface
	virtual BOOL canUndo();
	virtual void undo();

	virtual BOOL canRedo();
	virtual void redo();

	virtual BOOL canDoDelete();
	virtual void doDelete();

	virtual void deselect();
	virtual BOOL canDeselect();

	virtual void duplicate();
	virtual BOOL canDuplicate();

	// Apply functors to various subsets of the selected objects
	// Returns the AND of all apply() calls.
	bool applyToRootObjects(LLSelectedObjectFunctor* func);
	bool applyToObjects(LLSelectedObjectFunctor* func);
	bool applyToNodes(LLSelectedNodeFunctor* func);

	void updateEffects(); // Update HUD effects

	void setForceSelection(BOOL force) { mForceSelection = force; }

	// For when you want just a child object.
	void selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);

	// This method is meant to select an object, and then select all
	// of the ancestors and descendents. This should be the normal behavior.
	void selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);

	// Same as above, but takes a list of objects.  Used by rectangle select.
	void selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE);

	void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE);

	void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE);

	void deselectTransient(); // deselect "temporarily" selected objects (via pie menu)
	void convertTransient(); // converts temporarily selected objects to full-fledged selections

	// Send deselect messages to simulator, then clear the list
	void deselectAll();

	// Deselect if the selection center is too far away from the agent.
	void deselectAllIfTooFar();

	BOOL selectionRemoveObject(const LLUUID &id);

	BOOL contains(LLViewerObject* object);
	BOOL contains(LLViewerObject* object, S32 te);

	ESelectType getSelectType() { return mSelectType; }

	// count members
	S32 getObjectCount();
	S32 getTECount();
	S32 getRootObjectCount();

	BOOL isEmpty()				{ return !mSelectedObjects.getNumNodes(); }

	BOOL shouldShowSelection()	{ return mShowSelection; }

	LLSelectNodeList &getHoverObjects() { return mHoverObjects; }
	LLSelectNodeList &getSelectedObjects() { return mSelectedObjects; }

	// iterate through objects
	LLViewerObject* getFirstObject()	{ return mSelectedObjects.getFirstObject(); }
	LLViewerObject* getNextObject()		{ return mSelectedObjects.getNextObject(); }

	// iterate through root objects
	LLViewerObject *getFirstRootObject()	{ return mSelectedObjects.getFirstRootObject(); }
	LLViewerObject *getNextRootObject()		{ return mSelectedObjects.getNextRootObject(); }

	LLViewerObject* getFirstHighlightedObject() { return mHighlightedObjects.getFirstObject(); }
	LLViewerObject* getNextHighlightedObject() { return mHighlightedObjects.getNextObject(); }

	// iterate through tes
	void getPrimaryTE(LLViewerObject* *object, S32 *te) { mSelectedObjects.getPrimaryTE(object, te); }
	void getFirstTE(LLViewerObject* *object, S32 *te)	{ mSelectedObjects.getFirstTE(object, te); }
	void getNextTE(LLViewerObject* *object, S32 *te)	{ mSelectedObjects.getNextTE(object, te); };

	void setHoverObject(LLViewerObject *objectp);
	
	void addGridObject(LLViewerObject* objectp);
	void clearGridObjects();
	void setGridMode(EGridMode mode);
	EGridMode getGridMode() { return mGridMode; }
	void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale);

	void highlightObjectOnly(LLViewerObject *objectp);
	void highlightObjectAndFamily(LLViewerObject *objectp);
	void highlightObjectAndFamily(const LLDynamicArray<LLViewerObject*>& list);
	void unhighlightObjectOnly(LLViewerObject *objectp);
	void unhighlightObjectAndFamily(LLViewerObject *objectp);
	void unhighlightAll();
	void selectHighlightedObjects();
	void deselectHighlightedObjects();

	LLSelectNode *findSelectNode(LLViewerObject *objectp);
	LLSelectNode *getFirstRootNode()	{ return mSelectedObjects.getFirstRootNode(); }
	LLSelectNode *getNextRootNode()		{ return mSelectedObjects.getNextRootNode(); }
	LLSelectNode* getFirstNode()	{ return mSelectedObjects.getFirstNode(); }
	LLSelectNode* getNextNode()		{ return mSelectedObjects.getNextNode(); }

	LLSelectNode *getHoverNode();

	BOOL getTEMode()			{ return mTEMode; }
	void setTEMode(BOOL b)	{ mTEMode = b; }

	LLViewerObject*	getFirstCopyableObject(BOOL get_root = FALSE);
	LLViewerObject*	getFirstEditableObject(BOOL get_root = FALSE);
	LLViewerObject*	getFirstMoveableObject(BOOL get_root = FALSE);
	LLViewerObject* getFirstDeleteableObject(BOOL get_root = FALSE);

	LLSelectNode*	getFirstEditableNode(BOOL get_root = FALSE);
	LLSelectNode*	getFirstMoveableNode(BOOL get_root = FALSE);

	LLBBox getBBoxOfSelection() const;
	LLBBox getSavedBBoxOfSelection() const { return mSavedSelectionBBox; }

	BOOL areMultpleEditableObjectsSelected();

	void dump();
	void cleanup();

	void updateSilhouettes();
	void renderSilhouettes(BOOL for_hud);
	void enableSilhouette(BOOL enable) { mRenderSilhouettes = enable; }
	
	// Utility functions to operate on the list

	void			saveSelectedObjectTransform(EActionType action_type);
	void			saveSelectedObjectColors();
	void			saveSelectedObjectTextures();

	void			selectionUpdatePhysics(BOOL use_physics);
	void			selectionUpdateTemporary(BOOL is_temporary);
	void			selectionUpdatePhantom(BOOL is_ghost);
	void			selectionUpdateCastShadows(BOOL cast_shadows);
	void			selectionDump();

	BOOL selectionAllPCode(LLPCode code);		// all objects have this PCode
	BOOL selectionGetMaterial(U8 *material);	// all objects have same material
	BOOL selectionGetTexUUID(LLUUID& id);		// true if all selected tes have same texture
	BOOL selectionGetColor(LLColor4 &color);	// all tes have same color
	BOOL selectionGetTexScale(F32 *u, F32 *v);	// true if all selected tes have same scale
	BOOL selectionGetTexOffset(F32 *u, F32 *v);	// true if all selected tes have same offset
	BOOL selectionGetTexRotation(F32 *rad);		// true if all selected tes have same rotation
	BOOL selectionGetBumpmap(U8 *bumpmap);			// true if all selected tes have same
	BOOL selectionGetShiny(U8 *shiny);			// true if all selected tes have same
	BOOL selectionGetFullbright(U8 *fullbright);// true if all selected tes have same
	bool selectionGetMediaType(U8 *media_type);	// true if all selected tes have same
	BOOL selectionGetClickAction(U8* action);

	void selectionSetMaterial(U8 material);
	void selectionSetImage(const LLUUID& imageid); // could be item or asset id
	void selectionSetColor(const LLColor4 &color);
	void selectionSetColorOnly(const LLColor4 &color); // Set only the RGB channels
	void selectionSetAlphaOnly(const F32 alpha); // Set only the alpha channel
	void selectionRevertColors();
	BOOL selectionRevertTextures();
	void selectionSetBumpmap( U8 bumpmap );
	void selectionSetTexGen( U8 texgen );
	void selectionSetShiny( U8 shiny );
	void selectionSetFullbright( U8 fullbright );
	void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url );
	void selectionSetClickAction(U8 action);

	void setObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE);
	void setObjectName(const LLString& name);
	void setObjectDescription(const LLString& desc);
	void setObjectCategory(const LLCategory& category);
	void setObjectSaleInfo(const LLSaleInfo& sale_info);

	void selectionTexScaleAutofit(F32 repeats_per_meter);
	void selectionResetTexInfo(S32 te);						// sets S,T to 1
	void adjustTexturesByScale(BOOL send_to_sim, BOOL stretch);
	BOOL getTESTAxes(const LLViewerObject* object, const U8 te, U32* s_axis, U32* t_axis);	// Only for flex boxes

	void selectionResetRotation();				// sets rotation quat to identity
	void selectionRotateAroundZ(F32 degrees);
	void sendGodlikeRequest(const LLString& request, const LLString& parameter);


	// will make sure all selected object meet current criteria, or deselect them otherwise
	void validateSelection();

	// returns TRUE if it is possible to select this object
	BOOL canSelectObject(LLViewerObject* object);

	// Returns true if the viewer has information on all selected objects
	BOOL selectGetAllRootsValid();
	BOOL selectGetAllValid();

	// returns TRUE if you can modify all selected objects. 
	BOOL selectGetRootsModify();
	BOOL selectGetModify();

	// returns TRUE if selected objects can be transferred.
	BOOL selectGetRootsTransfer();

	// returns TRUE if selected objects can be copied.
	BOOL selectGetRootsCopy();
	
	BOOL selectGetCreator(LLUUID& id, LLString& name);					// true if all have same creator, returns id
	BOOL selectGetOwner(LLUUID& id, LLString& name);					// true if all objects have same owner, returns id
	BOOL selectGetLastOwner(LLUUID& id, LLString& name);				// true if all objects have same owner, returns id

	// returns TRUE if all are the same. id is stuffed with
	// the value found if available.
	BOOL selectGetGroup(LLUUID& id); 
	BOOL selectGetPerm(	U8 which_perm, U32* mask_on, U32* mask_off);	// true if all have data, returns two masks, each indicating which bits are all on and all off
	BOOL selectGetOwnershipCost(S32* cost);								// sum of all ownership costs

	BOOL selectIsGroupOwned();											// true if all root objects have valid data and are group owned.

	// returns TRUE if all the nodes are valid. Accumulates
	// permissions in the parameter.
	BOOL selectGetPermissions(LLPermissions& perm);

	// returns TRUE if anything is for sale. calculates the total
	// price and stores that value in price.
	BOOL selectIsForSale(S32& price);

	// returns TRUE if all nodes are valid. 
	BOOL selectGetCategory(LLCategory& category);
	
	// returns TRUE if all nodes are valid. method also stores an
	// accumulated sale info.
	BOOL selectGetSaleInfo(LLSaleInfo& sale_info);

	// returns TRUE if all nodes are valid. fills passed in object
	// with the aggregate permissions of the selection.
	BOOL selectGetAggregatePermissions(LLAggregatePermissions& ag_perm);

	// returns TRUE if all nodes are valid. fills passed in object
	// with the aggregate permissions for texture inventory items of the selection.
	BOOL selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm);

	// returns TRUE is any node is currenly worn as an attachment
	BOOL selectionIsAttachment();

	LLPermissions* findObjectPermissions(const LLViewerObject* object);

	void selectDelete();							// Delete on simulator
	void	selectForceDelete();			// just delete, no into trash
	void selectDuplicate(const LLVector3& offset, BOOL select_copy);	// Duplicate on simulator
	void repeatDuplicate();
	void		selectDuplicateOnRay(const LLVector3 &ray_start_region,
									   const LLVector3 &ray_end_region,
									   BOOL bypass_raycast,
									   BOOL ray_end_is_intersection,
									   const LLUUID &ray_target_id,
									   BOOL copy_centers,
									   BOOL copy_rotates,
									   BOOL select_copy);

	void sendMultipleUpdate(U32 type);	// Position, rotation, scale all in one
	void sendOwner(const LLUUID& owner_id, const LLUUID& group_id, BOOL override = FALSE);
	void sendGroup(const LLUUID& group_id);

	// Category ID is the UUID of the folder you want to contain the purchase
	// FIXME: sale_info check doesn't work for multiple object buy, which UI does not currently support
	// sale info is used for verification only, if it doesn't match region info then sale is canceled
	void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info);
	void sendAttach(U8 attachment_point);
	void sendDetach();
	void sendDropAttachment();
	void sendLink();
	void sendDelink();
	void sendHinge(U8 type);
	void sendDehinge();
	void sendSelect();

	void requestObjectPropertiesFamily(LLViewerObject* object);	// asks sim for creator, permissions, resources, etc.
	static void processObjectProperties(LLMessageSystem *mesgsys, void **user_data);
	static void processObjectPropertiesFamily(LLMessageSystem *mesgsys, void **user_data);
	static void processForceObjectSelect(LLMessageSystem* msg, void**);

	void requestGodInfo();

	LLVector3d		getSelectionCenterGlobal() const	{ return mSelectionCenterGlobal; }
	void			updateSelectionCenter();
	void			updatePointAt();

	// Internal list maintenance functions. TODO: Make these private!
	void remove(LLDynamicArray<LLViewerObject*>& objects);
	void remove(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE);
	void removeAll();
	void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE);
	void promoteSelectionToRoot();
	void demoteSelectionToIndividuals();

private:
	
	ESelectType getSelectTypeForObject(LLViewerObject* object);
	void addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add_to_end = FALSE);
	void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point);
	void getSilhouetteExtents(LLSelectNode* nodep, const LLQuaternion& orientation, LLVector3& min_extents, LLVector3& max_extents);
	// Send one message to each region containing an object on selection list.
	void sendListToRegions(	const LLString& message_name,
							void (*pack_header)(void *user_data), 
							void (*pack_body)(LLSelectNode* node, void *user_data), 
							void *user_data,
							ESendType send_type);
	U32 undoRedo(std::deque<LLSelectAction*> &queue_src, std::deque<LLSelectAction*> &queue_dst, const LLUUID &object_id);

	static void packAgentID(	void *);
	static void packAgentAndSessionID(void* user_data);
	static void packAgentAndGroupID(void* user_data);
	static void packAgentAndSessionAndGroupID(void* user_data);
	static void packAgentIDAndSessionAndAttachment(void*);
	static void packAgentGroupAndCatID(void*);
	static void packDeleteHeader(void* userdata);
	static void packDeRezHeader(void* user_data);
	static void packObjectID(	LLSelectNode* node, void *);
	static void packObjectIDAsParam(LLSelectNode* node, void *);
	static void packObjectIDAndRotation(	LLSelectNode* node, void *);
	static void packObjectLocalID(LLSelectNode* node, void *);
	static void packObjectClickAction(LLSelectNode* node, void* data);
	static void packObjectName(LLSelectNode* node, void* user_data);
	static void packObjectDescription(LLSelectNode* node, void* user_data);
	static void packObjectCategory(LLSelectNode* node, void* user_data);
	static void packObjectSaleInfo(LLSelectNode* node, void* user_data);
	static void packBuyObjectIDs(LLSelectNode* node, void* user_data);
	static void packDuplicate(	LLSelectNode* node, void *duplicate_data);
	static void packDuplicateHeader(void*);
	static void packDuplicateOnRayHead(void *user_data);
	static void packPermissions(LLSelectNode* node, void *user_data);
	static void packDeselect(	LLSelectNode* node, void *user_data);
	static void packMultipleUpdate(LLSelectNode* node, void *user_data);
	static void packPhysics(LLSelectNode* node, void *user_data);
	static void packShape(LLSelectNode* node, void *user_data);
	static void packOwnerHead(void *user_data);
	static void packHingeHead(void *user_data);
	static void packPermissionsHead(void* user_data);
	static void packGodlikeHead(void* user_data);
	static void confirmDelete(S32 option, void* data);
	
private:
	LLPointer<LLViewerImage> mSilhouetteImagep;

	LLSelectNodeList		mSelectedObjects;

	LLSelectNodeList		mHoverObjects;

	std::set<LLPointer<LLViewerObject> >	mRectSelectedObjects;
	
	LLSelectNodeList		mGridObjects;
	LLQuaternion			mGridRotation;
	LLVector3				mGridOrigin;
	LLVector3				mGridScale;
	EGridMode				mGridMode;
	BOOL					mGridValid;

	LLSelectNodeList		mHighlightedObjects;

	BOOL					mTEMode;			// render te
	LLVector3d				mSelectionCenterGlobal;
	LLBBox					mSelectionBBox;

	LLVector3d				mLastSentSelectionCenterGlobal;
	BOOL					mShowSelection; // do we send the selection center name value and do we animate this selection?
	LLVector3d				mLastCameraPos;		// camera position from last generation of selection silhouette
	BOOL					mRenderSilhouettes;	// do we render the silhouette
	LLBBox					mSavedSelectionBBox;

	ESelectType				mSelectType;

	LLFrameTimer			mEffectsTimer;
	BOOL					mForceSelection;

	std::deque<LLSelectAction*>	mUndoQueue;
	std::deque<LLSelectAction*>	mRedoQueue;

	LLAnimPauseRequest	mPauseRequest;
};


// Contains information about a selected object, particularly which
// tes are selected.
class LLSelectNode
{
public:
	LLSelectNode(LLViewerObject* object, BOOL do_glow);
	LLSelectNode(const LLSelectNode& nodep);
	~LLSelectNode();

	void selectAllTEs(BOOL b);
	void selectTE(S32 te_index, BOOL selected);
	BOOL isTESelected(S32 te_index);
	S32 getLastSelectedTE();
	void renderOneSilhouette(const LLColor4 &color);
	void setTransient(BOOL transient) { mTransient = transient; }
	BOOL isTransient() { return mTransient; }
	LLViewerObject *getObject();
	//FIXME: invalidate stored textures and colors when # faces change
	void saveColors();
	void saveTextures(const std::vector<LLUUID>& textures);
	void saveTextureScaleRatios();

	BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const;

public:
	BOOL			mIndividualSelection;		// For root objects and objects individually selected

	BOOL			mTransient;
	BOOL			mValid;				// is extra information valid?
	LLPermissions*	mPermissions;
	LLSaleInfo		mSaleInfo;
	LLAggregatePermissions mAggregatePerm;
	LLAggregatePermissions mAggregateTexturePerm;
	LLAggregatePermissions mAggregateTexturePermOwner;
	LLString		mName;
	LLString		mDescription;
	LLCategory		mCategory;
	S16				mInventorySerial;
	LLVector3		mSavedPositionLocal;	// for interactively modifying object position
	LLVector3d		mSavedPositionGlobal;	// for interactively modifying object position
	LLVector3		mSavedScale;			// for interactively modifying object scale
	LLQuaternion	mSavedRotation;			// for interactively modifying object rotation
	BOOL			mDuplicated;
	LLVector3d		mDuplicatePos;
	LLQuaternion	mDuplicateRot;
	LLUUID			mItemID;
	LLUUID			mFolderID;
	LLUUID			mFromTaskID;
	LLString		mTouchName;
	LLString		mSitName;
	std::vector<LLColor4>	mSavedColors;
	std::vector<LLUUID>		mSavedTextures;
	std::vector<LLVector3>  mTextureScaleRatios;
	std::vector<LLVector3>	mSilhouetteVertices;	// array of vertices to render silhouette of object
	std::vector<LLVector3>	mSilhouetteNormals;	// array of normals to render silhouette of object
	std::vector<S32>		mSilhouetteSegments;	// array of normals to render silhouette of object
	BOOL					mSilhouetteExists;	// need to generate silhouette?

protected:
	LLPointer<LLViewerObject>	mObject;
	BOOL			mTESelected[SELECT_MAX_TES];
	S32				mLastTESelected;
};

extern LLSelectMgr* gSelectMgr;

// Utilities
void dialog_refresh_all();		// Update subscribers to the selection list

#endif
