//========================================================================
// E3D library
//
// Support for undoable adding/deleting of Objects and Object components
// (Mesh PolyGroups, Polygons, Edges, Vertices, Face holes etc.)
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Jul-29 17:14:20
//
// Copyright (C) 2014-2026 by Gabor Nagy. All rights reserved.
//========================================================================
#ifndef _E3D_Editing_h
#define _E3D_Editing_h

#ifndef _EUndo_h
#include <EUndo.h>
#endif

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


typedef struct
{
	EIndex    OriginalIndex;
	EObject*  SubObject;  // E.g. Face contour Spline, or Mesh PolyGroup
} E3dOpSubObject;


typedef struct
{
	EIndex              PolygonIndex;  // PolyGroup->Polygons may be reallocated, so we must refer to Polygons by index
	EIndex*             VertexNodesToModify_Indices;uint8_t*  VertexNodesToModify;EIndex  VertexNodesToModify_Count;
	E3dVertexNodeIndex  OrigNumOfExteriorVertices;
} E3dOpPolygon;

typedef struct
{
	EIndex         OriginalIndex;
	E3dPolyGroup*  PolyGroup;

	uint8_t        Operation;                  // Add EEditADD, EEditDEL or EEditMODIFY

	EList(, E3dOpPolygon, PolygonsToModify);
	E3dVertexNodeSize  VertexNodeSize;

	EIndex*      PolygonsToDelete_Indices;     // Indices of Polygons to delete
	EList(, E3dPolygon, PolygonsToDelete);     // Back-up values of Polygons

	EIndex*      PolygonsToAdd_Indices;        // Indices of Polygons to add
	EList(, E3dPolygon, PolygonsToAdd);        // Values of Polygons to be added (e.g. when deleting Edges, these are the new Polygons created by merging the ones sharing a removed Edge)

	EIndex*      EdgeIndicesToDelete_Indices;  // Locations of (Mesh) Edge indices to be deleted
	EList(, EIndex, EdgeIndicesToDelete);      // Back-up values of Edge indices
} E3dOpPolyGroup;


typedef struct
{
	E3dObject*  Object;

	uint8_t     Operation;    // Add EEditADD, EEditDEL or EEditMODIFY

	EList(, EObjectAndIndex*, Models);

	EList(, E3dOpSubObject, SubObjects);
} E3dOpObject;



extern EOperatorClass*  E3dOperatorEditObjects_class;
extern EOperatorClass*  E3dOperatorEditMesh_class;


// Undoable Operator for adding / removing Mesh PolyGroups, Polygons, Edges and Vertices
//
typedef struct
{
	EOperatorCore;

	EList(, E3dOpObject*, Objects);
} E3dOperatorEditObjects;


// Undoable Operator for adding / removing Mesh PolyGroups, Polygons, Edges and Vertices
//
typedef struct
{
	EOperatorCore;

	E3dMesh*    MeshNewT;

	EList(, E3dOpPolyGroup, OpPolyGroups);

	EIndex*     EdgesToDelete_Indices;         // Indices of Edges to delete
	EList(, E3dEdge, EdgesToDelete);           // Values of Edges to be deleted (stored for undo)
	EIndex*     EdgesToAdd_Indices;            // Indices of Edges to ad
	EList(, E3dEdge, EdgesToAdd);              // Values of Edges to be added (stored for redo)

	EIndex*        VerticesToDelete_Indices;     // Indices of Vertices to delete
	uint8_t*       VerticesToDelete;EIndex  VerticesToDelete_Count;     // Values of Vertices to be deleted (stored for undo)
	EIndex*        VerticesToAdd_Indices;        // Indices of Vertices to add
	uint8_t*       VerticesToAdd;EIndex  VerticesToAdd_Count;           // Values of Vertices to be added (stored for redo)
	EResourceList  VertexAttributes;             // Needed for "rich" Vertices
	E3dVertexSize  VertexSize;
} E3dOperatorEditMesh;


// Undoable Operator for adding / removing Mesh Vertices
//
typedef struct
{
	EOperatorCore;

	E3dMesh*  MeshNewT;

	EList(, E3dOpPolyGroup, OpPolyGroups);     // Affected PolyGroups

// Indices of Vertices to delete must be in incremental order!
//
	EIndex*   Vertices_Indices;uint8_t*  Vertices;EIndex  Vertices_Count;
	EResourceList  VertexAttributes;           // Needed for "rich" Vertices
	E3dVertexSize  VertexSize;

	EIndex*   EdgesToDelete_Indices;           // Indices of Edges to delete
	EList(, E3dEdge, EdgesToDelete);           // Values of Edges to be deleted (stored for undo)
	EIndex*   EdgesToAdd_Indices;              // Indices of Edges to add
	EList(, E3dEdge, EdgesToAdd);              // Values of Edges to be added (stored for redo)

	uint16_t   DeleteMeshVertices:1;           // If FALSE, only disconnect Vertices from Polygons. Don't remove them from the Mesh
} E3dOperatorAddDeleteVertices;



static inline E3dOpPolygon* E3dOpPolyGroup_AddPolygon(E3dOpPolyGroup* POpPolyGroup, E3dPolygon* PPolygon)
{
	E3dOpPolygon*  LOpPolygon = EList_StructAdd(POpPolyGroup->PolygonsToModify);if(LOpPolygon)
	{
		LOpPolygon->PolygonIndex = PPolygon - POpPolyGroup->PolyGroup->Polygons.Items;

		LOpPolygon->VertexNodesToModify_Indices = NULL;LOpPolygon->VertexNodesToModify = NULL;LOpPolygon->VertexNodesToModify_Count = 0;
		LOpPolygon->OrigNumOfExteriorVertices = PPolygon->NumOfExteriorVertices;
	}
	return(LOpPolygon);
}

extern EIndex  E3dMesh_RemoveUnusedVertices(EOps* POps, E3dMesh* PMesh);

//------------------------------------------------
// libsrc/E3d/Panel/Editing.c
//------------------------------------------------
extern int         			E3dMesh_SeparatePolyGroups(E3dMesh* PMesh,  const EIndex* PIndices, const EIndex PIndices_Count,  E3dModel* PAddToModel, const EFlags PFlags,
 const EBool PKeepOriginalPolyGroups, const EBool PStoreForUndo, E3dOperatorEditMesh* POperatorEditMesh);

extern void             E3dScene_Delete_All(E3dScene* PScene);

extern E3dOpObject*     E3dEditObjects_AddOpObject(E3dOperatorEditObjects* POperator, E3dObject* PObject);
extern void             E3dEditObjects_OpSubObjectInit(E3dOpSubObject* PSubObject, const EIndex POriginalIndex, EObject* PObject);

extern EChangeFlags     E3d_MeshPolyGroupPolygonsAddDel(EOps* POps, E3dOperatorEditMesh* POperator,  E3dMesh* PMesh, E3dPolyGroup* PPolyGroup,
 EIndex* PPolygonsToDelIndices, const EIndex PPolygonsToDelIndices_Count,  E3dPolygon* PPolygonsToAdd, const EIndex PPolygonsToAdd_Count,  const char* PName);

extern E3dOpPolyGroup*  E3d_EditMeshAddOpPolyGroup(E3dOperatorEditMesh* POperator,  E3dPolyGroup* PPolyGroup, const EIndex POriginalIndex, const uint8_t POperation);
extern E3dOpPolyGroup*  E3d_AddDeleteVerticesAddOpPolyGroup(E3dOperatorAddDeleteVertices* POperator,  E3dPolyGroup* PPolyGroup, const EIndex POriginalIndex);

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

#endif	// _E3D_Editing_h
