//================================================================
// E3D library
//
// Scene management
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Jun-08 00:48:34
//
// Copyright (C) 1996-2026 By Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_Scene_h
#define _E3D_Scene_h


#ifndef _ELists_h
#include <ELists.h>
#endif

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

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

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

#ifndef _E3D_Ray_h
#include <E3D/Ray.h>
#endif

#ifndef _E3D_Shape_h
#include <E3D/Shape.h>
#endif


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

#define E3dSELECTED                 0x01
#define E3dUNSELECTED               0x02
#define E3dVISIBLE                  0x04
#define E3dHIDDEN                   0x08
#define E3dEXCLUDE_MODEL_SELECTION  0x10  // For E3dScene_GetObjects(). Don't consider an Object selected if one of its referencing Nodes is selected, but the Object itself is not


// How to add a newly created Object to the Scene
//
enum
{
	E3dNEW_INSTANCE = 1,  // Just add new Object to Model
	E3dNEW_MODEL,         // Add new Model with Object and add it to parent of Model
	E3dNEW_HRC            // Add new Model with Object and add it to Scene after root of Model
};



// Node-change Scene callback-struct
// Callback Reasons : E3dCR_NODE_*
//
typedef struct
{
	ECallbackStructCore;

	E3dNode**  Nodes;EIndex  NumOfNodes;
	void*      Value;
} E3dSceneNodesCallbackStruct;


// Object-change Scene callback-struct
// Callback Reasons : E3dCR_GEOMETRY_CHANGED, E3dCR_POLYGON_SELECTION, E3dCR_POINTS_SELECTION, E3dCR_EDGE_SELECTION, 3dCR_SPLINE_SEGMENT_SELECTED
//
typedef struct
{
	ECallbackStructCore;

	E3dObject*  Object;
	EObject*    SubObject;  // E.g a PolyGroup when Object is a Mesh

	EIndex      ContourIndex, PointIndex;
} E3dSceneObjectCallbackStruct;


// Material-change Scene callback-struct
// Callback Reasons : E3dCR_MATERIAL_ADDED, E3dCR_MATERIAL_REMOVED, E3dCR_MATERIAL_CHANGED, E3dCR_MATERIAL_NAME_CHANGED
typedef struct
{
	ECallbackStructCore;

	E3dMaterial**  Materials;EIndex  NumOfMaterials;
} E3dSceneMaterialsCallbackStruct;


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


typedef struct
{
	E3dMaterial*  Material;
	EListA_s(, EObjectPtr, Shadeables);
} E3dMaterialAndShadeable, *E3dMaterialAndShadeablePtr;
EListA_t(E3dMaterialAndShadeable);
EListA_t(E3dMaterialAndShadeablePtr);

typedef struct
{
	EObjectCore(EObject);
	EBool  Active;
} E3dLayer, *E3dLayerPtr;
EListA_t(E3dLayerPtr);


struct E3dScene_S
{
	char*  Name;
	char*  URL;

	EListA_s(, E3dNodePtr, RootNodes);
	EListA(, E3dMaterial*,  Materials);
	EListA(, E3d2DTexture*, Textures);

	EList(, ECallbackRec, Callbacks);

// For Matrix-stack operations
//
	int            MatrixPtr, MatrixScalePtr;

	E3dCoord3      CurrentScale;
	E3dCoord3      ScaleStack[E3dMAX_HIERARCHY_DEPTH];
	E3dMatrix      MatrixStack[E3dMAX_HIERARCHY_DEPTH];


// For animation
//
	EListA_s(, E3dAnimStackPtr, AnimStacks);
	E3dAnimStack*  CurrentAnimStack;

	EListA_s(, E3dAnimationPtr, GlobalAnimations);  // Animations that are not specific to a certain AnimStack. E.g. rigid body physics

// Change-tracking for animation
//
	E3dChangeList  ChangeList;
};


typedef EChangeFlags (*E3dSceneFunction)(E3dScene* PScene);

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

extern E3dMatrix  E3d_IdentityMatrix;


