//*****************************************************************************
//FileName			: EntityObj.c
//Author			: W. Scott Dillman
//Purpose			: Jet3D Object (DLL) to mark Entity position
//Date Of Creation	: 3/3/2000
//Notes				: Most of this code is a patchwork of functions lifted
//					  from the other Jet3D objects... I only put my name 
//					  here as the one responsible for putting it together.
//					  The code assumes there is a bitmap in the main editor
//					  directory called 'entity.bmp' much like the ambient object.
//Modification History:
//Date             Modifications
//*****************************************************************************

#include <windows.h>

#include <string.h>
#include <float.h>
#include "EntityObj.h"
#include "jeTypes.h"
#include "jeProperty.h"
#include "jeUserPoly.h"
#include "errorlog.h"
#include "jet.h"
#include "ram.h"
#include "memory.h"
#include "assert.h"

#if(0)//Start example

//Here is an example on how to use this object in your code
//to get a start position and actor file name.

jeWorld			*World;
jeXForm3d		XForm;
jeVec3d			Pos;
char			MyActorName[25];

GetEntityPos(World,"EntityObj1",XForm,Pos,MyActorName);

jeBoolean GetEntityActorName(jeObject * pObj,char * ActorName)
{
        jeProperty_List *List;
        HRESULT hResult=FALSE;
        
        if (jeObject_GetPropertyList(pObj, &List) == JE_FALSE)
        {
                return JE_FALSE;
        }
        for (int j = 0; j < List->jePropertyN; j++)
        {
                if(strcmp(List->pjeProperty[j].FieldName,"Actor")==NULL)
                {
                        if(List->pjeProperty[j].Data.String!=NULL)
                                strncpy(ActorName,List->pjeProperty[j].Data.String,64);
                        hResult=TRUE;
                }
        }        
        jeProperty_ListDestroy(&List);
        return hResult;
}

BOOL GetEntityPos(jeWorld *world, char *Name, jeXForm3d &oXForm,jeVec3d &pos,char *m_PlayerName)
{
        jeObject * temp = NULL, *player = NULL;
        
        const char * Object_Name;
        
        temp = jeWorld_FindObjectByDefName(world, "EntityObj");
        player = temp;
        
        if(!temp)
                return FALSE;
        if(!GetEntityActorName(player,m_PlayerName))
                return FALSE;
        
        while(player)
        {
                Object_Name = jeObject_GetName(player);
                
                if(!(strcmp(Object_Name, Name)))
                        break;
                player = jeObject_GetNextChild(temp, player);
                
                if(!player)
                        return FALSE;
        }
        jeObject_GetXForm(player, &oXForm);
        jeVec3d_Copy(&oXForm.Translation, &pos);
        
        return TRUE;
}
#endif//end example



////////////////////// IMPORTANT
// If you change the structure formats, data ids, then bump the version number
//////////////////////

#define ENTITYOBJ_VERSION 1

//Should it be visibile 
#define PROP1_NAME "Display"
#define PROP2_NAME "Actor"

//Royce
#define OBJ_PERSIST_SIZE 5000
//---

enum EntityObjProperties
{ 
	ENTITYOBJ_DISPLAYTOGGLE,
	ENTITYOBJ_NAMELIST = PROPERTY_LOCAL_DATATYPE_START,
};

enum {
	ENTITY_DISPLAYTOGGLE_INDEX,
	ENTITY_NAMELIST_INDEX,
		START_LAST_INDEX
};

#define DEFAULT_RADIUS 1000.0f

static 	jeBitmap	*pBitmap = NULL;

typedef struct EntityObj {
	char			Name[256];
	int				RefCnt;
	jeWorld			*World;
	jeUserPoly		*Poly;
	jeLVertex		Vertex;
	jeVec3d			Pos;
	//Royce-2
	int				DisplayToggle;
	//---
} EntityObj;

jeProperty EntityProperties[START_LAST_INDEX];
jeProperty_List EntityPropertyList = { START_LAST_INDEX, &EntityProperties[0] };

#define MAX_NAMES 1024
char *NameList[MAX_NAMES];
int NameListCount = 0;

