//===========================================================================//
// File:	D3DRMVideoRenderables.cpp                                        //
// Project: MUNGA           Brick: Win95 Video Renderer 	                 //
// Contents: Windows95 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 <ElementRenderer\StateChange.hpp>

using namespace ElementRenderer;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VideoComponent::ClassData*
	VideoComponent::CreateFactoryRequest(FactoryRequestParameters *parameters)
{
	Check_Object(parameters);

	//
	//-------------------------------------------------------------------------
	// 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(VideoComponent));
	bool result = BaseClass::CreateFactoryRequest(parameters) != NULL;

	//
	//-------------------------------
	// Find the input channel to read
	//-------------------------------
	//
	Page *page = parameters->m_page;
	Check_Object(page);

	//
	//--------------------------
	// Deal with the translation
	//--------------------------
	//
	Point3D translation = Point3D::Identity;
	bool t_exists = page->GetEntry("Translation", &translation);

	//
	//-----------------------
	// Deal with the rotation
	//-----------------------
	//
	YawPitchRoll rotation = YawPitchRoll::Identity;
	bool r_exists =
		page->GetEntry("Rotation", &rotation);
	LinearMatrix4D matrix;
	matrix.BuildTranslation(translation);
	matrix.BuildRotation(rotation);
	*component_stream << matrix;

	//
	//-----------------------------------------------------------------
	// Now look for any element state changes.  If we did not force any
	// translation or rotation, then we can set the identity flag
	//-----------------------------------------------------------------
	//
	unsigned
		state=0,
		delta;
	OBB
		bounds;
	Element::ReadStateFromPage(
		page,
		*MString::s_Empty,
		&state,
		&delta,
		&bounds
	);
	state &= ~Element::LocalToParentIsIdentityFlag;
	delta |= Element::LocalToParentIsIdentityFlag;
	if (!t_exists && !r_exists)
	{
		state |= Element::LocalToParentIsIdentityFlag;
	}
	*component_stream << delta;
	if (delta)
	{
		*component_stream << state;
		if (delta & Element::OBBFlag)
			*component_stream << bounds;
	}

	//
	//--------------------------------------------------
	// Look for the various state changes, and save them
	//--------------------------------------------------
	//
	StateChange states(page, *MString::s_Empty);
	ElementRenderer::WriteERFVersion(component_stream);
	states.Save(component_stream);

	//
	//------------------
	// Return the status
	//------------------
	//
	Check_Object(DefaultData);
	return (result) ? DefaultData : NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GroupComponent::ClassData*
	GroupComponent::CreateFactoryRequest(FactoryRequestParameters *parameters)
{
	Check_Object(parameters);

	//
	//-------------------------------------------------------------------------
	// 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(GroupComponent));
	bool result = BaseClass::CreateFactoryRequest(parameters) != NULL;

	//
	//---------------------------------
	// Make the right kind of billboard
	//---------------------------------
	//
	Page *page = parameters->m_page;
	Check_Object(page);
	DynamicArrayOf<ComponentDescriptor> *component_names = parameters->m_components;
	Check_Object(component_names);
	ChainOf<Note*>* child_chain = page->MakeNoteChain("Child");
	Check_Object(child_chain);
	Page::NoteIterator children(child_chain);

	//
	//-----------------------------------------------------------
	// Loop through the children, making sure we can hook them up
	//-----------------------------------------------------------
	//
	Note *child;
	int child_id = -1;
	while ((child = children.ReadAndNext()) != NULL)
	{
		Check_Object(child);
		const char* child_name = NULL;
		child->GetEntry(&child_name);
		Check_Pointer(child_name);
		child_id = ComponentDescriptor::FindName(component_names, parameters->m_index, child_name);
		if (child_id == -1)
		{
			STOP((
				"%s: {[%s]Child=%s}: Unknown component name!",
				page->GetNotationFile()->GetFileName(),
				page->GetName(),
				child_name
			));
			result = false;
		}
		else
		{
			Component::ClassData* class_data = (*component_names)[child_id].m_classData;
			Check_Object(class_data);
			if (!class_data->IsDerivedFrom(VideoComponent::DefaultData))
			{
				STOP((
					"%s: {[%s]Child=%s}: Child is not an VideoComponent component!",
					page->GetNotationFile()->GetFileName(),
					page->GetName(),
					child_name
				));
				result = false;
			}
		}
		*component_stream << child_id;
		child_id = -1;
	}

	//
	//---------------------------------------------------------------
	// Make sure to always write the null ID to stop the child stream
	//---------------------------------------------------------------
	//
	*component_stream << child_id;
	Unregister_Object(child_chain);
	delete child_chain;

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