/*======================================================================*/
/* 3DLib								*/
/*									*/
/* Scene header file							*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Dec-09 23:03:56					*/
/*									*/
/* 3DLib(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DScene_h
#define _E3DScene_h


#ifndef _E3DAnimation_h
#include <E3D/Animation.h>
#endif

#ifndef _E3DItem_h
#include <E3D/Item.h>
#endif


#ifndef _E3DLight_h
#include <E3D/Light.h>
#endif


#ifndef _E3DMaterial_h
#include <E3D/Material.h>
#endif

#ifndef _E3DModel_h
#include <E3D/Model.h>
#endif


#ifndef _E3DRendering_h
#include <E3D/Rendering.h>
#endif


#ifndef _E3DUndo_h
#include <E3D/Undo.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif



// E3dp_WindowsRedrawByChangeFlags() uses these flags that determine
// which windows should be redrawn.
// For example, the SetFrameProc of Animations should set this
//
#define	E3dCHG_LIGHT		0x01
#define	E3dCHG_CAMERA		0x02
#define	E3dCHG_HIDEUNHIDE	0x04
#define	E3dCHG_TRANSFORM	0x08
#define	E3dCHG_SHAPE		0x10
#define	E3dCHG_MATERIAL		0x20
#define	E3dCHG_2DTEXTURE	0x40


// Scene callback reasons
//
enum
{
 E3dCR_ROOTMODEL_ADDED=1,
 E3dCR_ROOTMODEL_REMOVED,
 E3dCR_NODE_SCALE,
 E3dCR_NODE_ROTATE,
 E3dCR_NODE_TRANSLATE,
 E3dCR_BRANCH_SCALE,
 E3dCR_BRANCH_ROTATE,
 E3dCR_BRANCH_TRANSLATE,
 E3dCR_TREE_SCALE,
 E3dCR_TREE_ROTATE,
 E3dCR_TREE_TRANSLATE,
 E3dCR_MATERIAL_ADDED,
 E3dCR_MATERIAL_REMOVED,
 E3dCR_MATERIAL_CHANGED,
 E3dCR_MATERIAL_NAME_CHANGED,
 E3dCR_2DTEXTURE_ADDED,
 E3dCR_2DTEXTURE_REMOVED,
 E3dCR_2DTEXTURE_CHANGED,
 E3dCR_2DTEXTURE_NAME_CHANGED,
 E3dCR_GEOMETRY_CHANGED,
 E3dCR_NODE_SELECTED,
 E3dCR_NODE_UNSELECTED,
 E3dCR_BRANCH_SELECTED,
 E3dCR_BRANCH_UNSELECTED,
 E3dCR_SPLINE_SEGMENT_SELECTED,
 E3dCR_SPLINE_SEGMENT_UNSELECTED,
 E3dCR_HIDE_UNHIDE
};


#define E3dSceneCallbackStructCore()\
 int		Reason



// Generic Scene callback-struct
//
typedef struct
{
 E3dSceneCallbackStructCore();
} E3dSceneCallbackStruct;


// Model-change Scene callback-struct
//
typedef struct
{
 E3dSceneCallbackStructCore();

 unsigned int	NumOfModels;
 E3dModel**	Models;
 void*		Value;
} E3dSceneModelsCallbackStruct;


// Model-change Scene callback-struct
//
typedef struct
{
 E3dSceneCallbackStructCore();

 E3dGeometry*	Geometry;
 int		SubGeoIndex;
} E3dSceneGeometryCallbackStruct;


// Material-change Scene callback-struct
//
typedef struct
{
 E3dSceneCallbackStructCore();

 E3dMaterial**	Materials;
 unsigned int	NumOfMaterials;
} E3dSceneMaterialsCallbackStruct;


// Scene callback types
//
#define E3dCALLBACK_SELECT		0x01
#define E3dCALLBACK_ADDREMOVE		0x02
#define E3dCALLBACK_GENERAL		0x04

#ifndef _E3dScene
#define _E3dScene
typedef struct E3dScene_S	E3dScene;
#endif


struct E3dScene_S
{
 char*			Name;

 E3dRenderInfo		RenderInfo;
 E3dModel**		RootModels;
 unsigned int		NumOfRootModels, NumOfRootModelsAllocated;
 E3dMaterial**		Materials;
 unsigned int		NumOfMaterials, NumOfMaterialsAllocated;

 unsigned int		NumOf2DTextures, NumOf2DTexturesAllocated;
 E3d2DTexture**		Textures2D;

 E3dLight**		Lights;
 unsigned int		NumOfLights, NumOfLightsAllocated;

 unsigned int		NumOfCallbacks;
 E3dCallbackRec*	Callbacks;

 unsigned int		NumOfSelectCallbacks;
 E3dCallbackRec*	SelectCallbacks;

 unsigned int		NumOfAddRemoveCallbacks;	// These get called when a Model is added or removed
 E3dCallbackRec*	AddRemoveCallbacks;


// For rendering
//
 E3dPolyGroup**		RenderPolyGroups;		// PolyGroups prepared for rendering
 unsigned int		NumOfRenderPolyGroups;

// For ray-coherence speedup
//
 E3dRTriangle*		ShadowRayLastHit;
 E3dRTriangle*		TestRayLastHit;

 E3dVoxel*		Voxels;				// Uniform-grid subdivision for rendering
 E3dCoordinate		VoxelXSize, VoxelYSize, VoxelZSize,
			VoxelXSizeInv, VoxelYSizeInv, VoxelZSizeInv;
 int			RayCounter;

// The application can only change these in RenderInfo, not here!
//
 int			GridXCount, GridYCount, GridZCount;

 E3d3DPosition		BBoxMin, BBoxMax;

#ifdef USEOpenGL
 E3dGLLight		GLLights[GL_MAX_LIGHTS];
#endif // USEOpenGL

// For animation
//
 double			Frame, Time;
 E3dAnimation**		Animations;
 unsigned int		NumOfAnimations, NumOfAnimationsAllocated;
 unsigned int		Changed;			// For animation. SetFrameProcs must set these flags
};



/*--------------------------------------------------------------*/
/* Global variables						*/
/*--------------------------------------------------------------*/
extern E3dScene*	E3d_Scene;

