/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "CommonConvert.h"
#include "PMDConvert.h"
#include "PSAConvert.h"
#include "StdSkeletons.h"
#include
#include
void default_logger(void*, int severity, const char* message)
{
fprintf(stderr, "[%d] %s\n", severity, message);
}
static LogFn g_Logger = &default_logger;
static void* g_LoggerCBData = NULL;
EXPORT void set_logger(LogFn logger, void* cb_data)
{
if (logger)
{
g_Logger = logger;
g_LoggerCBData = cb_data;
}
else
{
g_Logger = &default_logger;
g_LoggerCBData = NULL;
}
}
void Log(int severity, const char* msg, ...)
{
char buffer[1024];
va_list ap;
va_start(ap, msg);
vsnprintf(buffer, sizeof(buffer), msg, ap);
buffer[sizeof(buffer)-1] = '\0';
va_end(ap);
g_Logger(g_LoggerCBData, severity, buffer);
}
struct BufferedOutputCallback : public OutputCB
{
static const unsigned int bufferSize = 4096;
char buffer[bufferSize];
unsigned int bufferUsed;
OutputFn fn;
void* cb_data;
BufferedOutputCallback(OutputFn fn, void* cb_data)
: fn(fn), cb_data(cb_data), bufferUsed(0)
{
}
~BufferedOutputCallback()
{
// flush the buffer if it's not empty
if (bufferUsed > 0)
fn(cb_data, buffer, bufferUsed);
}
virtual void operator() (const char* data, unsigned int length)
{
if (bufferUsed+length > bufferSize)
{
// will overflow buffer, so flush the buffer first
fn(cb_data, buffer, bufferUsed);
bufferUsed = 0;
if (length > bufferSize)
{
// new data won't fit in buffer, so send it out unbuffered
fn(cb_data, data, length);
return;
}
}
// append onto buffer
memcpy(buffer+bufferUsed, data, length);
bufferUsed += length;
assert(bufferUsed <= bufferSize);
}
};
int convert_dae_to_whatever(const char* dae, OutputFn writer, void* cb_data, void(*conv)(const char*, OutputCB&, std::string&))
{
Log(LOG_INFO, "Starting conversion");
FCollada::Initialize();
std::string xmlErrors;
BufferedOutputCallback cb(writer, cb_data);
try
{
conv(dae, cb, xmlErrors);
}
catch (const ColladaException& e)
{
if (! xmlErrors.empty())
Log(LOG_ERROR, "%s", xmlErrors.c_str());
Log(LOG_ERROR, "%s", e.what());
FCollada::Release();
return -2;
}
FCollada::Release();
if (! xmlErrors.empty())
{
Log(LOG_ERROR, "%s", xmlErrors.c_str());
return -1;
}
return 0;
}
EXPORT int convert_dae_to_pmd(const char* dae, OutputFn pmd_writer, void* cb_data)
{
return convert_dae_to_whatever(dae, pmd_writer, cb_data, ColladaToPMD);
}
EXPORT int convert_dae_to_psa(const char* dae, OutputFn psa_writer, void* cb_data)
{
return convert_dae_to_whatever(dae, psa_writer, cb_data, ColladaToPSA);
}
EXPORT int set_skeleton_definitions(const char* xml, int length)
{
std::string xmlErrors;
try
{
Skeleton::LoadSkeletonDataFromXml(xml, length, xmlErrors);
}
catch (const ColladaException& e)
{
if (! xmlErrors.empty())
Log(LOG_ERROR, "%s", xmlErrors.c_str());
Log(LOG_ERROR, "%s", e.what());
return -1;
}
return 0;
}