//========================================================================================================
// E3D library
//
// Generic "Item" header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2024-Oct-06 01:11:08
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//========================================================================================================
#ifndef _E3D_Item_h
#define _E3D_Item_h

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

#ifndef _E3D_Polygon_h
#include <E3D/Polygon.h>
#endif

#ifndef _E3D_PointSet_h
#include <E3D/PointSet.h>
#endif


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


// Item types
//
#define E3dItemNONE                 0x00000000    // No further detail. E.g. when picking Models only, no Object / Instance index (indices start from 1, so 0 means no data)
#define E3dItemWORLD_POSITION       0x00000001    // No object type in particular, just tell the callback function the 3D position picked in world-space (e.g. for drawing a Spline)
#define E3dItemSURFACE              0x00000002    // Face, Mesh etc. surface, with no more detail (needed when picking Models, Meshes etc. It's much faster to call EpglDrawElements. It would make no sense to draw a Mesh triangle-by triangle and popping/pushing PolyGroup and PolyGroup indices when we are only interested in which Model or Object was picked)
#define E3dItemANIMATION_CURVE      0x00000004
#define E3dItemMATERIAL             0x00000008

#define E3dItemNODE                 0x00000010
#define E3dItemMODEL                0x00000020
#define E3dItemBRANCH               0x00000040
#define E3dItemTREE                 0x00000080

#define E3dItemOBJECT               0x00000100

#define E3dItemLIGHT                0x00000200
#define E3dItemCAMERA               0x00000400

#define E3dItemPOINTSET             0x00000800

#define E3dItemSPLINE               0x00001000
#define E3dItemSPLINE_SEGMENT       0x00002000
#define E3dItemSPLINE_CV            0x00004000
#define E3dItemTANGENT_PREVIOUS     0x00008000
#define E3dItemTANGENT_NEXT         0x00010000

#define E3dItemFACE                 0x00020000
#define E3dItemFACE_CONTOUR         0x00040000    // A Spline that's either the Exterior or a Hole contour of a Face
#define E3dItemFACE_SURFACE         0x00080000

#define E3dItemMESH                 0x00100000
#define E3dItemPOLYGROUP            0x00200000
#define E3dItemPOLYGON              0x00400000
#define E3dItemEDGE                 0x00800000
#define E3dItemVERTEX               0x01000000

#define E3dItemSCHEM_COLLAPSEBUTTON	0x10000000

#define E3dItemPOINT       (E3dItemVERTEX|E3dItemSPLINE_CV)				// Vertex, Spline key etc.
#define E3dItemGEOMETRY    (E3dItemPOINTSET|E3dItemMESH|E3dItemSPLINE|E3dItemFACE)	// Vertex, Spline key etc.
#define E3dItemANYOBJECT   (E3dItemOBJECT|E3dItemLIGHT|E3dItemCAMERA|E3dItemPOINTSET|E3dItemSPLINE|E3dItemFACE|E3dItemMESH)	// Vertex, Spline key etc.

#define E3dItemALL  0xFFFFFFFF



#define E3dItemINDEX_MASK                0x07FFFFFF


#define E3dItemOBJECT_ON_DIFFERENT_NODE	 0x10000000

// This flag is used on Objects in a View's pick method.
// On some Views, like the Schematics View, an Object may be distinctly picked without picking
// a Node, in which case this flag is NOT added to the Object pick index via EpglPushName
//
#define E3dItemPICK_ON_3DVIEW            0x20000000

#define E3dItemCOMPONENT_OBJECT          0x40000000   // When OR-ed to the Node Object/Instance index (within a Model), or to the Sub-geometry (PolyGroup, Spline Segment etc.) index on an Object, the index will indicate a Node or Object ComponentObject index, respectively
#define E3dItemALWAYS_ON_TOP             0x80000000   // Ignore Z. This object is always "on top" (e.g. Skeleton Joints, when DrawOver is set)


#define E3dItemCore\
	unsigned int  Type;\
	unsigned int  InternalType


// Generic structure for picking, selecting caching for modification, undo/redo etc.
//
typedef struct
{
	E3dItemCore;
} E3dAnyItem;


// Material
//
typedef struct
{
	E3dItemCore;

	E3dMaterial*   Material;
	E3dPolyGroup*  PolyGroup;
	EList_s(, E3dTextureMapperPtr, TextureMappers);
} E3dMaterialItem;


typedef unsigned int  E3dPickZ;

//
// A "tangible" object, such as a Geometry
//
#define E3dObjItemCore\
	E3dItemCore;\
\
	E3dNode*    Node;\
	E3dObject*  Object;\
	E3dPickZ    ZNear, ZFar


// Just a Node
//
typedef struct
{
	E3dObjItemCore;
} E3dObjItem;


// Mesh, PolyGroup, Polygon, Vertex etc.
//
typedef struct
{
	E3dObjItemCore;

	E3dPolyGroup*  PolyGroup;       // A PolyGroup in a Mesh
	EIndex         PolygonIndex;    // Index of a Polygon in a PolyGroup

	E3dVertex*     Vertex;
	EIndex         PointIndex;
} E3dPolyItem;


typedef struct
{
	E3dObjItemCore;

	E3dPolyGroup*  PolyGroup;       // A PolyGroup in a Mesh
	EIndex         PolygonIndex;    // Index of a Polygon in a PolyGroup

	EIndex         PointIndex;
	EIndex         VertexAttributeIndex;
	EIndex         MapperIndex;     // TextureMapper index on the PolyGroup.
	EIndex         TextureIndex;    // Texture index on the PolyGroup's Material. Multiple Textures may be using the same Mapper, hence the separation of these two values.
} E3dTexCoordItem;


// Mesh or PolyGroup Edge
//
typedef struct
{
	E3dObjItemCore;

	E3dEdge*       Edge;
	EIndex         EdgeIndex;
} E3dEdgeItem;



#define E3dSplineItemCore\
	E3dObjItemCore;\
\
/* If Object (in E3dObjItemCore) is a Spline, this field will be the same.	*/\
/* If Object is a Face, this will point to a Spline Contour of that Face	*/\
	E3dSpline*  Spline;\
	EIndex      ContourIndex;\
\
	void*       CV;			/* A Spline Control Vertex	*/\
	EIndex      PointIndex



// Spline, Spline segment, Spline CV, Face etc.
//
typedef struct
{
	E3dSplineItemCore;
} E3dSplineItem;


// Animation curve
//
typedef struct
{
	E3dSplineItemCore;

	E3dAnimation*         Animation;
	E3dAnimationChannel*  Channel;
} E3dAnimationCurveItem;



// Generic structure for picking, selecting caching for modification, undo/redo etc.
// These are in a union to have a unified size to reduce memory fragmentation (the union will have the size of the largest member struct)
//
typedef union
{
	E3dAnyItem             Item;
	E3dObjItem             ObjItem;
	E3dPolyItem            PolyItem;
	E3dTexCoordItem        TexCoordItem;
	E3dSplineItem          SplineItem;
	E3dAnimationCurveItem  AnimationCurveItem;
} E3dItem;


extern void          E3dItem_Init(E3dItem* LItem);

extern unsigned int  E3d_ClassToItemID(const ECoreClass* LClass);


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

#endif	// _E3D_Item_h