extern EBool		E3d_Verbose;

extern unsigned int	E3d_MatOffsetModels;	

extern E3d2DTexture*	E3d_Current2DGLTexture;

extern E3dMatrix	E3d_IdentityMatrix;


#ifdef USEOpenGL
extern EBool		E3d_GLDataTransformed;
#endif // USEOpenGL


/*--------------------------------------------------------------*/
/* Function prototypes						*/
/*--------------------------------------------------------------*/
extern EBool		E3d_SceneGetModelIndices(E3dScene* LScene, E3dModel* LModel, int* LRootModelIndexRet, int* LNodeIndexRet);
extern void		E3d_SceneDefault(E3dScene* LScene);
extern E3dScene*	E3d_SceneAllocate(char* LName);
extern void		E3d_SceneFree(E3dScene* LScene);


extern void		E3d_SceneAppendLight(E3dScene* LScene, E3dLight* LLight);
extern E3dLight*	E3d_SceneCreateAndAddLight(E3dScene* LScene, int LType);
extern void		E3d_SceneRemoveLight(E3dScene* LScene, E3dLight* LLight);


extern EBool		E3d_SceneAddModelHrc(E3dScene* LScene, E3dModel* LRootModel);
extern void		E3d_SceneRemoveModelHrc(E3dScene* LScene, E3dModel* LRootModel);

extern EBool		E3d_SceneAddMaterial(E3dScene* LScene, E3dMaterial* LMaterial);
extern int		E3d_SceneAddMaterials(E3dScene* LScene, E3dMaterial** LMaterials, unsigned int LCount);
extern int		E3d_SceneAddMaterialsFromModelHrc(E3dScene* LScene, E3dModel* LRootModel);
extern EBool		E3d_SceneRemoveMaterial(E3dScene* LScene, E3dMaterial* LMaterial);
extern int		E3d_SceneRemoveMaterials(E3dScene* LScene, E3dMaterial** LMaterials, unsigned int LCount);

extern E3dMaterial*	E3d_SceneMaterialClone(E3dScene* LScene, E3dMaterial* LMaterial);


extern EBool		E3d_SceneAdd2DTexture(E3dScene* LScene, E3d2DTexture* L2DTexture);
extern int		E3d_SceneAdd2DTextures(E3dScene* LScene, E3d2DTexture** L2DTextures, unsigned int LCount);
extern EBool		E3d_SceneRemove2DTexture(E3dScene* LScene, E3d2DTexture* L2DTexture);
extern int		E3d_SceneRemove2DTextures(E3dScene* LScene, E3d2DTexture** L2DTextures, unsigned int LCount);

