/**
 @file GraphicsData.cpp

 Dojo Game Engine

 Copyright 2005, Morgan McGuire
 All rights reserved.
 */
#include "dojo/GraphicsData.h"

namespace dojo {

GraphicsData::~GraphicsData() {}


GraphicsData::GraphicsData(const Q3MapModelRef& model) : type (Q3MAP), q3MapModel(model) {
}


GraphicsData::GraphicsData(const ArticulatedModelRef& model) : type (ARTICULATED), artmodel(model) {
}


GraphicsData::GraphicsData(const ASFModelRef& model) : type(ASF), asfmodel(model) {
}


GraphicsData::GraphicsData(
    const MD2ModelRef& model0, 
    const TextureRef&  t0, 
    const MD2ModelRef& model1,
    const TextureRef&  t1) : type(Q2CHARACTER) {
    md2model[0] = model0;
    md2model[1] = model1;
    md2material[0].texture.append(t0);
    md2material[1].texture.append(t1);
}



static GFontRef font() {
    static GFontRef f = GFont::fromFile(NULL, "dominant.fnt");
    return f;
}


static void drawLabels(
    RenderDevice*                   rd, 
    const CoordinateFrame&          cframe,  
    const ArticulatedModelRef&      m, 
    const ArticulatedModel::Part&   part) {

    font()->draw3D(rd, part.name, cframe, 0.05);
    
    for (int i = 0; i < part.subPartArray.size(); ++i) {
        int p = part.subPartArray[i];
        CoordinateFrame cframe2 = cframe * m->partArray[p].cframe;
        drawLabels(rd, cframe2, m, m->partArray[p]);
    }
}


static void drawLabelsHelper(RenderDevice* rd, const CoordinateFrame& cframe, const ArticulatedModelRef& m) {
    for (int p = 0; p < m->partArray.size(); ++p) {
        const ArticulatedModel::Part& part = m->partArray[p];
        if (part.parent == -1) {
            // This is a root part, pose it
            drawLabels(rd, cframe, m, part);
        }
    }

}


void GraphicsData::drawLabels(
    RenderDevice* rd, 
    const CoordinateFrame& physicsFrame) const {

    switch (type) {
    case ARTICULATED:
        font()->draw3D(rd, artmodel->name, cframe);
        drawLabelsHelper(rd, physicsFrame * cframe, artmodel);
        break;

    case ASF:
//        font()->draw3D(rd, asfmodel->name, cframe);
        drawLabelsHelper(rd, physicsFrame * cframe, asfmodel->model);
        break;

    case Q2CHARACTER:
        font()->draw3D(rd, md2model[0]->name(), physicsFrame * cframe);
        break;

    case Q3MAP:
//        font()->draw3D(rd, md2model->name(), physicsFrame * cframe);
        break;


    default:
        debugAssertM(false, "Unsupported model type");
    }
}


void GraphicsData::pose(
    Array<PosedModelRef>&   posedModels, 
    const CoordinateFrame&  physicsFrame) {

    switch (type) {
    case ARTICULATED:
        artmodel->pose(posedModels, physicsFrame * cframe, artpose);
        break;

    case ASF:
        asfmodel->pose(posedModels, physicsFrame * cframe);
        break;

    case Q2CHARACTER:
        for (int i = 0; i < 2; ++i) {
            posedModels.append(md2model[i]->pose(physicsFrame * cframe, md2pose, md2material[i]));
        }
        break;

    case Q3MAP:
        q3MapModel->pose(posedModels, physicsFrame * cframe);
        break;

    default:
        debugAssertM(false, "Unsupported model type");
    }
}

} // namespace
