// Copyright (c)1999 MetaCreations All Rights Reserved.

//   Modifier Extension : BARYCENTER
//------------------------------
//   Implementation of the BARYCENTER Interface
//////////////////////////////////////////////////////////////////////// 


#include "BARYCENTER.h"
#include "MCCountedPtrHelper.h"
#include "Weight.h"
#include "COMUtilities.h"
#include "BasicModifiers.h"
#include "I3DShRenderFeature.h"
#include "I3DShRenderable.h"
#include "I3DShTreeElement.h"
#include "I3DShScene.h"

const MCGUID CLSID_ExBarycenter(R_CLSID_ExBarycenter);

void Extension3DInit(IMCUnknown* utilities)
{
	// Perform your dll initialisation there
}

void Extension3DCleanup()
{
}


TBasicUnknown* MakeCOMObject(const MCCLSID& classId)	//  method instanciate
{														// the object Fog
	TBasicUnknown* res = NULL;
	
	
	if (classId == CLSID_ExBarycenter) res = new ExBarycenter;
	if (classId == CLSID_ExWeight) res = new Weight;
	
	return res;
}

void* ExBarycenter::GetExtensionDataBuffer()
{
	return &fData;
}


// Constructor / Destructor of the C++ Object :
ExBarycenter::ExBarycenter()
{
}


// I3DExTreeBehavior methods :

MCCOMErr ExBarycenter::Apply(I3DShTreeElement* tree)
{
	// check for all the instances to find a misc feature
	TMCCountedPtr<I3DShScene> ascene;
	TMCCountedPtr<I3DShGroup> agroup;
	TMCCountedPtr<I3DShTreeElement> atree;
	TMCCountedPtr<I3DShTreeElement> atreeBis;
	TMCCountedPtr<I3DShDataComponent> agendata;
	TMCCountedPtr<Weight> weightGenData;
	
	const TRenderableAndTfmArray* instances;	
	real totalWeight=0;
	TVector3 sumPos; sumPos[0]=0; sumPos[1]=0; sumPos[2]=0;
	uint32 jj;
	uint32 nbMisc;

	tree->GetScene(&ascene);
	ascene->GetTreeRoot(&agroup);
	agroup->QueryInterface(IID_I3DShTreeElement,(void**)&atree);
	ThrowIfNil(atree);
	
	atree->BeginGetRenderables(instances);
	TRenderableAndTfmArray::const_iterator	iter = instances->Begin();
		
	for (const TRenderableAndTfm* curInstance = iter.First(); iter.More(); curInstance = iter.Next())
	{
		curInstance->fInstance->QueryInterface(IID_I3DShTreeElement, (void**)&atreeBis);
		/*if (atreeBis == tree)
		{
			TRenderableFlags renderableFlags = curInstance->fRenderable->GetRenderableFlags();
			renderableFlags.SetMaskedValue(TRenderableFlags::kStaticMask,false);
		}
		*/
		if (atreeBis != tree)
		{
			nbMisc=atreeBis->GetDataComponentsCount();
			for (jj=nbMisc; jj>0; jj--)
			{
				// loop on all the misc features
				atreeBis->GetDataComponentByIndex(&agendata,jj-1);
				if (agendata->QueryInterface(CLSID_ExWeight, (void**)&weightGenData)==MC_S_OK)
				{
					real weight=weightGenData->GetWeight();
					totalWeight += weight;
					sumPos[0]+=curInstance->fT.fTranslation[0] * weight;
					sumPos[1]+=curInstance->fT.fTranslation[1] * weight;
					sumPos[2]+=curInstance->fT.fTranslation[2] * weight;
				}
			}
		}
	}
		
	if (totalWeight!=0)
	{
		TTransform3D tr;
		// Set the new position of tree
		tree->GetGlobalTransform3D(tr);
		tr.fTranslation[0] = sumPos[0] / totalWeight;
		tr.fTranslation[1] = sumPos[1] / totalWeight;
		tr.fTranslation[2] = sumPos[2] / totalWeight;
		tree->SetGlobalTransform3D(tr);
	}
	
	atree->EndGetRenderables();
	
	return MC_S_OK;
}

