metaforce/DataSpec/DNACommon/ANCS.hpp

185 lines
6.6 KiB
C++
Raw Normal View History

2015-08-11 23:32:02 +00:00
#ifndef _DNACOMMON_ANCS_HPP_
#define _DNACOMMON_ANCS_HPP_
2015-08-13 07:29:00 +00:00
#include <unordered_set>
2015-08-11 23:32:02 +00:00
#include "DNACommon.hpp"
#include "BlenderConnection.hpp"
#include "CMDL.hpp"
namespace Retro
{
namespace DNAANCS
{
template <typename IDTYPE>
struct CharacterResInfo
{
std::string name;
IDTYPE cmdl;
IDTYPE cskr;
IDTYPE cinf;
2015-09-27 02:24:03 +00:00
std::vector<std::pair<HECL::FourCC, std::pair<IDTYPE, IDTYPE>>> overlays;
2015-08-11 23:32:02 +00:00
};
template <typename IDTYPE>
struct AnimationResInfo
{
std::string name;
IDTYPE animId;
bool additive;
};
2015-09-26 03:12:08 +00:00
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
2015-08-11 23:32:02 +00:00
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
const ANCSDNA& ancs,
const HECL::ProjectPath& outPath,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
2015-09-06 21:44:57 +00:00
const SpecBase& dataspec,
std::function<void(const HECL::SystemChar*)> fileChanged,
2015-08-11 23:32:02 +00:00
bool force=false)
2015-08-13 07:29:00 +00:00
{
2015-09-06 21:44:57 +00:00
/* Extract character CMDL/CSKR first */
2015-08-11 23:32:02 +00:00
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
ancs.getCharacterResInfo(chResInfo);
2015-09-06 21:44:57 +00:00
for (const auto& info : chResInfo)
{
2015-10-04 05:08:56 +00:00
const NOD::Node* node;
2015-10-16 00:35:40 +00:00
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, true);
2015-09-06 21:44:57 +00:00
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
2015-10-07 01:17:17 +00:00
if (!conn.createBlend(cmdlPath, HECL::BlenderConnection::TypeMesh))
2015-09-06 21:44:57 +00:00
return false;
HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(*cmdlE));
fileChanged(bestNameView.sys_str().c_str());
typename ANCSDNA::CSKRType cskr;
pakRouter.lookupAndReadDNA(info.cskr, cskr);
typename ANCSDNA::CINFType cinf;
pakRouter.lookupAndReadDNA(info.cinf, cinf);
2015-09-26 03:12:08 +00:00
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
RigPair rigPair(&cskr, &cinf);
2015-09-06 21:44:57 +00:00
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
2015-09-26 03:12:08 +00:00
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
2015-09-06 21:44:57 +00:00
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
conn.saveBlend();
}
}
}
HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(entry));
fileChanged(bestNameView.sys_str().c_str());
2015-08-11 23:32:02 +00:00
/* Establish ANCS blend */
2015-10-07 01:17:17 +00:00
if (!conn.createBlend(outPath, HECL::BlenderConnection::TypeActor))
2015-08-11 23:32:02 +00:00
return false;
HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);
2015-08-13 07:29:00 +00:00
os.format("import bpy\n"
"from mathutils import Vector\n"
"bpy.context.scene.name = '%s'\n"
"bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
"\n"
"# Using 'Blender Game'\n"
"bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
"\n"
"# Clear Scene\n"
"for ob in bpy.data.objects:\n"
" if ob.type != 'LAMP':\n"
" bpy.context.scene.objects.unlink(ob)\n"
" bpy.data.objects.remove(ob)\n"
"\n"
"actor_data = bpy.context.scene.hecl_sact_data\n",
pakRouter.getBestEntryName(entry).c_str());
typename ANCSDNA::CINFType cinf;
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
for (const auto& info : chResInfo)
{
2015-08-15 04:12:15 +00:00
/* Provide data to add-on */
os.format("actor_subtype = actor_data.subtypes.add()\n"
"actor_subtype.name = '%s'\n\n",
info.name.c_str());
2015-08-13 07:29:00 +00:00
/* Build CINF if needed */
if (cinfsDone.find(info.cinf) == cinfsDone.end())
{
pakRouter.lookupAndReadDNA(info.cinf, cinf);
cinf.sendCINFToBlender(os, info.cinf);
cinfsDone.insert(info.cinf);
}
else
2015-09-24 00:59:36 +00:00
os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
2015-08-15 04:12:15 +00:00
os << "actor_subtype.linked_armature = arm_obj.name\n";
2015-08-13 07:29:00 +00:00
/* Link CMDL */
2015-10-16 00:35:40 +00:00
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, true);
2015-08-15 04:12:15 +00:00
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
2015-08-31 03:44:42 +00:00
os.linkBlend(cmdlPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE), true);
2015-08-15 04:12:15 +00:00
/* Attach CMDL to CINF */
os << "if obj.name not in bpy.context.scene.objects:\n"
" bpy.context.scene.objects.link(obj)\n"
"obj.parent = arm_obj\n"
"obj.parent_type = 'ARMATURE'\n"
"actor_subtype.linked_mesh = obj.name\n\n";
}
2015-09-27 02:24:03 +00:00
/* Link overlays */
for (const auto& overlay : info.overlays)
{
os << "overlay = actor_subtype.overlays.add()\n";
os.format("overlay.name = '%s'\n", overlay.first.toString().c_str());
/* Link CMDL */
2015-10-16 00:35:40 +00:00
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, true);
2015-09-27 02:24:03 +00:00
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
os.linkBlend(cmdlPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE), true);
/* Attach CMDL to CINF */
os << "if obj.name not in bpy.context.scene.objects:\n"
" bpy.context.scene.objects.link(obj)\n"
"obj.parent = arm_obj\n"
"obj.parent_type = 'ARMATURE'\n"
"overlay.linked_mesh = obj.name\n\n";
}
}
2015-08-13 07:29:00 +00:00
}
2015-08-11 23:32:02 +00:00
/* Get animation primitives */
std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
2015-08-11 23:32:02 +00:00
ancs.getAnimationResInfo(animResInfo);
for (const auto& id : animResInfo)
{
2015-08-13 07:29:00 +00:00
typename ANCSDNA::ANIMType anim;
if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true))
2015-08-15 04:12:15 +00:00
{
os.format("act = bpy.data.actions.new('%s')\n"
"act.use_fake_user = True\n", id.second.name.c_str());
anim.sendANIMToBlender(os, cinf, id.second.additive);
2015-08-15 04:12:15 +00:00
}
2015-08-13 07:29:00 +00:00
os.format("actor_action = actor_data.actions.add()\n"
"actor_action.name = '%s'\n", id.second.name.c_str());
2015-08-11 23:32:02 +00:00
}
2015-08-13 07:29:00 +00:00
os.close();
conn.saveBlend();
2015-08-11 23:32:02 +00:00
return true;
}
}
}
#endif // _DNACOMMON_ANCS_HPP_