#define UTIL_MAX_RESOURCE_LENGTH	(128)
static char stringbuffer[UTIL_MAX_RESOURCE_LENGTH + 1];
static char	*NoSelection = "< none >";

//////////////////////////////////////////////////////////////////////////////
//
//  LOCAL UTILITY
//
//////////////////////////////////////////////////////////////////////////////

static jeBoolean Util_StrDupManagePtr(char **dest, char *src, int min_size)
	{
	int len;

	assert(dest);
	assert(src);

	len = strlen(src)+1;

	if (*dest)
		{
		if ( len < min_size )
			{
			strcpy(*dest, src);
			return JE_TRUE;
			}

		jeRam_Free(*dest);
		*dest = NULL;
		}

	*dest = jeRam_Allocate(__max(min_size, len));
	if (*dest == NULL)
		{
		jeErrorLog_Add( JE_ERR_MEMORY_RESOURCE, NULL );
		return JE_FALSE;
		}

	strcpy(*dest, src);
	return JE_TRUE;
	}

static int Util_GetAppPath(
	char	*Buf,		// where to store path name
	int		BufSize )	// size of buf
{

	// locals
	int	Count;

	// get exe full path name
	Count = GetModuleFileName( NULL, Buf, BufSize );
	if ( Count == 0 )
	{
		return 0;
	}

	// eliminate the exe from the path name
	while ( Count >= 0 )
	{
		if ( Buf[Count] == '\\' )
		{
			break;
		}
		Buf[Count] = '\0';
		Count--;
	}

	// all done
	return Count;

} 

//////////////////////////////////////////////////////////////////////////////
//
//  LOCAL BITMAP RELATED
//
//////////////////////////////////////////////////////////////////////////////

static jeBoolean EntityObject_LoadBmp()
{
	jeVFile	* BmpFile;
	char BitMapPath[255];

	Util_GetAppPath( BitMapPath, 255 );
	strcat( BitMapPath, "Entity.bmp" );

	BmpFile = jeVFile_OpenNewSystem(
		NULL,
		JE_VFILE_TYPE_DOS,
		BitMapPath,
		NULL,
		JE_VFILE_OPEN_READONLY  );
	if( BmpFile == NULL )
		return( JE_FALSE );
	pBitmap = jeBitmap_CreateFromFile( BmpFile );
	jeVFile_Close( BmpFile );
	if( pBitmap == NULL )
		return( JE_FALSE );
	jeBitmap_SetColorKey( pBitmap, JE_TRUE, 255, JE_TRUE );
	return( JE_TRUE );
	
}

static jeBoolean EntityObject_InitIcon( EntityObj * pEntityObj )
{
	assert(pEntityObj != NULL);

	assert(pBitmap);

	pEntityObj->Vertex.r = 255.0f;
	pEntityObj->Vertex.g = 255.0f;
	pEntityObj->Vertex.b = 255.0f;
	pEntityObj->Vertex.a = 255.0f;
	pEntityObj->Vertex.u = 0.0f;
	pEntityObj->Vertex.v = 0.0f;
	pEntityObj->Vertex.sr = 255.0f;
	pEntityObj->Vertex.sg = 255.0f;
	pEntityObj->Vertex.sb = 255.0f;

	pEntityObj->Vertex.X = 0.0f;
	pEntityObj->Vertex.Y = 0.0f;
	pEntityObj->Vertex.Z = 0.0f;

	pEntityObj->Poly = jeUserPoly_CreateSprite(	&pEntityObj->Vertex,
									pBitmap,
									1.0f,
									JE_RENDER_FLAG_ALPHA | JE_RENDER_FLAG_NO_ZWRITE );

	return JE_TRUE;
}				

static jeBoolean EntityObject_UpdateIcon( EntityObj * pEntityObj )
{
	assert(pEntityObj != NULL);

	pEntityObj->Vertex.X = pEntityObj->Pos.X;
	pEntityObj->Vertex.Y = pEntityObj->Pos.Y;
	pEntityObj->Vertex.Z = pEntityObj->Pos.Z;

	//Royce-2
	if (pEntityObj->DisplayToggle)
		jeUserPoly_UpdateSprite(pEntityObj->Poly, &pEntityObj->Vertex, pBitmap, 1.0f);
	//---

	return JE_TRUE;
}				