//----------------------------------------------------------------
// Rendering/Rendering.c
//----------------------------------------------------------------
// 3D Icons
//
extern E3dMesh*    E3d_3DCrossMesh;
extern E3dObject*  E3d_ManipulatorRot;
extern E3dObject*  E3d_ManipulatorTrn;


//----------------------------------------------------------------
// Scene.c
//----------------------------------------------------------------
extern EBool        E3d_Exiting;

extern ECoreClass   E3dSceneNodesCallbackStruct_class[];
extern ECoreClass   E3dSceneObjectCallbackStruct_class[];
extern ECoreClass   E3dSceneMaterialsCallbackStruct_class[];

extern const void*  E3d_Classes[];extern const int  E3d_Classes_Count;
extern const        EObjectClass  E3dLayer_class[];


extern EIndex       E3dScene_CollectClassesAndObjects(E3dScene* PScene,  E3dNode** PNodeBranches, const EIndex PNNodeBranches,
                     EResContext* PContext, const uint16_t PAddToAllObjects,  E3dObjectPtrListA* PObjects);

extern ECoreClass*  E3d_ClassByName(const char* PClassName);

EListA_s(extern, E3dLayerPtr, E3d_Layers);

extern void         E3dScene_Init(E3dScene* PScene);
extern E3dScene*    E3dScene_New(const char* PName);
extern void         E3dScene_Free(E3dScene* PScene);

extern EBool        E3dScene_HasSelectedAnimationChannel(const E3dScene* PScene);

extern char*        E3dScene_GetUniqueNodeName(E3dScene* PScene, const char* PBaseName);
extern char*        E3dScene_GetUniqueObjectName(E3dScene* PScene, const char* PBaseName);

extern E3dLight*    E3dScene_LightAdd(E3dScene* PScene, int PType);

extern EBool         E3dScene_NodeHrcAdd(E3dScene* PScene, E3dNode* PRootNode, const EUpdateFlags PNotifyFlags);
extern EBool         E3dScene_NodeHrcInsert(E3dScene* PScene, E3dNode* PRootNode, const EIndex PHere, const EBool PNotify);
extern EBool         E3dScene_NodeHrcRemove(E3dScene* PScene, E3dNode* PRootNode, EChangeFlags* PChangedRet, const EBool PNotify);
 
extern EBool         E3dScene_MaterialAdd(E3dScene* PScene, E3dMaterial* PMaterial);
extern EIndex        E3dScene_MaterialsAdd(E3dScene* PScene, E3dMaterial** PMaterials, const EIndex PCount);

extern EIndex        E3dScene_MaterialsAddFromObject(E3dScene* PScene, E3dObject* PObject);
extern EIndex        E3dScene_MaterialsAddFromNodeHrc(E3dScene* PScene, E3dNode* PRootNode);
extern EBool         E3dScene_MaterialRemove(E3dScene* PScene, E3dMaterial* PMaterial);
extern EIndex        E3dScene_MaterialsRemove(E3dScene* PScene, E3dMaterial** PMaterials, const EIndex PCount);

extern E3dMaterial*  E3dScene_MaterialCopy(E3dScene* PScene, const E3dRenderer* PRenderer, const E3dMaterial* PMaterial, const EBool PCopyCaches);

extern EIndex        E3dScene_MaterialCollectShadeables(E3dScene* PScene, const E3dMaterial* PMaterial,  EObjectPtrListA* PShadeables);
extern EIndex        E3dScene_CollectMaterialsAndShadeables(E3dScene* PScene, E3dMaterialAndShadeableListA* PList);

extern EBool         E3dScene_TextureAdd(E3dScene* PScene, E3d2DTexture* PTexture);
extern EBool         E3dScene_TextureRemove(E3dScene* PScene, E3d2DTexture* PTexture);

extern int           E3dScene_TextureCollectShadeableRecs(E3dScene* PScene, E3d2DTexture* PTexture, E3dShadeableRecPtrListA* PShadeableRecs);

extern int           E3dScene_ImageLoad(E3dScene* PScene, const char* PPath,  E3dImage** PImageRet);
extern int           E3dScene_TextureImageLoad(E3dScene* PScene, E3d2DTexture* PTexture, const char* PPath,  const double PFrame,  EBool PForceReRead,  E3dImage** PImageRet);

