
#include "AdeptHeaders.hpp"
#include "GameModelAttribute.hpp"

//#############################################################################
//##########################    ModelAttributeEntry    #############################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ModelAttributeEntry::ModelAttributeEntry(
	Entity__GameModel::AttributeID attribute_ID,
	const char *attribute_name,
	RegisteredClass::ClassID attribute_type,
	Entity__GameModel::AttributePointer attribute_address
):
	Plug(DefaultData),
	attributeName(attribute_name)
{
	attributeID = attribute_ID;
	attributeType = attribute_type;
	attributeAddress = attribute_address;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ModelAttributeEntry::~ModelAttributeEntry()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ModelAttributeEntry::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	STOP(("Not implemented for this attribute"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ModelAttributeEntry::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	STOP(("Not implemented for this attribute"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	ModelAttributeEntry::GetChangedValue(
		Entity__GameModel *model, 
		void *new_value,
		void *current_value,
		Scalar diff_threshold
	)
{
	STOP(("Not implemented for this attribute"));
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Scalar, ScalarClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Scalar, ScalarClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Vector3D, Vector3DClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Vector3D, Vector3DClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<int, IntClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<int, IntClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Radian, RadianClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Radian, RadianClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Point3D, Point3DClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Point3D, Point3DClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Normal3D, Normal3DClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Normal3D, Normal3DClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<UnitQuaternion, UnitQuaternionClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<UnitQuaternion, UnitQuaternionClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<EulerAngles, EulerAnglesClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<EulerAngles, EulerAnglesClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Motion3D, Motion3DClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<Motion3D, Motion3DClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<LinearMatrix4D, LinearMatrix4DClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<LinearMatrix4D, LinearMatrix4DClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<ResourceID, ResourceIDClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<ResourceID, ResourceIDClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<bool, BoolClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<bool, BoolClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<const char *, CharClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	Str_Copy((char *)pointer, (char *)new_value, Entity__GameModel::MaxStringLength);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<const char *, CharClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	Str_Copy((char *)new_value, (char *)pointer, Entity__GameModel::MaxStringLength);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<RGBAColor, RGBAColorClassID>::SetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,pointer) = *Cast_Pointer(T*,new_value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectModelAttributeEntryOf<RGBAColor, RGBAColorClassID>::GetValue(
		Entity__GameModel *model, 
		void *new_value
	)
{
	Check_Object(model);
	Check_Pointer(new_value);
	Verify(attributeAddress != NULL);

	void *pointer = &(model->*attributeAddress);
	*Cast_Pointer(T*,new_value) = *Cast_Pointer(T*,pointer);
}

//#############################################################################
//#########################    ModelAttributeTable    #########################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ModelAttributeTable::ModelAttributeTable():
	attributesByID(NULL, true),
	attributesByName(NULL, true)
{
	#if defined(_ARMOR)
		verifyTable = true;
	#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ModelAttributeTable::~ModelAttributeTable()
{
	attributesByID.DeletePlugs();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ModelAttributeTable::CopyFrom(ModelAttributeTable *attribute_table)
{
	Check_Object(attribute_table);

	TableIteratorOf<ModelAttributeEntry*, Entity__GameModel::AttributeID>
		iterator(&attribute_table->attributesByID);
	ModelAttributeEntry
		*attribute_entry;

	while ((attribute_entry = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(attribute_entry);
		attributesByID.AddValue(attribute_entry, attribute_entry->attributeID);
		attributesByName.AddValue(attribute_entry, attribute_entry->attributeName);
	}

	#if defined(_ARMOR)
		VerifyTable();
	#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ModelAttributeTable::AddAttributeEntry(ModelAttributeEntry *attribute_entry)
{
	Check_Object(attribute_entry);
	
	//
	// If entry already exists then remove it
	//
	ModelAttributeEntry 
		*found_attribute_entry;

	found_attribute_entry = attributesByID.Find(attribute_entry->attributeID);
	if (found_attribute_entry != NULL)
	{
		Check_Object(found_attribute_entry);
		attributesByID.RemovePlug(found_attribute_entry);
		attributesByName.RemovePlug(found_attribute_entry);
	}
	
	//
	// Add entry to the table
	//
	attributesByID.AddValue(attribute_entry, attribute_entry->attributeID);
	attributesByName.AddValue(attribute_entry, attribute_entry->attributeName);

	//
	// Verify that the attribute IDs correspond to array position
	//
	#if defined(_ARMOR)
		verifyTable = true;
	#endif
}

#if defined(_ARMOR)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ModelAttributeTable::VerifyTable()
{
	//
	// Verify that the attribute IDs correspond to array position
	//
	if (verifyTable)
	{
		verifyTable = false;

		TableIteratorOf<ModelAttributeEntry*, Entity__GameModel::AttributeID>
			iterator(&attributesByID);
		unsigned
			table_size;

		table_size = iterator.GetSize();
		for (int i = 0; i < table_size; i++)
		{
			ModelAttributeEntry 
				*test_attribute_entry;

			test_attribute_entry = iterator.GetNth(i);
			Check_Object(test_attribute_entry);
			Verify(test_attribute_entry->attributeID == i);
		}
	}
}
#endif
