#include "stdafx.h"
#include "SceneNode.h"
#include "Bone.h"



namespace geom
{


bool SceneNode::HasKey(void) const
{
	if (!m_Rotate.empty())
		return true;
	if (!m_Scale.empty())
		return true;
	if (!m_Translate.empty())
		return true;
	return false;
}

lm::matrix4f SceneNode::GetFrameTransform(int frame) const
{
	// 未定義フレーム番号が指定された場合はノードのトランスフォームを返す
	if (frame < 0)
		return m_Transform;
	if (!HasKey())
		return m_Transform;

	int max_kf = GetKeyframeMax();
	int fn = (lm::clamp)(0, frame, max_kf - 1);

	lm::matrix4f mt = lm::matrix4f::get_identity();

	if (!m_Scale.empty())
	{
		const lm::vec3f& s = m_Scale[fn];
		mt *= lm::matrix4f::get_scale(s.x, s.y, s.z);
	}

	if (!m_Rotate.empty())
	{
		float vel;
		lm::vec3f ax;
		m_Rotate[fn].get_rotate_params(ax, vel);
		mt *= lm::matrix4f::get_rotate(ax, vel);
	}

	if (!m_Translate.empty())
	{
		lm::vec3f d = m_Translate[fn];
		mt *= lm::matrix4f::get_translate(d);
	}

	return mt;
}

int SceneNode::GetKeyframeMax(void) const
{
	int child_max = 0;
	for (const SceneNode& n : m_Children)
	{
		child_max = (std::max)(child_max, n.GetKeyframeMax());
	}

	int st = (int)m_Translate.size();
	int ss = (int)m_Rotate.size();
	int sr = (int)m_Scale.size();
	int cm = (lm::max)(st, ss, sr);

	return (std::max)(child_max, cm);
}


int GeoNodeTree::GetKeyframeMax(void) const
{
	int kf = 0;
	for (const SceneNode& n : m_RootNodes)
	{
		kf = (std::max)(kf, n.GetKeyframeMax());
	}

	return kf;
}

void GeoNodeTree::TraceNodeTree(void)
{
	for (SceneNode& n : m_RootNodes)
	{
		TraceNodeTreeN(&n);
	}
}

void GeoNodeTree::TraceNodeTreeN(SceneNode* bn)
{
	static int TraceLayer = 0;

	if (bn == NULL)
		return;

	std::ostringstream s;
	for (int i = 0; i < TraceLayer; ++i)
	{
		s << "|";
	}

	s << "+" << bn->m_Name;
	if (bn->m_Bone != NULL)
		s << "b" << bn->m_Bone->m_Index;

	s << "(" << bn->GetKeyframeMax() << ")";
	s << "[";
	for (int mid : bn->m_MeshIDs)
	{
		s << " " << mid;
	}
	s << " ]";
	s << std::endl;
	OutputDebugStringA(s.str().c_str());

	for (SceneNode& cn : bn->m_Children)
	{
		TraceLayer++;
		TraceNodeTreeN(&cn);
		TraceLayer--;
	}
}


SceneNode* NodeMap::Find(const std::string& name)
{
	std::map<std::string, SceneNode*>::iterator i;
	i = Bones.find(name);
	if (i == Bones.end())
		return NULL;

	return i->second;
}


}