extern EBool         E3dScene_NodeHrcHasTextures(const E3dNode* PRootNode);
extern EIndex        E3dScene_NodeHrcReadTextures(E3dScene* PScene, E3dNode* PNode, const char* PPath, const double PFrame);

extern void          E3dMaterial_UpdateTextureImages(E3dScene* PScene, E3dMaterial* PMaterial, const char* PPath, const double PFrame);

extern EChangeFlags  E3dObject_UpdateForDisplay(E3dObject* PObject,  const EUpdateFlags PUpdateFlags, ECallFlags PCallFlags,  E3dScene* PScene);

extern E3dObject*    E3dObject_CustomNew(E3dScene* PScene, E3dNode* PParent, E3dModel* POrigModel, const char* PNewModelName, E3dObjectComponent* PInfo, const uint16_t PAddMode,
                      const EBool PCreateUniqueName,  E3dModel** PNewModelP);

extern E3dObject*    E3dObject_CustomNewInit(E3dScene* PScene, void* PComponentTemplate, const EBool PCreateUniqueName);

extern E3dModel*     E3dModel_CustomNew(E3dScene* PScene, E3dNodeComponentClass* PClass, E3dNodeComponent* PComponentTemplate, const EBool PCreateUniqueName);
extern E3dModel*     E3dModel_CustomObjectNewInit(E3dScene* PScene, void* PComponentTemplate, E3dObject** PObjectRet, const char* PName, const EBool PCreateUniqueName);
extern E3dModel*     E3dModel_CustomObjectNew(E3dScene* PScene, E3dObjectComponentClass* PClass, E3dObject** PObjectRet, const EBool PCreateUniqueName);


extern int               E3dScriptFunction_Register(const char* PName, const char* PUIName, const char* PToolTip,  EScriptFunctionFunc PFunc, EResourceList* PParams,
                          EScriptFunction** PFuncStruct);

extern int               E3dScriptFunction_Remove(EScriptFunction* PFuncStruct);
extern EScriptFunction*  E3dScriptFunction_ByName(const char* PName);


extern EChangeFlags  E3dSpline_Changed(E3dSpline* PSpline, const EChangeFlags PChangeFlags,  EOpNodeListA* POpNodes);


extern void          E3d_Init(void);
extern void          E3d_Free(void);
extern void          E3dScene_Clear(E3dScene* PScene, const EBool PAll, const EBool PRemoveResidentAnims);
extern void          E3dScene_InvalidateShadowCaches(E3dScene* PScene);
extern void          E3dScene_RefreshLights(E3dScene* PScene, E3dRenderer* PRenderer);

extern void          E3dLayers_Free(E3dLayerPtrListA* PLayers);
extern void          (*E3dLayers_SetFromScene)(E3dScene* PScene, E3dLayerPtrListA* PLayers,  const uint8_t PAction,  const EIndex* PValues, const EIndex PIndex);

extern EBool         E3d_IsObject(ECoreObject* PObject);
extern EBool         E3dObject_TypePass(const ECoreObject* PObject, const uint32_t PObjectTypeFlags);

extern EChangeFlags  E3dScene_FromLayers(const E3dLayerPtrListA* PLayers, E3dScene* PScene);


extern EIndex        E3dScene_GetAnimatedObjects(E3dScene* PScene, const uint32_t PObjectTypeFlags, E3dAnimatedObject** PListRet);
extern void          E3d_AnimatedObjectsFree(E3dAnimatedObject* PAO, const EIndex PNAO);

extern EIndex        E3dSpline_CVInsertBetween(E3dSpline* PSpline, E3dMatrix PWorldToLocalMatrix,  E3dCoord3* P3Position, E3dRay* PRay, E3dSplineCV* PCV);

extern EIndex        E3dScene_ObjectAnimations(const E3dScene* PScene, ECoreObject* PObject, const E3dAnimationClass* PAnimationClass,  E3dAnimation*** PAnimations);