//////////////////////////////////////////////////////////////////////////////
//
//  PROCESS ATTACH/DETACH
//
//////////////////////////////////////////////////////////////////////////////

void Init_Class( HINSTANCE hInstance )
{
	//Royce-2
	EntityObject_LoadBmp(); //failure is not fatal, don't bother checking
	//pBitmap is now our flag to tell us whether "entity.bmp" is in the
	//host exe's dir. If it is new instances will default DisplayToggle ON
	//(i.e. we assume we're in the editor instead of some game)
	//---
}

void Destroy_Class( void )
{
	int i;

	for (i = 0; i < MAX_NAMES; i++)
		{
		if (NameList[i])
			{
			jeRam_Free(NameList[i]);
			NameList[i] = NULL;
			}
		}

	NameListCount = 0;
	//Royce-2
	jeBitmap_Destroy(&pBitmap);
	//---
}

//////////////////////////////////////////////////////////////////////////////
//
//  DLL INTERFACE
//
//////////////////////////////////////////////////////////////////////////////

void * JETCC CreateInstance( void )
{
	EntityObj *pEntityObj;

	pEntityObj = JE_RAM_ALLOCATE_STRUCT( EntityObj );
	if( pEntityObj == NULL )
		return( NULL );
	memset(pEntityObj, 0, sizeof(*pEntityObj));
	
	//Royce-2
	pEntityObj->DisplayToggle = pBitmap ? JE_TRUE : JE_FALSE;
	//---
	strcpy(pEntityObj->Name, NoSelection);
	pEntityObj->RefCnt = 1;
	//Royce-2

	return( pEntityObj );
}


void JETCC CreateRef(void * Instance)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

	pEntityObj->RefCnt++;
}

jeBoolean JETCC Destroy(void **pInstance)
{
	EntityObj **hEntityObj = (EntityObj**)pInstance;
	EntityObj *pEntityObj = *hEntityObj;

	assert( pInstance );
	assert( pEntityObj->RefCnt > 0 );

	pEntityObj->RefCnt--;
	if( pEntityObj->RefCnt == 0 )
	{

		if (pEntityObj->Poly)
			{
			jeUserPoly_Destroy(&pEntityObj->Poly);
			}

		jeRam_Free( pEntityObj );
	}

	return JE_TRUE;
}


jeBoolean JETCC Render(const void * Instance, const jeWorld * pWorld, const jeEngine *Engine, const jeCamera *Camera, const jeFrustum *CameraSpaceFrustum, jeObject_RenderFlags RenderFlags)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );
	assert( pWorld );
	assert( Engine );
	assert( Camera );

	if( jeWorld_GetRenderRecursion( pWorld ) > 1 )
		return JE_TRUE;
	
	return( JE_TRUE );
}
static jeBoolean EntityObj_ReadActorNames(jeVFile *FileBase, int *FileCount)
{
	jeVFile_Finder * Finder;
	
	assert(FileBase);
	
	Finder = jeVFile_CreateFinder(FileBase,"*.act");
	if ( ! Finder )
	{
		jeVFile_Close(FileBase);
		return JE_FALSE;
	}
	
	while( jeVFile_FinderGetNextFile(Finder) )
	{
		jeVFile_Properties Properties;
		jeVFile_FinderGetProperties(Finder,&Properties);
		
		strlwr(Properties.Name);
		
		if (Util_StrDupManagePtr(&NameList[(*FileCount)++], Properties.Name, 32) == JE_FALSE)
		{
			jeVFile_DestroyFinder(Finder);
			return JE_FALSE;
		}
	}
	
	jeVFile_DestroyFinder(Finder);
	
	return JE_TRUE;
}
static jeBoolean JETCC EntityObj_GetActorNames( void * Instance, jeWorld * pWorld )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;
	jeResourceMgr *ResourceMgr;
	jeVFile *ActorDir;

	assert( Instance );
	assert( pWorld );

	Util_StrDupManagePtr(&NameList[0], NoSelection, 32);
	NameListCount = 1;

	ResourceMgr = jeWorld_GetResourceMgr(pWorld);

	if (ResourceMgr == NULL)
		return JE_FALSE;

	ActorDir = jeResource_GetVFile(ResourceMgr, "Actors");

	if (!ActorDir)
		return JE_FALSE;

	if (!EntityObj_ReadActorNames(ActorDir, &NameListCount))
		return JE_FALSE;

	return( JE_TRUE );
}
jeBoolean JETCC AttachWorld( void * Instance, jeWorld * pWorld )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;


	assert( Instance );
	assert( pWorld );

	pEntityObj->World = pWorld;

	if (!EntityObj_GetActorNames(Instance, pEntityObj->World))
		return JE_FALSE;

	jeProperty_FillCombo( &EntityPropertyList.pjeProperty[ENTITY_NAMELIST_INDEX], 
		PROP2_NAME, pEntityObj->Name, ENTITYOBJ_NAMELIST, NameListCount, NameList );

	//Royce-2
	
	// add the Poly to the world
	if (pEntityObj->DisplayToggle && !pEntityObj->Poly ) {
		if (EntityObject_InitIcon(pEntityObj)) {
			if ( jeWorld_AddUserPoly( pWorld, pEntityObj->Poly, JE_FALSE ) == JE_FALSE )
			{
				jeUserPoly_Destroy( &( pEntityObj->Poly ) );
				return JE_FALSE;
			}
		}
		else return JE_FALSE;
		EntityObject_UpdateIcon(pEntityObj);
	}
	//---
	


	return( JE_TRUE );
}

