#include "AdeptHeaders.hpp"

#include "VideoHeaders.hpp"

//
// Class Data Support
//
Component::ClassData*
	ScalableShapeComponent::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ScalableShapeComponentClassID,
			"Adept::ScalabeShapeComponent",
			BaseClass::DefaultData,
			0,
			NULL
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ScalableShapeComponent::ScalableShapeComponent(
	ClassData *class_data,
	MemoryStream *stream,
	VideoComponentWeb *owning_web
):
	VideoComponent(
		class_data,
		stream,
		owning_web,
		ReadShape(stream)
	)
{
	Check_Object(owning_web);

	//
	//----------------------
	// Set the initial scale
	//----------------------
	//
	Scalar scale;
	*stream >> scale;
	Verify(scale > 0.01f);
	ElementRenderer::ScalableShapeElement *element = GetElement();
	Check_Object(this);
	element->SetScale(Vector3D(1.0f, 1.0f, 1.0f));
	gos_PushCurrentHeap(ElementRenderer::ScalableShapeElement::s_Heap);
	gos_PopCurrentHeap();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Element*
	ScalableShapeComponent::ReadShape(MemoryStream *stream)
{
	Check_Object(stream);

	//
	//-----------------------
	// Make the memory stream
	//-----------------------
	//
	bool instance;
	*stream >> instance;
	ResourceID mesh_id;
	*stream >> mesh_id;
	Resource shape_stream(mesh_id);
	ElementRenderer::ScalableShapeElement *shape =
		ElementRenderer::ScalableShapeElement::MakeFromShape(
			&shape_stream,
			ElementRenderer::ReadERFVersion(&shape_stream)
		);
	Register_Object(shape);
	return shape;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::SkipStreamData(MemoryStream *stream)
{
	Check_Object(this);
	Check_Object(stream);

	ResourceID mesh_id;
	*stream >> mesh_id;

	BaseClass::SkipStreamData(stream);

	Scalar scale;
	*stream >> scale;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ScalableShapeComponent*
	ScalableShapeComponent::Create(
		MemoryStream *stream,
		VideoComponentWeb *owning_web
	)
{
	Check_Object(stream);
	Check_Object(owning_web);
	Component *component = DoesComponentExist(stream, owning_web);
	ScalableShapeComponent *object;
	if (component)
	{
		object = static_cast<ScalableShapeComponent*>(component);
		Check_Object(object);
		object->SkipStreamData(stream);
	}
	else
	{
		object = new ScalableShapeComponent(DefaultData, stream, owning_web);
		Register_Object(object);
	}
	return object;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::SetScale(Scalar x_scale, Scalar y_scale, Scalar z_scale)
{
	Check_Object(this);
	Verify(x_scale >= 0.01f);
	Verify(y_scale >= 0.01f);
	Verify(z_scale >= 0.01f);

	ElementRenderer::ScalableShapeElement *element = GetElement();
	Check_Object(this);
	element->SetScale(Vector3D(x_scale, y_scale, z_scale));
	element->NeedMatrixSync();
	element->Sync();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::ChannelChanged(Channel *channel)
{
	Check_Object(this);
	Check_Object(channel);

	switch (channel->GetCommand())
	{
	case VideoRenderer::ScaleChangedCommandID:
		{
			ChannelOf<Scalar> *scale_channel =
				Cast_Object(ChannelOf<Scalar>*, channel);
			SetScale(scale_channel->ReadChannel(), scale_channel->ReadChannel(), scale_channel->ReadChannel());
		}
		break;
	case VideoRenderer::ZScaleChangedCommandID:
		{
			ChannelOf<Scalar> *scale_channel =
				Cast_Object(ChannelOf<Scalar>*, channel);
			SetScale(1.0f, 1.0f, scale_channel->ReadChannel());
		}
		break;
	default:
		BaseClass::ChannelChanged(channel);
		break;
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ScalableShapeComponent::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}
