//========================================================================
// E3D library
//
// - 3D (file, network etc.) I/O
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Aug-06 18:17:07
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//========================================================================
#ifndef	_E3D_IO_h
#define	_E3D_IO_h

#include <float.h>

#ifndef _E3D_Scene_h
#include <E3D/Scene.h>
#endif


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


#define E3dFileFormatNONE            NULL
#define E3dFileFormatFROM_EXTENSION  NULL  // Get format from filename extension
#define E3dFileFormatAUTOMATIC       NULL  // Automatic format recognition (for reading)

// Filter types
//
#define	E3dDataTypeNONE               0
#define E3dDataTypeMODEL              1
#define E3dDataTypeHIERARCHY         (1<<1)
#define E3dDataTypeSCENE             (1<<2)
#define E3dDataTypeMODEL_ANIMATION   (1<<3)
#define E3dDataTypeVERTEX_ANIMATION  (1<<4)
#define E3dDataTypeMATERIAL          (1<<5)
#define E3dDataTypeLIGHT             (1<<6)


typedef struct E3dIOModule_S   E3dIOModule;
typedef struct E3dIOModule_S*  E3dIOModulePtr;
EList_t(E3dIOModulePtr);

typedef struct
{
	EFileCore;                                // Inherited from EFile

	E3dScene*     AppActiveScene;    // May be used by IO modules to check for resident Animations etc.

// This allows Scene readers to overwrite (turn off) the DeleteAllBeforeReadingScene flag,
// as some file formats support multiple hierarchies, but no Lights, Cameras etc.
	uint32_t      ClearSceneBefore : 1,

// Read UI setup etc. If FALSE, only read 3D assets
	              ReadSession : 1;

	uint8_t       DataType;          // E3dBINARY or E3dASCII
} E3dFile;

typedef int    (*E3dLoadFunc)(E3dFile* P3DFile, void** PObjectRet);
typedef int    (*E3dSaveFunc)(E3dFile* P3DFile, const uint8_t PType);

typedef int    (*E3dNodeLoadFunc)(E3dFile* P3DFile, E3dNode** PONodeRet);
typedef int    (*E3dNodeSaveFunc)(E3dFile* P3DFile, E3dNode*, const uint8_t PType);

typedef int    (*E3dSceneLoadFunc)(E3dFile* P3DFile, E3dScene** PSceneRet);
typedef int    (*E3dSceneSaveFunc)(E3dFile* P3DFile, E3dScene*, const uint8_t PType);

// This way, we don't have to include Xe/Xe.h. XeWidget is an opaque type for lower-level modules anyway.
#ifndef XeWidget_DEF
typedef struct _XeWidget_S*  XeWidget;
#endif

#define E3dIOModuleCore\
	EIOModuleCore;  /* Inherited from EIOModule */\
\
	uint32_t      DataTypes;           /* E3dDataTypeMODEL, E3dDataTypeSCENE etc...    */\
	E3dLoadFunc   Load;                /* Function to load 3D data                     */\
	E3dSaveFunc   Save;                /* Function to save 3D data                     */\
	void          (*GUIForLoad)(E3dIOModule* PIOModule, XeWidget PParentW, const uint16_t PAction);\
	void          (*GUIForSave)(E3dIOModule* PIOModule, XeWidget PParentW, const uint16_t PAction)

struct E3dIOModule_S
{
	E3dIOModuleCore;
};

EList_s(extern, E3dIOModulePtr, E3d_3DModelFileFormats);
EList_s(extern, E3dIOModulePtr, E3d_3DHierarchyFileFormats);
EList_s(extern, E3dIOModulePtr, E3d_3DSceneFileFormats);

extern EpImage*  _Image_File3D;  // Default 3D file icon for XeFileSelectionBox

extern int            E3d_3DIOReadStatus;

extern E3dIOModule*   E3dIOModule_ByFileNameExtension(const char* PExtension,  E3dIOModulePtrList* PFormats,  const uint32_t PFlags);

extern const char*    E3d_GetBaseFileName(const char* PFileName, char* PNameRet, const int PMaxLen);


extern void*      E3d_3DModelIOModuleAdd(E3dIOModule* PTemplate);
extern void       E3d_3DModelIOModuleRemove(void* PFileFormat);
extern void       E3d_3DModelIOModuleDeactivate(void* PFileFormat);

extern void*      E3d_3DHierarchyIOModuleAdd(E3dIOModule* PTemplate);
extern void       E3d_3DHierarchyIOModuleRemove(void* PFileFormat);
extern void       E3d_3DHierarchyIOModuleDeactivate(void* PFileFormat);

extern void*      E3d_3DSceneIOModuleAdd(E3dIOModule* PTemplate);
extern void       E3d_3DSceneIOModuleRemove(void* PFileFormat);
extern void       E3d_3DSceneIOModuleDeactivate(void* PFileFormat);

extern void       E3dIOModules_Free(void);


extern int       E3dNode_LoadFromFile(const char* PFileName, E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet,  E3dScene* PAppScene,  E3dNode** PNode);

extern int       E3dNode_SaveToFile(const char* PFileName, char* PNameReturn, const int PNameMaxLen,  E3dScene* PAppScene, E3dNode* PNode,
                  E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet);

extern int       E3dNodeHrc_LoadFromFile(const char* PFileName, E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet, E3dNode** PNodePtr);
extern int       E3dNodeHrc_LoadFromMemory(const uint8_t* PBuffer, EIndex PBufferSize, E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet, E3dNode** PNodePtr);

extern int       E3dNodeHrc_SaveToFile(const char* PFileName, char* PNameReturn, int PNameMaxLen,  E3dScene* PScene, E3dNode* PNode,
                  E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet);

extern int       E3dScene_LoadFromFile(const char* PFileName, E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet,  E3dScene* PAppActiveScene, E3dScene** PScene,
                  EBool* PClearSceneBeforeP, const EBool PReadSession);

extern int       E3dScene_SaveToFile(const char* PFileName, char* PNameReturn, int PNameMaxLen, E3dScene* PModel, E3dIOModule* PFileFormat, E3dIOModule** PFileFormatRet);

extern E3dGeometry*  E3dIcon_LoadGeometry(const char* PFileName,  const uint8_t* PBuffer, const EIndex PBufferSize,  E3dIOModule* PFileFormat);
extern E3dNode*      E3dIcon_LoadNode(const char* PFileName);

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


#endif	// _E3D_IO_h