//--------------------------------
// NodeHrc.c
//--------------------------------
extern E3dNode*      E3dNodeHrc_BranchCopy(E3dScene* PScene, E3dNode* PRootNode, const EFlags PCopyFlags, const EBool PInstance, const uint32_t PObjectTypeFlags,
                      const EBool PVisibleOnly, const EBool PUpdate);

extern EChangeFlags  E3dNodeHrc_CloneInfo(E3dScene* PScene, E3dNode* PRootNode, E3dNode* PNewRootNode, const EFlags PFlags);



//--------------------------------
// Surface.c
//--------------------------------
typedef struct
{
	E3dObject*          Object;
	E3dModel*           Model;

	EBool               Active;
	E3dCoordinate       MinDistance;
} E3dSnapToSurface;


extern void  E3dSnapToSurface_Init(E3dSnapToSurface* PThis);
extern void  E3dSnapToSurface_CopyContents(const E3dSnapToSurface* PSrc, E3dSnapToSurface* PDst);
extern void  E3dSnapToSurface_FreeContents(E3dSnapToSurface* PThis);
extern void  E3dSnapToSurface_SnapPoints(E3dSnapToSurface* PSnap, const E3dModel* PPathModel, const E3dMatrix PWorldToLocalMatrix, const EIndex PUPoints,
              const uint8_t PNormalSource, const E3dCoord3* PNormal,  const E3dCoord3* PPositions, const E3dCoord3* PTangents, const EBool PPathClosed,
              E3dCoordinate** PMatricesP, EIndex* PMatrices_CountAllocatedP);




//--------------------------------
// GeometryAdv.c
//--------------------------------
extern E3dMaterial*  E3dGeometry_GetMaterial(const E3dGeometry* PGeometry, const EBool PSelectedSubGeo);

//--------------------------------
// Model.c
//--------------------------------
extern E3dModel*  E3d_VectorTest(E3dModel* PModel, E3dGeometry* PGeometry, E3dGeometry** PGeometryRet,  const E3dCoordinate PX1, const E3dCoordinate PY1, const E3dCoordinate PZ1,
                   const E3dCoordinate PX2, const E3dCoordinate PY2, const E3dCoordinate PZ2,  const EBool PCreateArrow);


//----------------------------------------
// Adv/SceneAdv.c
//----------------------------------------
extern void  E3dNode_BranchUpdateCameras(E3dScene* PScene, E3dNode* PBranchRootNode);


//----------------------------------------
// GL/Texture.c
//----------------------------------------
extern EBool    E3dScene_TextureUpdateGLImage(E3dScene* PScene, E3d2DTexture* PTexture, const E3dTextureMapper* PMapper);


extern EIndex         E3dScene_GetObjects(E3dScene* PScene, const uint32_t PObjectTypeFlags, const E3dItemFlags PFlags, const EBool PAddReferences,  E3dObjectPtrListA* PObjects);

extern EIndex         E3dScene_GetInstances(E3dScene* PScene, const uint32_t PObjectTypeFlags, const E3dItemFlags PFlags, const EBool PAddReferences,
                       E3dInstancePtrListA* PInstances);

extern E3dNode*       E3dScene_NodeByName(E3dScene* PScene, const char* PName);
extern E3dNode*       E3dScene_NodeByComponentClass(E3dScene* PScene, const E3dNodeComponentClass* PClass);

extern E3dObject*     E3dScene_ObjectByName(E3dScene* PScene, const char* PName);

extern E3dMaterial*   E3dScene_MaterialByName(E3dScene* PScene, const char* PName);


extern EIndex         E3dScene_GetSelectedNodes(E3dScene* PScene, const uint32_t PSelectionTypes, const EBool PAddReferences,  E3dNodePtrListA* PNodeList);
extern EIndex         E3dScene_GetNodes(E3dScene* PScene, const EBool PAddReferences,  E3dNodePtrListA* PNodes);

extern int            E3dScene_GetSingleSelection(E3dScene* PScene, void* PSelectedItem, const int PTarget, const E3dItemFlags PFlags);
extern EChangeFlags   E3dScene_UnselectAll(E3dScene* PScene, const uint32_t PFlags, const EBool PNotify);
extern EBool          E3dScene_UnhighlightAll(E3dScene* PScene, const uint32_t PFlags);