jeBoolean	JETCC DettachWorld( void * Instance, jeWorld * pWorld )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

	//Royce-2
	if (pEntityObj->Poly) {
		if (pEntityObj->DisplayToggle) 
			if ( jeWorld_RemoveUserPoly( pWorld, pEntityObj->Poly) == JE_FALSE ) 
				return JE_FALSE;
		
		
		jeUserPoly_Destroy(&(pEntityObj->Poly));
		//---
	}

	pEntityObj->World = NULL;

	return( JE_TRUE );
}
				
jeBoolean	JETCC AttachEngine ( void * Instance, jeEngine *Engine )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;


	assert( Instance );
	assert( Engine );

	//Royce-2
	if( pBitmap )
		return( jeEngine_AddBitmap( (jeEngine*)Engine, pBitmap, JE_ENGINE_BITMAP_TYPE_3D ) );	
	//---
	return JE_TRUE;
	Instance;
}

jeBoolean	JETCC DettachEngine( void * Instance, jeEngine *Engine )
{
	assert( Instance );

	//Royce-2
	
	if( pBitmap )
		jeEngine_RemoveBitmap(	Engine, pBitmap );
	//---
	return( JE_TRUE );
	Instance;
}

jeBoolean	JETCC AttachSoundSystem( void * Instance, jeSound_System *SoundSystem )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;


	assert( Instance );

	return( JE_TRUE );
}

jeBoolean	JETCC DettachSoundSystem( void * Instance, jeSound_System *SoundSystem )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

	return( JE_TRUE );
	SoundSystem;
}

jeBoolean	JETCC Collision(const jeObject *Object, const jeExtBox *Box, const jeVec3d *Front, const jeVec3d *Back, jeVec3d *Impact, jePlane *Plane)
{
	return( JE_FALSE );
}

jeBoolean JETCC SetMaterial(void * Instance,const jeBitmap *Bmp,const jeRGBA * Color)
{
	return( JE_TRUE );
}

jeBoolean JETCC GetMaterial(const void * Instance,jeBitmap **pBmp,jeRGBA * Color)
{
	return( JE_TRUE );
}

jeBoolean JETCC GetExtBox(const void * Instance,jeExtBox *BBox)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;
	jeVec3d Point;

	assert( Instance );
	assert( BBox );

	Point = pEntityObj->Pos;

	jeExtBox_Set (  BBox, 
					Point.X-5.0f, Point.Y-5.0f, Point.Z-5.0f,
					Point.X+5.0f, Point.Y+5.0f, Point.Z+5.0f);

	return( JE_TRUE );
}