extern EBool		E3d_Scene2DTextureUpdateImageForDisplay(E3dScene* LScene, E3d2DTexture* L2DTexture);

extern EBool		E3d_Scene2DTextureReadImage(E3dScene* LScene, E3d2DTexture* L2DTexture, char* LPath, EBool LForceReRead, EBool LSetUpForDisplay);
extern void		E3d_SceneModelHrcRead2DTextures(E3dScene* LScene, E3dModel* LModel, char* LPath, EBool LForceReRead, EBool LSetUpForDisplay);



extern void		E3d_3DInit(void);
extern void		E3d_Free();
extern void		E3d_ClearScene(E3dScene* LScene);
extern void		E3d_SceneRefreshLights(E3dScene* LScene, E3dMatrix LCameraTransMatrix);

#ifdef USEOpenGL
extern void		E3d_SceneRemoveGLDisplayLists();
extern void		E3d_SceneLightsRefreshGL(E3dScene* LScene);
extern void		E3d_SceneLightsDefineGL(E3dScene* LScene);
#endif // USEOpenGL



extern int		E3d_SceneGetSelectedGeometries(E3dScene* LScene, E3dGeometry*** LGeometriesRet, int LGeoType);
extern int		E3d_SceneGetSelectedModels(E3dScene* LScene, E3dModel*** LModelsRet, EBool LBranchesAsOne);

extern int		E3d_SceneGetSingleSelection(E3dScene* LScene, E3dItem* LSelectedItem, int LTarget);
extern void		E3d_SceneUnSelectAll(E3dScene* LScene, int LFlags);

extern void		E3d_SceneAddCallback(E3dScene* LScene, unsigned int LCallbackType, E3dCallbackProc LCallbackProc, EPointer LClientData);
extern void		E3d_SceneRemoveCallback(E3dScene* LScene, unsigned int LCallbackType, E3dCallbackProc LCallbackProc, EPointer LClientData);

extern void		E3d_SceneWalkModels(E3dScene* LScene, void (*LFunct)(E3dModel*));
extern void		E3d_SceneWalkGeometries(E3dScene* LScene, void (*LFunct)(E3dModel*, E3dGeometry*));


extern E3dShapeSnapshot*	E3d_SceneTaggedPointsToTransformPoints(E3dScene* LScene, unsigned int* LNumOfShapeSnapshotsRet);

extern int		E3d_SceneCollectModelNames(E3dScene* LScene, char*** LNamesRet);


extern EBool		E3d_SceneAppendAnimation(E3dScene* LScene, E3dAnimation* LAnimation);
extern E3dAnimation*	E3d_SceneAddAnimation(E3dScene* LScene, E3dAnimationClass* LClass);
extern void		E3d_SceneRemoveAnimation(E3dScene* LScene, E3dAnimation* LAnimation);



/*--------------------------------------*/
/* From Rendering.c			*/
/*--------------------------------------*/
extern unsigned int	E3d_SceneGetRenderTriangles(E3dScene* LScene, E3dRenderInfo* LRenderInfo, E3dCamera* LCamera);
extern EBool		E3d_SceneFreeRenderTriangles(E3dScene* LScene);
extern E3dVoxel*	E3d_SceneVoxelize(E3dScene* LScene);
extern EBool		E3d_SceneFreeVoxels(E3dScene* LScene);
extern void		E3d_SceneResetRayCounters(E3dScene* LScene);


extern EBool		E3d_SceneGetRenderBoundingBox(E3dScene* LScene);

/*--------------------------------------*/
/* From Scene.c				*/
/*--------------------------------------*/
extern void		E3d_ShapeSnapshotsFree(E3dShapeSnapshot* LShapeSnapshots, unsigned int LNumOfShapeSnapshots);


/*--------------------------------------*/
/* From Panel/Undo.c			*/
/*--------------------------------------*/
extern void		E3d_SceneFreeUndoStack(E3dScene* LScene);
extern void		E3d_SceneAddOps(E3dScene* LScene, EOps* LOps, EBool LDuplicate);
extern void		E3d_SceneAddOps1Operator(E3dScene* LScene, EOperator* LOperator, int LSize, EBool LDuplicate);

extern void		E3d_SceneUndo(E3dScene* LScene);
extern void		E3d_SceneRedo(E3dScene* LScene);

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration which encloses file.
#endif

#endif	// _E3DScene_h