extern void           E3dScene_CallbackAdd(E3dScene* PScene, const EChangeFlags PEventMask, ECallbackFunc PFunc, EPointer PClientData);
extern EIndex         E3dScene_CallbackRemove(E3dScene* PScene,  ECallbackFunc PFunc, EPointer PClientData);

extern void           E3dScene_WalkNodes(E3dScene* PScene, void (*PFunct)(E3dNode*, EPointer), EPointer PClientData);
extern void           E3dScene_WalkObjects(E3dScene* PScene, void (*PFunct)(E3dModel*, E3dObject*, EPointer), EPointer PClientData);


extern E3dShapeSnapshot**  E3dScene_CollectTransformPoints(E3dScene* PScene, EIndex* PNumOfShapeSnapshotsRet, const EBool PAllPoints, const EBool PVisibleOnly);

extern int            E3dScene_CollectNodeNames(E3dScene* PScene, char*** PNamesRet);

extern EIndex         E3dScene_AnimStackAppend(E3dScene* PScene, E3dAnimStack* PAnimStack);
extern void           E3dScene_AnimStackRemove(E3dScene* PScene, E3dAnimStack* PAnimStack);

extern void           E3dScene_AddDefaultAnimStack(E3dScene* PScene);

extern void           E3dScene_GlobalAnimationAppend(E3dScene* PScene, E3dAnimation* PAnimation);
extern E3dAnimation*  E3dScene_GlobalAnimationAdd(E3dScene* PScene, E3dAnimationClass* PClass, const EBool PSingle);
extern EBool          E3dScene_GlobalAnimationRemove(E3dScene* PScene, E3dAnimation* PAnimation, const EBool PRemoveResidentAnim);
extern E3dAnimation*  E3dScene_GlobalAnimationByClass(E3dScene* PScene, E3dAnimationClass* PClass);

extern void           E3dScene_AnimationAppend(E3dScene* PScene, E3dAnimation* PAnimation);
extern E3dAnimation*  E3dScene_AnimationAdd(E3dScene* PScene, E3dAnimationClass* PClass);

extern E3dKeyFrameAnimation*  E3dScene_KeyFrameAnimationAdd(E3dScene* PScene, ECoreObject* PTargetObject, const char* PAnimName,
                               const EResource* PTargetMember0, const EIndex PTargetMember0Index);

extern EBool          E3dScene_AnimationRemove(E3dScene* PScene, E3dAnimation* PAnimation, const EBool PRemoveResidentAnim);

extern void           E3dScene_ObjectsUpdateModelList(E3dScene* PScene);

extern void           E3dGL_MatrixPush(E3dScene* PScene);
extern void           E3dGL_MatrixPop(E3dScene* PScene);


typedef struct
{
	EBool       Active;
	E3dSpline*  OrigSpline;
	E3dModel*   Model;
} E3dScalingBySpline;


//--------------------------------
// Panel/View_Schematics.c
//--------------------------------
extern void    E3dNodeHrc_RefresSchemPositions(E3dModel* PRootModel);
extern int     E3dScene_LayoutOnSchematics(E3dScene* PScene, const EBool PAutoFrameSchematicsViews);


//----------------------------------------
// Visual debugging
//----------------------------------------
//----------------------------------------
// Panel/Panel.c
//----------------------------------------
extern void          E3dBBox_VisualizeWithMeshEdges(const E3dBBox* PBBox, E3dMesh* PMesh, const char* PModelName);

extern void          E3d_VisualizeVectorsWithMeshEdges(const E3dCoord3* PSamples, const EIndex PNumOfSphereSamples, const char* PModelName);
extern void          E3d_VisualizeRaysWithMeshEdges(const E3dRay* PSamples, const EIndex PCount, const char* PModelName, const E3dCoordinate PLength);
extern E3dPointSet*  E3d_VisualizePointsWithPointSet(const E3dCoord3* PSamples, const EIndex PCount, const char* PModelName);
extern void          E3d_VisualizeColorPointsWithPointSet(E3dScene* PScene, E3dVertex* PPoints, const EIndex PCount, const char* PModelName);


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

#endif	// _E3D_Scene_h
