//===========================================================================//
// File:	vidrend.cc																			  //
// Project: MUNGA           Brick: Video Renderer Manager	                 //
// Contents: Interface specification Video Renderer Manager       			  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/11/95  GAC  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include <munga.hpp>
#pragma hdrstop

#if !defined(VIDREND_HPP)
#	include <vidrend.hpp>
#endif

#if !defined(APP_HPP)
	#include <app.hpp>
#endif

#if !defined(ENTITY_HPP)
	#include <entity.hpp>
#endif

#if defined(USE_ONE_VIDEO_TRACE) || defined(TRACE_VIDEO_RENDERER)
	BitTrace Video_Renderer("Video Renderer");
#endif

#if !defined(USE_ONE_VIDEO_TRACE)
#	if defined(TRACE_VIDEO_BECOME_INTERESTING)
		BitTrace Video_Become_Interesting("Video Become Interesting");
#	endif

#	if defined(TRACE_VIDEO_BECOME_UNINTERESTING)
		BitTrace Video_Become_Uninteresting("Video Become Uninteresting");
#	endif
#endif

//
//#############################################################################
// Constructor for the video renderer
//#############################################################################
//
VideoRenderer::VideoRenderer(
	RendererRate calibration_rate,
	RendererComplexity calibration_complexity,
	RendererPriority calibration_priority,
	InterestType interest_type,
	InterestDepth depth_calibration
):
	Renderer(
		 calibration_rate,
		 calibration_complexity,
		 calibration_priority,
		 interest_type,
		 depth_calibration
		)
{
	Disconnected_Eye	=	False;
}
//
//#############################################################################
// Destructor for the video renderer
//#############################################################################
//
VideoRenderer::~VideoRenderer()
{
}
//
//#############################################################################
// This creates the data structures and loads up data for an entity that has
// become interesting to the renderer.
//#############################################################################
//
void
	VideoRenderer::NotifyOfNewInterestingEntity(Entity *interesting_entity)
{
	ResourceDescription
		*video_resource;
	ResourceFile
		*this_resource_file;
	ResourceDescription::ResourceID
		this_resource_ID;
	ViewFrom
		view_this_entity_from;
	//
	// Check the newly interesting entity, then determine what kind of view we want
	// to construct for it by seeing if it is the linked entity and checking to
	// see if the eye is disconnected at a higher renderer level.
	//
	SET_VIDEO_BECOME_INTERESTING();
	Check(interesting_entity);
	if(Disconnected_Eye)
	{
		view_this_entity_from	=	outsideEntity;
	}
	else
	{
		if(interesting_entity == GetLinkedEntity())
		{
			view_this_entity_from	=	insideEntity;
		}
		else
		{
			view_this_entity_from	=	outsideEntity;
		}
	}
	//
	// Try to fetch this entity's video resource, if there isn't one, we still
	// call make renderables as something up above us may have code to construct
	// some effects independant of the resource file.
	//
	Check(application);
	this_resource_file	=	application->GetResourceFile();
	Check(this_resource_file);
	this_resource_ID		=	interesting_entity->GetResourceID();
	video_resource			= this_resource_file->SearchList(
		this_resource_ID,
		ResourceDescription::VideoModelResourceType);
	//
	// Call the make renderables process to convert the resource script into a
	// set of renderables for this entity.
	//
	if (video_resource)
	{
		video_resource->Lock();
	}
	MakeEntityRenderables(
		interesting_entity,
		video_resource,
		view_this_entity_from
	);
	if (video_resource)
	{
		video_resource->Unlock();
	}

	CLEAR_VIDEO_BECOME_INTERESTING();
}
//
//#############################################################################
// This handles killing off of an entity that has become uninteresting.
//#############################################################################
//
void
	VideoRenderer::NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity)
{
	SET_VIDEO_BECOME_UNINTERESTING();
	//
	// Destroy the dynamic entities that go with this uninteresting Entity
	// in the reverse order that they were created.
	//
	{
		Entity::DynamicVideoSocketIterator
			iterator(uninteresting_entity);
		Component
			*component;

		Check(&iterator);
		iterator.Last();
		while ((component = iterator.ReadAndPrevious()) != NULL)
		{
			Unregister_Object(component);
			delete component;
		}
	}

	//
	// Destroy the static entities that go with this uninteresting Entity
	// in the reverse order that they were created.
	//
	{
		Entity::StaticVideoSocketIterator
			iterator(uninteresting_entity);
		Component
			*component;

		Check(&iterator);
		iterator.Last();
		while ((component = iterator.ReadAndPrevious()) != NULL)
		{
			Unregister_Object(component);
			delete component;
		}
	}

	#if 0
	//
	// Destroy all the static and dynamic entities that go with this uninteresting Entity
	// in the same order they were created.  This caused some problems for DPL in the past
	// but it may no longer be the case.
	//

	Entity::DynamicVideoSocketIterator iterator(uninteresting_entity);
	iterator.DeletePlugs();

	Entity::StaticVideoSocketIterator static_iterator(uninteresting_entity);
	static_iterator.DeletePlugs();

	uninteresting_entity->DeleteVideoWatchers();
	#endif

	CLEAR_VIDEO_BECOME_UNINTERESTING();
}
//
//#############################################################################
// Execute Method, performs the rendering of one frame
//#############################################################################
//
void
	VideoRenderer::ExecuteImplementation(
		RendererComplexity,
		RendererOrigin::InterestingEntityIterator *
	)
{
	Tell("VideoRenderer::ExecuteImplementation has been called\n");
}
//
//#############################################################################
// This process is supposed to make the renderables for an object, when a higher
// level of this virtual can't figure out how to make something it calls down
// to the level below it.  If we reach here then nobody could figure out what
// to do so we can print an error or information message.
//#############################################################################
//
void
	VideoRenderer::MakeEntityRenderables(
				Entity* my_entity,						// The entity we are dealing with
				ResourceDescription*,	// Pointer to the video resource
				ViewFrom)					// Type of reference (inside/outside...etc.)
{
	switch (my_entity->GetClassID())
	{
		//
		// Scorezones are allowed to have no graphics.
		//
		case	ScoreZoneClassID:
			break;
		//
		// Default case complains about missing graphics
		//
		default:
			DEBUG_STREAM<<"Entity "<<my_entity->entityID<<" class"<<my_entity->GetClassID();
			DEBUG_STREAM<<" couldn't figure out how to MakeEntityRenderables\n";
			break;
	}
}
//
//#############################################################################
// Startup the implementation of the Division video renderer
//#############################################################################
//
void
	VideoRenderer::LoadMissionImplementation(Mission*)
{
	Tell("VideoRenderer::StartImplementation has been called\n");
}
void
	VideoRenderer::ShutdownImplementation()
{
	Tell("VideoRenderer::StopImplementation has been called\n");
}
void
	VideoRenderer::SuspendImplementation()
{
	Tell("VideoRenderer::SuspendImplementation has been called\n");
}
void
	VideoRenderer::ResumeImplementation()
{
	Tell("VideoRenderer::ResumeImplementation has been called\n");
}

Logical
	VideoRenderer::TestInstance() const
{
	return IsDerivedFrom(ClassDerivations);
}