#ifndef NEWLOAD_START
void *	JETCC CreateFromFile(jeVFile * File, jePtrMgr *PtrMgr)
{
	EntityObj * pEntityObj;

	pEntityObj = JE_RAM_ALLOCATE_STRUCT( EntityObj );
	memset(pEntityObj, 0, sizeof(*pEntityObj));
	if( pEntityObj == NULL )
		return( NULL );

#ifdef NEW_READ 
	{
	int Version;
	if (!jeVFile_Read(File,  &Version, sizeof(Version)))
		goto CFF_ERROR;

	if (Version != ENTITYOBJ_VERSION_MAJOR)
		{
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "PathObject file format/version has changed.", NULL);
		goto CFF_ERROR;
		}

	if (!jeVFile_Read(File,  &Version, sizeof(Version)))
		goto CFF_ERROR;
	}
#endif

	if( !jeVFile_Read(	File, pEntityObj->Name, sizeof( pEntityObj->Name) ) )
		goto CFF_ERROR;
	if( !jeVFile_Read(	File, &pEntityObj->Pos, sizeof( pEntityObj->Pos) ) )
		goto CFF_ERROR;

	//Royce-2
	//this property is detected based on the existance of entity.bmp
	pEntityObj->DisplayToggle = pBitmap ? JE_TRUE : JE_FALSE; //not a fatal error
	//---
	pEntityObj->RefCnt = 1;

	return( pEntityObj );

CFF_ERROR:
	jeRam_Free( pEntityObj );
	return( NULL );
	PtrMgr;
}
#endif

#ifndef NEWSAVE_START
jeBoolean	JETCC WriteToFile(const void * Instance,jeVFile * File, jePtrMgr *PtrMgr)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

#ifdef NEW_WRITE
	{
	int Version;

	Version = EntityObj_VERSION_MAJOR;
	if (!jeVFile_Write(File,  &Version, sizeof(Version)))
		return( JE_FALSE );

	Version = EntityObj_VERSION_MINOR;
	if (!jeVFile_Write(File,  &Version, sizeof(Version)))
		return( JE_FALSE );
	}
#endif

	if( !jeVFile_Write(	File, pEntityObj->Name, sizeof( pEntityObj->Name) ) )
		return( JE_FALSE );
	if( !jeVFile_Write(	File, &pEntityObj->Pos, sizeof( pEntityObj->Pos) ) )
		return( JE_FALSE );


	return( JE_TRUE );
	PtrMgr;
}
#endif

jeBoolean	JETCC GetPropertyList(void * Instance, jeProperty_List **List)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

	if (pEntityObj->World)
	{
		if (!EntityObj_GetActorNames(Instance, pEntityObj->World))
			return JE_FALSE;
		
		jeProperty_FillCombo( &EntityPropertyList.pjeProperty[ENTITY_NAMELIST_INDEX], 
			PROP2_NAME, pEntityObj->Name, ENTITYOBJ_NAMELIST, NameListCount, NameList );
	}
	else
	{
		jeProperty_FillCombo( &EntityPropertyList.pjeProperty[ENTITY_NAMELIST_INDEX], 
			PROP2_NAME, NoSelection, ENTITYOBJ_NAMELIST, 1, &NoSelection );
	}

	//Royce-2
	jeProperty_FillCheck( &EntityPropertyList.pjeProperty[ENTITY_DISPLAYTOGGLE_INDEX],
		PROP1_NAME, pEntityObj->DisplayToggle, ENTITYOBJ_DISPLAYTOGGLE);
	//---

	*List = jeProperty_ListCopy( &EntityPropertyList);
	EntityPropertyList.bDirty = JE_FALSE;

	if( *List == NULL )
		return( JE_FALSE );

	return( JE_TRUE );
}


