//===========================================================================//
// File:	D3DRMVideoRenderables.cpp                                        //
// Project: MUNGA           Brick: Win95 Video Renderer 	                 // 
// Contents: GOS95 Layer Video Renderer									 //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 03/13/97  JTR  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1997, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "AdeptHeaders.hpp"

#include "VideoHeaders.hpp"
#include <gosFX\EffectLibrary.hpp>


#include "Entity.hpp"
#include "Attribute.hpp"
#include "EntityClassData.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BeamComponent::ClassData*
	BeamComponent::CreateFactoryRequest(
		FactoryRequestParameters *parameters,
		Entity::ClassData *class_data
	)
{
	Check_Object(parameters);
	Check_Object(class_data);

	//
	//-------------------------------------------------------------------------
	// Allocate enough room for what we need to write out, then call our parent
	//-------------------------------------------------------------------------
	//
	MemoryStream *component_stream = parameters->m_stream;
	Check_Object(component_stream);
	component_stream->AllocateBytes(sizeof(BeamComponent));

	//
	//------------------------------------
	// Find the parent object for the mesh
	//------------------------------------
	//
	Page *page = parameters->m_page;
	Check_Object(page);

	//
	//----------------------------------------------------------------------
	// Now see if this component is going to hook up to an attribute.  If it
	// doesn't, set it up as an executing looping effect
	//----------------------------------------------------------------------
	//
	int end_id = -1;
	const char* attribute_name;
	page->GetEntry("End", &attribute_name, true);
	Check_Object(class_data);
	bool result = true;
	const AttributeEntry *attribute_entry =
		class_data->attributeTable.GetAttributeEntry(attribute_name);
	if (attribute_entry == NULL)
	{
		STOP((
			"%s: {[%s]End=%s}: Unknown attribute!",
			page->GetNotationFile()->GetFileName(),
			page->GetName(),
			attribute_name
		));
		result = false;
	}
	else
	{
		Check_Object(attribute_entry);
		if (attribute_entry->attributeType != Point3DClassID)
		{
			PAUSE((
				"%s: {[%s]End=%s}: Attribute is not correct type!",
				page->GetNotationFile()->GetFileName(),
				page->GetName(),
				attribute_name
			));
			result = false;
		}
		else
			end_id = attribute_entry->attributeID;
	}
	*component_stream << end_id;

	//
	//---------------------------------------------------------------------
	// Now handle the LOD issues.  We first make a list of all the entries,
	// and look for the ones that convert to a non zero number
	//---------------------------------------------------------------------
	//
	Page::NoteIterator *entries = page->MakeNoteIterator();
	Check_Object(entries);
	Note *entry;
	#if defined(_ARMOR)
		Scalar last_range = 1e7f;
	#endif
	while ((entry = entries->ReadAndNext()) != NULL)
	{
		Check_Object(entry);
		Scalar range;
		range = AtoF(entry->GetName());
		if (range == 0.0f)
			continue;

		//
		//------------------------------------------------------------------
		// Compute the range squared, then write out the range to the stream
		//------------------------------------------------------------------
		//
		#if defined(_ARMOR)
			Verify(range < last_range);
			last_range = range;
		#endif
		range *= range;
		*component_stream << range;

		//
		//---------------------------------------------------
		// Read in the gosfx and find it in the gosFX library
		//---------------------------------------------------
		//
		const char* gosfx_name;
		entry->GetEntry(&gosfx_name);
		Check_Object(gosFX::EffectLibrary::Instance);
		int id = gosFX::EffectLibrary::Instance->Find(gosfx_name);
		if (id < 0)
			STOP(("can't find effect \"%s\"", gosfx_name));
		*component_stream << id;
	}
	*component_stream << -1.0f;
	delete entries;

	//
	//---------------------------------------------------
	// Read in the gosfx and find it in the gosFX library
	//---------------------------------------------------
	//
	const char* gosfx_name;
	page->GetEntry("gosFX", &gosfx_name, true);
	Check_Object(gosFX::EffectLibrary::Instance);
	int id = gosFX::EffectLibrary::Instance->Find(gosfx_name);
	if (id < 0)
		STOP(("can't find effect \"%s\"", gosfx_name));
	*component_stream << id;
	Resource::ParentFileDependencies->AddDependencies(&gosFX::EffectLibrary::Instance->m_fileDependencies);

	//
	//------------------------------------
	// Now set up the flags for the effect
	//------------------------------------
	//
	unsigned state = 0;
	bool execute=true;
	page->GetEntry("Execute", &execute);
	if (execute)
		state |= gosFX::Effect::ExecuteFlag;
	const char* sim_mode="LocalSpace";
	page->GetEntry("SimulationMode", &sim_mode);
	if (!_stricmp(sim_mode, "LocalSpace"))
		state |= gosFX::Effect::LocalSpaceSimulationMode;
	else if (!_stricmp(sim_mode, "StaticWorldSpace"))
		state |= gosFX::Effect::StaticWorldSpaceSimulationMode;
	else if (!_stricmp(sim_mode, "DynamicWorldSpace"))
		state |= gosFX::Effect::DynamicWorldSpaceSimulationMode;
	else
		STOP((
			"%s: {[%s]SimulationMode=%s}: Unknown simulation mode!",
			page->GetNotationFile()->GetFileName(),
			page->GetName(),
			sim_mode
		));

	//
	//----------------------------------------------------------------------
	// Now see if this component is going to hook up to an attribute.  If it
	// doesn't, set it up as an executing looping effect
	//----------------------------------------------------------------------
	//
	int attribute_id = -1;
	if (page->GetEntry("Status", &attribute_name))
	{
		Check_Object(class_data);
		const AttributeEntry *attribute_entry =
			class_data->attributeTable.GetAttributeEntry(attribute_name);
		if (attribute_entry == NULL)
		{
			STOP((
				"%s: {[%s]Status=%s}: Unknown attribute!",
				page->GetNotationFile()->GetFileName(),
				page->GetName(),
				attribute_name
			));
			result = false;
		}
		else
		{
			Check_Object(attribute_entry);
			if (attribute_entry->attributeType != BoolClassID)
			{
				PAUSE((
					"%s: {[%s]Status=%s}: Attribute is not correct type!",
					page->GetNotationFile()->GetFileName(),
					page->GetName(),
					attribute_name
				));
				result = false;
			}
			else
				attribute_id = attribute_entry->attributeID;
		}
	}

	//
	//-------------------------------------------------
	// If we don't have an attribute, we loop & execute
	//-------------------------------------------------
	//
	if (attribute_id == -1)
		state |= gosFX::Effect::LoopFlag|gosFX::Effect::ExecuteFlag;

	bool does_loop = false;
	page->GetEntry("DoesLoop", &does_loop);
	if(does_loop)
		state |= gosFX::Effect::LoopFlag|gosFX::Effect::ExecuteFlag;
	
	*component_stream << state;

	//
	//----------------------------
	// Let our parent do its thing
	//----------------------------
	//
	if (result)
		result = BaseClass::CreateFactoryRequest(parameters) != NULL;

	//
	//-------------------------------
	// Now write out the attribute id
	//-------------------------------
	//
	*component_stream << attribute_id << end_id;

	Check_Object(DefaultData);
	return (result) ? DefaultData : NULL;
}