jeBoolean	JETCC SetProperty( void * Instance, int32 FieldID, PROPERTY_FIELD_TYPE DataType, jeProperty_Data * pData )
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );
	assert( pData );

	//Royce-2
	
	switch (FieldID) { 
	case ENTITYOBJ_NAMELIST:
		
		if (strcmp(pData->String, NoSelection) == 0)
			return JE_TRUE;
		
		strcpy(pEntityObj->Name, pData->String);
		//AmbObject_LoadSound(pAmbObj, pData->String);
		EntityPropertyList.bDirty = JE_TRUE;
		break;
	case ENTITYOBJ_DISPLAYTOGGLE:
		pEntityObj->DisplayToggle = pData->Bool;
		if (pEntityObj->DisplayToggle ) {
			if ( pEntityObj->World) {
				if (pBitmap) {
					if (!pEntityObj->Poly) 
						EntityObject_InitIcon(pEntityObj);

					//turn on the sprite
					if ( jeWorld_AddUserPoly( pEntityObj->World, pEntityObj->Poly, JE_FALSE ) == JE_FALSE ) {
						//if this busts we should probably hear about it
						//but it is not fatal
						jeUserPoly_Destroy( &( pEntityObj->Poly ) );
						jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to add the Entity UserPoly to the World.", NULL);
						//note that the bitmap may still be outstanding
					}
					EntityObject_UpdateIcon(pEntityObj);
				}
			}
		}
		else {
			//turn off the sprite
			if (pEntityObj->Poly) {
				if ( jeWorld_RemoveUserPoly( pEntityObj->World, pEntityObj->Poly) == JE_FALSE ) {
					//something bad has probably gone wrong here
					//but I still don't think it should be fatal
					jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to remove the Entity UserPoly from the World.", NULL);
					break; //don't orphan the poly 
				}
			}		
		}
		break;
	}
	//---

	return( JE_TRUE );
}

jeBoolean	JETCC SetXForm(void * Instance,const jeXForm3d *XF)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );
	assert( XF );

	pEntityObj->Pos = XF->Translation;
	EntityObject_UpdateIcon(pEntityObj);

	return( JE_TRUE );
}

jeBoolean JETCC GetXForm(const void * Instance,jeXForm3d *XF)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );
	assert( XF );

	jeXForm3d_SetIdentity(XF);
	XF->Translation = pEntityObj->Pos;
	return( JE_TRUE );
}

int	JETCC GetXFormModFlags( const void * Instance )
{
	Instance;
	return( JE_OBJECT_XFORM_TRANSLATE);
}

jeBoolean JETCC GetChildren(const void * Instance,jeObject * Children,int MaxNumChildren)
{
	return( JE_TRUE );
}

jeBoolean JETCC AddChild(void * Instance,const jeObject * Child)
{
	return( JE_TRUE );
}

jeBoolean JETCC RemoveChild(void * Instance,const jeObject * Child)
{
	return( JE_TRUE );
}

jeBoolean JETCC EditDialog (void * Instance,HWND Parent)
{
	return( JE_TRUE );
}


jeBoolean JETCC MessageFunction (void * Instance, int32 Msg, void * Data)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

	switch (Msg)
		{
		default:
			return JE_FALSE;
			break;
		}// switch

	return( JE_TRUE );
}


jeBoolean	JETCC UpdateTimeDelta(void * Instance, float TimeDelta )
{


	// ensure valid data
	assert( Instance != NULL );

	if ( TimeDelta == 0.0f )
	{
		return JE_TRUE;
	}

	return JE_TRUE;
}

#ifdef NEWLOAD_START
void *	JETCC CreateFromFile(jeVFile * File, jeNameMgr *NM)
{
	EntityObj * pEntityObj;

	pEntityObj = JE_RAM_ALLOCATE_STRUCT( EntityObj );
	memset(pEntityObj, 0, sizeof(*pEntityObj));
	if( pEntityObj == NULL )
		return( NULL );

#ifdef NEW_READ 
	{
	int Version;
	if (!jeVFile_Read(File,  &Version, sizeof(Version)))
		goto CFF_ERROR;

	if (Version != ENTITYOBJ_VERSION)
		{
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "PathObject file format/version has changed.", NULL);
		goto CFF_ERROR;
		}
	}
#endif

	if( !jeVFile_Read(	File, pEntityObj->Name, sizeof( pEntityObj->Name) ) )
		goto CFF_ERROR;
	if( !jeVFile_Read(	File, &pEntityObj->Pos, sizeof( pEntityObj->Pos) ) )
		goto CFF_ERROR;
	//Royce-2
	//this property is detected based on the existance of entity.bmp
	pEntityObj->DisplayToggle = pBitmap ? JE_TRUE : JE_FALSE; //not a fatal error
	//---
	pEntityObj->RefCnt = 1;

	return( pEntityObj );

CFF_ERROR:
	jeRam_Free( pEntityObj );
	return( NULL );
	NM;
}
#endif

#ifdef NEWSAVE_START
jeBoolean	JETCC WriteToFile(const void * Instance,jeVFile * File, jeNameMgr *NM)
{
	EntityObj *pEntityObj = (EntityObj*)Instance;

	assert( Instance );

#ifdef NEW_WRITE
	{
	int Version;

	Version = ENTITYOBJ_VERSION;
	if (!jeVFile_Write(File,  &Version, sizeof(Version)))
		return( JE_FALSE );
	}
#endif

	if( !jeVFile_Write(	File, pEntityObj->Name, sizeof( pEntityObj->Name) ) )
		return( JE_FALSE );
	if( !jeVFile_Write(	File, &pEntityObj->Pos, sizeof( pEntityObj->Pos) ) )
		return( JE_FALSE );

	return( JE_TRUE );
	NM;
}
#endif


//Royce
////////////////////////////////////////////////////////////////////////////////////////
//
//	DuplicateInstance()
//
///////////////////////////////////////////////////////////////////////////////////////
void * JETCC DuplicateInstance(void * Instance)
{
	jeVFile *ramdisk, *ramfile;
	jeVFile_MemoryContext vfsmemctx;
	jeObject* newEntityObj = NULL;
	jePtrMgr *ptrMgr = NULL;


	vfsmemctx.Data = jeRam_Allocate(OBJ_PERSIST_SIZE); //"I dunno, 100K sounds good."
	vfsmemctx.DataLength = OBJ_PERSIST_SIZE;

	if (!vfsmemctx.Data) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to allocate enough RAM to duplicate this object", NULL);
		return NULL;
	}

	ramdisk = jeVFile_OpenNewSystem
	(
		NULL, 
		JE_VFILE_TYPE_MEMORY|JE_VFILE_TYPE_VIRTUAL,
		"Memory",
		NULL,
		JE_VFILE_OPEN_CREATE|JE_VFILE_OPEN_DIRECTORY
	);

	if (!ramdisk) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to create a VFile Memory Directory", NULL);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}

	ramfile = jeVFile_Open(ramdisk, "tempObject", JE_VFILE_OPEN_CREATE);

	if (!ramfile) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to create a VFile Memory File", NULL);
		jeVFile_Close(ramdisk);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}
	ptrMgr = jePtrMgr_Create();

	if (!ptrMgr) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to create a Pointer Manager", NULL);
		jeVFile_Close(ramfile);
		jeVFile_Close(ramdisk);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}

	if (!WriteToFile(Instance, ramfile, jePtrMgr_Create())) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to write the object to a temp VFile Memory File", NULL);
		jeVFile_Close(ramfile);
		jeVFile_Close(ramdisk);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}

	if (!jeVFile_Rewind(ramfile)) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to rewind the temp VFile Memory File", NULL);
		jeVFile_Close(ramfile);
		jeVFile_Close(ramdisk);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}

	newEntityObj = CreateFromFile(ramfile, ptrMgr);
	if (!newEntityObj) {
		jeErrorLog_AddString(JE_ERR_SUBSYSTEM_FAILURE, "Unable to reade the object back from a temp VFile Memory File", NULL);
		jeVFile_Close(ramfile);
		jeVFile_Close(ramdisk);
		jeRam_Free(vfsmemctx.Data);
		return NULL;
	}

	jeVFile_Close(ramfile);
	jeVFile_Close(ramdisk);

	jeRam_Free(vfsmemctx.Data);

	return( newEntityObj );
}
//---

// Icestorm
jeBoolean	JETCC ChangeBoxCollision(const void *Instance,const jeVec3d *Pos, const jeExtBox *FrontBox, const jeExtBox *BackBox, jeExtBox *ImpactBox, jePlane *Plane)
{
	return( JE_FALSE );
}