Several initial character classes

This commit is contained in:
Jack Andersen 2016-04-09 18:49:02 -10:00
parent ac0d2d8828
commit 4f7d6e167f
30 changed files with 788 additions and 210 deletions

View File

@ -1,13 +1,14 @@
#include "DNACommon.hpp" #include "DNACommon.hpp"
#include "PAK.hpp" #include "PAK.hpp"
#include "boo/ThreadLocalPtr.hpp"
namespace DataSpec namespace DataSpec
{ {
logvisor::Module LogDNACommon("urde::DNACommon"); logvisor::Module LogDNACommon("urde::DNACommon");
SpecBase* g_curSpec = nullptr; ThreadLocalPtr<SpecBase> g_curSpec;
PAKRouterBase* g_PakRouter = nullptr; ThreadLocalPtr<PAKRouterBase> g_PakRouter;
hecl::Database::Project* UniqueIDBridge::s_Project = nullptr; ThreadLocalPtr<hecl::Database::Project> UniqueIDBridge::s_Project;
UniqueID32 UniqueID32::kInvalidId; UniqueID32 UniqueID32::kInvalidId;
} }

View File

@ -7,13 +7,14 @@
#include "hecl/hecl.hpp" #include "hecl/hecl.hpp"
#include "hecl/Database.hpp" #include "hecl/Database.hpp"
#include "../SpecBase.hpp" #include "../SpecBase.hpp"
#include "boo/ThreadLocalPtr.hpp"
namespace DataSpec namespace DataSpec
{ {
extern logvisor::Module LogDNACommon; extern logvisor::Module LogDNACommon;
extern SpecBase* g_curSpec; extern ThreadLocalPtr<SpecBase> g_curSpec;
extern class PAKRouterBase* g_PakRouter; extern ThreadLocalPtr<class PAKRouterBase> g_PakRouter;
/* This comes up a great deal */ /* This comes up a great deal */
typedef athena::io::DNA<athena::BigEndian> BigDNA; typedef athena::io::DNA<athena::BigEndian> BigDNA;
@ -84,22 +85,24 @@ class UniqueIDBridge
friend class UniqueID32; friend class UniqueID32;
friend class UniqueID64; friend class UniqueID64;
static hecl::Database::Project* s_Project; static ThreadLocalPtr<hecl::Database::Project> s_Project;
public: public:
template <class IDType> template <class IDType>
static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings=false) static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings=false)
{ {
if (!g_PakRouter) PAKRouterBase* pakRouter = g_PakRouter.get();
if (!pakRouter)
LogDNACommon.report(logvisor::Fatal, LogDNACommon.report(logvisor::Fatal,
"g_Project must be set to non-null before calling UniqueIDBridge::TranslatePakIdToPath"); "g_Project must be set to non-null before calling UniqueIDBridge::TranslatePakIdToPath");
return g_PakRouter->getWorking(id, silenceWarnings); return pakRouter->getWorking(id, silenceWarnings);
} }
static hecl::ProjectPath MakePathFromString(const std::string& str) static hecl::ProjectPath MakePathFromString(const std::string& str)
{ {
if (!s_Project) hecl::Database::Project* project = s_Project.get();
if (!project)
LogDNACommon.report(logvisor::Fatal, LogDNACommon.report(logvisor::Fatal,
"UniqueIDBridge::setGlobalProject must be called before MakePathFromString"); "UniqueIDBridge::setGlobalProject must be called before MakePathFromString");
return hecl::ProjectPath(*s_Project, str); return hecl::ProjectPath(*project, str);
} }
template <class IDType> template <class IDType>
static void TransformOldHashToNewHash(IDType& id) static void TransformOldHashToNewHash(IDType& id)
@ -109,7 +112,7 @@ public:
static void setGlobalProject(hecl::Database::Project& project) static void setGlobalProject(hecl::Database::Project& project)
{ {
s_Project = &project; s_Project.reset(&project);
} }
}; };

View File

@ -224,7 +224,7 @@ void PAKRouter<BRIDGETYPE>::build(std::vector<BRIDGETYPE>& bridges, std::functio
template <class BRIDGETYPE> template <class BRIDGETYPE>
void PAKRouter<BRIDGETYPE>::enterPAKBridge(const BRIDGETYPE& pakBridge) void PAKRouter<BRIDGETYPE>::enterPAKBridge(const BRIDGETYPE& pakBridge)
{ {
g_PakRouter = this; g_PakRouter.reset(this);
auto pit = m_bridgePaths.begin(); auto pit = m_bridgePaths.begin();
size_t bridgeIdx = 0; size_t bridgeIdx = 0;
for (const BRIDGETYPE& bridge : *m_bridges) for (const BRIDGETYPE& bridge : *m_bridges)

View File

@ -2,6 +2,8 @@
namespace DataSpec namespace DataSpec
{ {
extern hecl::Database::DataSpecEntry SpecEntMP1PC;
namespace DNAMP1 namespace DNAMP1
{ {
@ -1005,6 +1007,255 @@ const char* ANCS::AnimationSet::DNAType()
return "urde::DNAMP1::ANCS::AnimationSet"; return "urde::DNAMP1::ANCS::AnimationSet";
} }
bool ANCS::Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const hecl::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
bool force,
hecl::BlenderToken& btok,
std::function<void(const hecl::SystemChar*)> fileChanged)
{
hecl::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
hecl::ProjectPath::Type yamlType = yamlPath.getPathType();
hecl::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
hecl::ProjectPath::Type blendType = blendPath.getPathType();
ANCS ancs;
ancs.read(rs);
if (force ||
yamlType == hecl::ProjectPath::Type::None ||
blendType == hecl::ProjectPath::Type::None)
{
if (force || yamlType == hecl::ProjectPath::Type::None)
{
FILE* fp = hecl::Fopen(yamlPath.getAbsolutePath().c_str(), _S("w"));
ancs.toYAMLFile(fp);
fclose(fp);
}
if (force || blendType == hecl::ProjectPath::Type::None)
{
hecl::BlenderConnection& conn = btok.getBlenderConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
}
}
/* Extract EVNTs */
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animRes;
ancs.getAnimationResInfo(animRes);
for (const auto& res : animRes)
{
if (res.second.evntId)
{
hecl::SystemStringView sysStr(res.second.name);
hecl::ProjectPath evntYamlPath = outPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str());
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
if (force || evntYamlType == hecl::ProjectPath::Type::None)
{
EVNT evnt;
if (pakRouter.lookupAndReadDNA(res.second.evntId, evnt, true))
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("w"));
evnt.toYAMLFile(fp);
fclose(fp);
}
}
}
}
return true;
}
bool ANCS::Cook(const hecl::ProjectPath& outPath,
const hecl::ProjectPath& inPath,
const DNAANCS::Actor& actor,
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
{
/* Search for yaml */
hecl::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true);
if (yamlPath.getPathType() != hecl::ProjectPath::Type::File)
Log.report(logvisor::Fatal, _S("'%s' not found as file"),
yamlPath.getRelativePath().c_str());
athena::io::FileReader yamlReader(yamlPath.getAbsolutePath());
if (!BigYAML::ValidateFromYAMLFile<ANCS>(yamlReader))
Log.report(logvisor::Fatal, _S("'%s' is not urde::DNAMP1::ANCS type"),
yamlPath.getRelativePath().c_str());
ANCS ancs;
ancs.read(yamlReader);
/* Set Character Resource IDs */
for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters)
{
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(ch.cmdl);
if (path)
ch.cskr = path.ensureAuxInfo(_S("skin"));
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
{
if (!sub.name.compare(ch.name))
{
if (sub.armature >= 0)
{
const DNAANCS::Actor::Armature& arm = actor.armatures[sub.armature];
hecl::SystemStringView chSysName(arm.name);
ch.cinf = inPath.ensureAuxInfo(chSysName.c_str());
break;
}
}
}
path = UniqueIDBridge::TranslatePakIdToPath(ch.cmdlOverlay);
if (path)
ch.cskrOverlay = path.ensureAuxInfo(_S("skin"));
}
/* Set Animation Resource IDs */
ancs.enumeratePrimitives([&](AnimationSet::MetaAnimPrimitive& prim) -> bool
{
hecl::SystemStringView sysStr(prim.animName);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
prim.animId = pathOut;
return true;
});
std::unordered_map<std::string, atInt32> boneIdMap;
/* Write out CINF resources */
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
{
hecl::SystemStringView sysStr(arm.name);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
CINF cinf(arm, boneIdMap);
cinf.write(w);
}
/* Write out CSKR resources */
for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters)
{
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(ch.cmdl);
if (path.getPathType() != hecl::ProjectPath::Type::File)
Log.report(logvisor::Fatal, _S("unable to resolve '%s'"), path.getRelativePath().c_str());
hecl::ProjectPath skinIntPath = path.getCookedPath(SpecEntMP1PC).getWithExtension(_S(".skinint"));
if (skinIntPath.getModtime() < path.getModtime())
if (!modelCookFunc(path))
Log.report(logvisor::Fatal, _S("unable to cook '%s'"), path.getRelativePath().c_str());
athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
if (skinIO.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s'"), skinIntPath.getRelativePath().c_str());
std::vector<std::vector<uint32_t>> skinBanks;
uint32_t bankCount = skinIO.readUint32Big();
skinBanks.reserve(bankCount);
for (uint32_t i=0 ; i<bankCount ; ++i)
{
skinBanks.emplace_back();
std::vector<uint32_t>& bonesOut = skinBanks.back();
uint32_t boneCount = skinIO.readUint32Big();
bonesOut.reserve(boneCount);
for (uint32_t j=0 ; j<boneCount ; ++j)
{
uint32_t idx = skinIO.readUint32Big();
bonesOut.push_back(idx);
}
}
std::vector<std::string> boneNames;
uint32_t boneNameCount = skinIO.readUint32Big();
boneNames.reserve(boneNameCount);
for (uint32_t i=0 ; i<boneNameCount ; ++i)
boneNames.push_back(skinIO.readString());
skinIO.close();
hecl::ProjectPath skinPath = path.getCookedPath(SpecEntMP1PC).getWithExtension(_S(".skin"));
athena::io::FileWriter skinOut(skinPath.getAbsolutePath(), true, false);
if (skinOut.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
skinPath.getRelativePath().c_str());
skinOut.writeUint32Big(bankCount);
for (const std::vector<uint32_t>& bank : skinBanks)
{
skinOut.writeUint32Big(bank.size());
for (uint32_t bIdx : bank)
{
const std::string& name = boneNames[bIdx];
auto search = boneIdMap.find(name);
if (search == boneIdMap.cend())
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s",
name.c_str(), inPath.getRelativePathUTF8().c_str());
skinOut.writeUint32Big(search->second);
}
}
}
/* Write out ANIM resources */
ancs.animationSet.animResources.reserve(actor.actions.size());
for (const DNAANCS::Actor::Action& act : actor.actions)
{
hecl::SystemStringView sysStr(act.name);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
ANIM anim(act, boneIdMap);
ancs.animationSet.animResources.emplace_back();
ancs.animationSet.animResources.back().animId = pathOut;
/* Check for associated EVNT YAML */
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str(), true);
if (evntYamlPath.getPathType() == hecl::ProjectPath::Type::File)
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("r"));
if (fp)
{
EVNT evnt;
evnt.fromYAMLFile(fp);
fclose(fp);
anim.m_anim->evnt = evntYamlPath;
hecl::ProjectPath evntYamlOut = pathOut.getWithExtension(_S(".evnt"));
athena::io::FileWriter w(evntYamlOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
evntYamlOut.getRelativePath().c_str());
evnt.write(w);
ancs.animationSet.animResources.back().evntId = evntYamlPath;
}
}
anim.write(w);
}
/* Write out ANCS */
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
outPath.getRelativePath().c_str());
ancs.write(w);
return true;
}
} }
} }

View File

@ -534,183 +534,12 @@ struct ANCS : BigYAML
const PAK::Entry& entry, const PAK::Entry& entry,
bool force, bool force,
hecl::BlenderToken& btok, hecl::BlenderToken& btok,
std::function<void(const hecl::SystemChar*)> fileChanged) std::function<void(const hecl::SystemChar*)> fileChanged);
{
hecl::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
hecl::ProjectPath::Type yamlType = yamlPath.getPathType();
hecl::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
hecl::ProjectPath::Type blendType = blendPath.getPathType();
ANCS ancs;
ancs.read(rs);
if (force ||
yamlType == hecl::ProjectPath::Type::None ||
blendType == hecl::ProjectPath::Type::None)
{
if (force || yamlType == hecl::ProjectPath::Type::None)
{
FILE* fp = hecl::Fopen(yamlPath.getAbsolutePath().c_str(), _S("w"));
ancs.toYAMLFile(fp);
fclose(fp);
}
if (force || blendType == hecl::ProjectPath::Type::None)
{
hecl::BlenderConnection& conn = btok.getBlenderConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
}
}
/* Extract EVNTs */
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animRes;
ancs.getAnimationResInfo(animRes);
for (const auto& res : animRes)
{
if (res.second.evntId)
{
hecl::SystemStringView sysStr(res.second.name);
hecl::ProjectPath evntYamlPath = outPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str());
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
if (force || evntYamlType == hecl::ProjectPath::Type::None)
{
EVNT evnt;
if (pakRouter.lookupAndReadDNA(res.second.evntId, evnt, true))
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("w"));
evnt.toYAMLFile(fp);
fclose(fp);
}
}
}
}
return true;
}
static bool Cook(const hecl::ProjectPath& outPath, static bool Cook(const hecl::ProjectPath& outPath,
const hecl::ProjectPath& inPath, const hecl::ProjectPath& inPath,
const DNAANCS::Actor& actor) const DNAANCS::Actor& actor,
{ const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
/* Search for yaml */
hecl::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true);
if (yamlPath.getPathType() != hecl::ProjectPath::Type::File)
Log.report(logvisor::Fatal, _S("'%s' not found as file"),
yamlPath.getRelativePath().c_str());
athena::io::FileReader yamlReader(yamlPath.getAbsolutePath());
if (!BigYAML::ValidateFromYAMLFile<ANCS>(yamlReader))
Log.report(logvisor::Fatal, _S("'%s' is not urde::DNAMP1::ANCS type"),
yamlPath.getRelativePath().c_str());
ANCS ancs;
ancs.read(yamlReader);
/* Set Character Resource IDs */
for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters)
{
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(ch.cmdl);
if (path)
ch.cskr = path.ensureAuxInfo(_S("skin"));
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
{
if (!sub.name.compare(ch.name))
{
if (sub.armature >= 0)
{
const DNAANCS::Actor::Armature& arm = actor.armatures[sub.armature];
hecl::SystemStringView chSysName(arm.name);
ch.cinf = inPath.ensureAuxInfo(chSysName.c_str());
break;
}
}
}
path = UniqueIDBridge::TranslatePakIdToPath(ch.cmdlOverlay);
if (path)
ch.cskrOverlay = path.ensureAuxInfo(_S("skin"));
}
/* Set Animation Resource IDs */
ancs.enumeratePrimitives([&](AnimationSet::MetaAnimPrimitive& prim) -> bool
{
hecl::SystemStringView sysStr(prim.animName);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
prim.animId = pathOut;
return true;
});
std::unordered_map<std::string, atInt32> boneIdMap;
/* Write out CINF resources */
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
{
hecl::SystemStringView sysStr(arm.name);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
CINF cinf(arm, boneIdMap);
cinf.write(w);
}
/* Write out ANIM resources */
ancs.animationSet.animResources.reserve(actor.actions.size());
for (const DNAANCS::Actor::Action& act : actor.actions)
{
hecl::SystemStringView sysStr(act.name);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
ANIM anim(act, boneIdMap);
ancs.animationSet.animResources.emplace_back();
ancs.animationSet.animResources.back().animId = pathOut;
/* Check for associated EVNT YAML */
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str(), true);
if (evntYamlPath.getPathType() == hecl::ProjectPath::Type::File)
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("r"));
if (fp)
{
EVNT evnt;
evnt.fromYAMLFile(fp);
fclose(fp);
anim.m_anim->evnt = evntYamlPath;
hecl::ProjectPath evntYamlOut = pathOut.getWithExtension(_S(".evnt"));
athena::io::FileWriter w(evntYamlOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
evntYamlOut.getRelativePath().c_str());
evnt.write(w);
ancs.animationSet.animResources.back().evntId = evntYamlPath;
}
}
anim.write(w);
}
/* Write out ANCS */
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
outPath.getRelativePath().c_str());
ancs.write(w);
return true;
}
}; };
} }

View File

@ -94,7 +94,7 @@ struct CMDL
/* Output skinning intermediate */ /* Output skinning intermediate */
auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin(); auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin();
athena::io::FileWriter writer(outPath.getWithExtension(_S(".skin")).getAbsolutePath()); athena::io::FileWriter writer(outPath.getWithExtension(_S(".skinint")).getAbsolutePath());
writer.writeUint32Big(skinMesh.skins.size()); writer.writeUint32Big(skinMesh.skins.size());
for (const std::vector<DNACMDL::Mesh::SkinBind> skin : skinMesh.skins) for (const std::vector<DNACMDL::Mesh::SkinBind> skin : skinMesh.skins)
{ {
@ -126,7 +126,7 @@ struct CMDL
return false; return false;
/* Output skinning intermediate */ /* Output skinning intermediate */
athena::io::FileWriter writer(outPath.getWithExtension(_S(".skin")).getAbsolutePath()); athena::io::FileWriter writer(outPath.getWithExtension(_S(".skinint")).getAbsolutePath());
writer.writeUint32Big(mesh.skinBanks.banks.size()); writer.writeUint32Big(mesh.skinBanks.banks.size());
for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks) for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks)
{ {

View File

@ -93,7 +93,7 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
void SpecBase::doExtract(const ExtractPassInfo& info, FProgress progress) void SpecBase::doExtract(const ExtractPassInfo& info, FProgress progress)
{ {
DataSpec::g_curSpec = this; DataSpec::g_curSpec.reset(this);
if (!Blender::BuildMasterShader(m_masterShader)) if (!Blender::BuildMasterShader(m_masterShader))
Log.report(logvisor::Fatal, "Unable to build master shader blend"); Log.report(logvisor::Fatal, "Unable to build master shader blend");
if (m_isWii) if (m_isWii)
@ -173,7 +173,7 @@ const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::Proj
void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath,
bool fast, hecl::BlenderToken& btok, FCookProgress progress) bool fast, hecl::BlenderToken& btok, FCookProgress progress)
{ {
DataSpec::g_curSpec = this; DataSpec::g_curSpec.reset(this);
if (hecl::IsPathBlend(path)) if (hecl::IsPathBlend(path))
{ {
hecl::BlenderConnection& conn = btok.getBlenderConnection(); hecl::BlenderConnection& conn = btok.getBlenderConnection();
@ -184,19 +184,19 @@ void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& co
case hecl::BlenderConnection::BlendType::Mesh: case hecl::BlenderConnection::BlendType::Mesh:
{ {
hecl::BlenderConnection::DataStream ds = conn.beginData(); hecl::BlenderConnection::DataStream ds = conn.beginData();
cookMesh(cookedPath, path, ds, fast, progress); cookMesh(cookedPath, path, ds, fast, btok, progress);
break; break;
} }
case hecl::BlenderConnection::BlendType::Actor: case hecl::BlenderConnection::BlendType::Actor:
{ {
hecl::BlenderConnection::DataStream ds = conn.beginData(); hecl::BlenderConnection::DataStream ds = conn.beginData();
cookActor(cookedPath, path, ds, fast, progress); cookActor(cookedPath, path, ds, fast, btok, progress);
break; break;
} }
case hecl::BlenderConnection::BlendType::Area: case hecl::BlenderConnection::BlendType::Area:
{ {
hecl::BlenderConnection::DataStream ds = conn.beginData(); hecl::BlenderConnection::DataStream ds = conn.beginData();
cookArea(cookedPath, path, ds, fast, progress); cookArea(cookedPath, path, ds, fast, btok, progress);
break; break;
} }
default: break; default: break;

View File

@ -56,13 +56,16 @@ struct SpecBase : hecl::Database::IDataSpec
using Actor = BlendStream::Actor; using Actor = BlendStream::Actor;
virtual void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, virtual void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const=0; BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)=0;
virtual void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, virtual void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const=0; BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)=0;
virtual void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, virtual void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const=0; BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)=0;
virtual void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, virtual void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
FILE* fin, FCookProgress progress) const=0; FILE* fin, FCookProgress progress)=0;
const hecl::ProjectPath& getMasterShaderPath() const {return m_masterShader;} const hecl::ProjectPath& getMasterShaderPath() const {return m_masterShader;}

View File

@ -23,6 +23,7 @@ namespace DataSpec
static logvisor::Module Log("urde::SpecMP1"); static logvisor::Module Log("urde::SpecMP1");
extern hecl::Database::DataSpecEntry SpecEntMP1; extern hecl::Database::DataSpecEntry SpecEntMP1;
extern hecl::Database::DataSpecEntry SpecEntMP1PC;
struct SpecMP1 : SpecBase struct SpecMP1 : SpecBase
{ {
@ -343,7 +344,8 @@ struct SpecMP1 : SpecBase
} }
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
Mesh mesh = ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, Mesh mesh = ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1,
[&progress](int surfCount) [&progress](int surfCount)
@ -358,19 +360,31 @@ struct SpecMP1 : SpecBase
} }
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
Actor actor = ds.compileActor(); Actor actor = ds.compileActor();
DNAMP1::ANCS::Cook(out, in, actor); DNAMP1::ANCS::Cook(out, in, actor,
[&](const hecl::ProjectPath& modelPath) -> bool
{
hecl::ProjectPath cooked;
if (m_pc)
cooked = modelPath.getCookedPath(SpecEntMP1PC);
else
cooked = modelPath.getCookedPath(SpecEntMP1);
doCook(modelPath, cooked, fast, btok, progress);
return true;
});
} }
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
FILE* fin, FCookProgress progress) const FILE* fin, FCookProgress progress)
{ {
athena::io::YAMLDocReader reader; athena::io::YAMLDocReader reader;
yaml_parser_set_input_file(reader.getParser(), fin); yaml_parser_set_input_file(reader.getParser(), fin);

View File

@ -295,22 +295,25 @@ struct SpecMP2 : SpecBase
} }
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
FILE* fin, FCookProgress progress) const FILE* fin, FCookProgress progress)
{ {
} }
}; };

View File

@ -490,22 +490,25 @@ struct SpecMP3 : SpecBase
} }
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
BlendStream& ds, bool fast, FCookProgress progress) const BlendStream& ds, bool fast, hecl::BlenderToken& btok,
FCookProgress progress)
{ {
} }
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
FILE* fin, FCookProgress progress) const FILE* fin, FCookProgress progress)
{ {
} }
}; };

View File

@ -0,0 +1,15 @@
#include "CAnimCharacterSet.hpp"
#include "CToken.hpp"
namespace urde
{
CAnimCharacterSet::CAnimCharacterSet(CInputStream& in)
: x0_version(in.readUint16Big()), x4_characterSet(in), x1c_animationSet(in) {}
CFactoryFnReturn FAnimCharacterSet(const SObjectTag&, CInputStream& in, const CVParamTransfer&)
{
return TToken<CAnimCharacterSet>::GetIObjObjectFor(std::make_unique<CAnimCharacterSet>(in));
}
}

View File

@ -0,0 +1,24 @@
#ifndef __PSHAG_CANIMCHARACTERSET_HPP__
#define __PSHAG_CANIMCHARACTERSET_HPP__
#include "CFactoryMgr.hpp"
#include "CCharacterSet.hpp"
#include "CAnimationSet.hpp"
namespace urde
{
class CAnimCharacterSet
{
u16 x0_version;
CCharacterSet x4_characterSet;
CAnimationSet x1c_animationSet;
public:
CAnimCharacterSet(CInputStream& in);
};
CFactoryFnReturn FAnimCharacterSet(const SObjectTag&, CInputStream&, const CVParamTransfer&);
}
#endif // __PSHAG_CANIMCHARACTERSET_HPP__

View File

View File

@ -0,0 +1,17 @@
#ifndef __PSHAG_CANIMATIONSET_HPP__
#define __PSHAG_CANIMATIONSET_HPP__
#include "IOStreams.hpp"
namespace urde
{
class CAnimationSet
{
public:
CAnimationSet(CInputStream& in);
};
}
#endif // __PSHAG_CANIMATIONSET_HPP__

View File

@ -0,0 +1,32 @@
#include "CCharacterInfo.hpp"
namespace urde
{
static std::vector<std::pair<u32, std::pair<std::string, std::string>>>
MakeAnimInfoVector(CInputStream& in)
{
std::vector<std::pair<u32, std::pair<std::string, std::string>>> ret;
u32 animInfoCount = in.readUint32Big();
ret.reserve(animInfoCount);
for (u32 i=0 ; i<animInfoCount ; ++i)
{
u32 idx = in.readUint32Big();
std::string a = in.readString();
std::string b = in.readString();
ret.emplace_back(idx, std::make_pair(a, b));
}
return ret;
}
CCharacterInfo::CCharacterInfo(CInputStream& in)
: x0_tableCount(in.readUint16Big()),
x4_name(in.readString()),
x14_cmdl(in.readUint32Big()),
x18_cskr(in.readUint32Big()),
x1c_cinf(in.readUint32Big()),
x20_animInfo(MakeAnimInfoVector(in)),
x30_pasDatabase(in)
{}
}

View File

@ -0,0 +1,26 @@
#ifndef __PSHAG_CCHARACTERINFO_HPP__
#define __PSHAG_CCHARACTERINFO_HPP__
#include "IOStreams.hpp"
#include "CPASDatabase.hpp"
namespace urde
{
class CCharacterInfo
{
u16 x0_tableCount;
std::string x4_name;
TResId x14_cmdl;
TResId x18_cskr;
TResId x1c_cinf;
std::vector<std::pair<u32, std::pair<std::string, std::string>>> x20_animInfo;
CPASDatabase x30_pasDatabase;
public:
CCharacterInfo(CInputStream& in);
};
}
#endif // __PSHAG_CCHARACTERINFO_HPP__

View File

@ -0,0 +1,17 @@
#include "CCharacterSet.hpp"
namespace urde
{
CCharacterSet::CCharacterSet(CInputStream& in)
: x0_version(in.readUint16Big())
{
u32 charCount = in.readUint32Big();
for (u32 i=0 ; i<charCount ; ++i)
{
u32 id = in.readUint32Big();
x4_characters.emplace(id, in);
}
}
}

View File

@ -0,0 +1,20 @@
#ifndef __PSHAG_CCHARACTERSET_HPP__
#define __PSHAG_CCHARACTERSET_HPP__
#include "IOStreams.hpp"
#include "CCharacterInfo.hpp"
namespace urde
{
class CCharacterSet
{
u16 x0_version;
std::map<u32, CCharacterInfo> x4_characters;
public:
CCharacterSet(CInputStream& in);
};
}
#endif // __PSHAG_CCHARACTERSET_HPP__

View File

@ -16,4 +16,13 @@ add_library(RuntimeCommonCharacter
CSegIdList.hpp CSegIdList.cpp CSegIdList.hpp CSegIdList.cpp
CSegId.hpp CSegId.cpp CSegId.hpp CSegId.cpp
CSkinRules.hpp CSkinRules.cpp CSkinRules.hpp CSkinRules.cpp
CAnimCharacterSet.hpp CAnimCharacterSet.cpp
CAnimationSet.hpp CAnimationSet.cpp
CCharacterSet.hpp CCharacterSet.cpp
CCharacterInfo.hpp CCharacterInfo.cpp
CPASDatabase.hpp CPASDatabase.cpp
CPASAnimState.hpp CPASAnimState.cpp
CPASParmInfo.hpp CPASParmInfo.cpp
CPASAnimInfo.hpp CPASAnimInfo.cpp
CPASAnimParm.hpp CPASAnimParm.cpp
CBodyState.hpp) CBodyState.hpp)

View File

@ -0,0 +1,9 @@
#include "CPASAnimInfo.hpp"
namespace urde
{
CPASAnimInfo::CPASAnimInfo(u32 id, rstl::reserved_vector<CPASAnimParm::UParmValue, 8>&& parms)
: x0_id(id), x4_parms(std::move(parms)) {}
}

View File

@ -0,0 +1,22 @@
#ifndef __PSHAG_CPASANIMINFO_HPP__
#define __PSHAG_CPASANIMINFO_HPP__
#include "IOStreams.hpp"
#include "rstl.hpp"
#include "CPASAnimParm.hpp"
namespace urde
{
class CPASAnimInfo
{
u32 x0_id;
rstl::reserved_vector<CPASAnimParm::UParmValue, 8> x4_parms;
public:
CPASAnimInfo(u32 id, rstl::reserved_vector<CPASAnimParm::UParmValue, 8>&& parms);
u32 GetId() const {return x0_id;}
};
}
#endif // __PSHAG_CPASANIMINFO_HPP__

View File

View File

@ -0,0 +1,86 @@
#ifndef __PSHAG_CPASANIMPARM_HPP__
#define __PSHAG_CPASANIMPARM_HPP__
#include "RetroTypes.hpp"
namespace urde
{
class CPASAnimParm
{
public:
enum class EParmType
{
None = -1,
Int32 = 0,
UInt32 = 1,
Float = 2,
Bool = 3,
Enum = 4
};
union UParmValue
{
s32 m_int;
u32 m_uint;
float m_float;
bool m_bool;
};
private:
UParmValue x0_value;
EParmType x4_type;
public:
CPASAnimParm(UParmValue val, EParmType tp) : x4_type(tp), x0_value(val) {}
s32 GetEnumValue() const {return x0_value.m_int;}
bool GetBoolValue() const {return x0_value.m_bool;}
float GetReal32Value() const {return x0_value.m_float;}
u32 GetUint32Value() const {return x0_value.m_uint;}
s32 GetInt32Value() const {return x0_value.m_int;}
static CPASAnimParm FromEnum(s32 val)
{
UParmValue valin;
valin.m_int = val;
return CPASAnimParm(valin, EParmType::Enum);
}
static CPASAnimParm FromBool(bool val)
{
UParmValue valin;
valin.m_bool = val;
return CPASAnimParm(valin, EParmType::Bool);
}
static CPASAnimParm FromReal32(float val)
{
UParmValue valin;
valin.m_float = val;
return CPASAnimParm(valin, EParmType::Float);
}
static CPASAnimParm FromUint32(u32 val)
{
UParmValue valin;
valin.m_uint = val;
return CPASAnimParm(valin, EParmType::UInt32);
}
static CPASAnimParm FromInt32(s32 val)
{
UParmValue valin;
valin.m_int = val;
return CPASAnimParm(valin, EParmType::Int32);
}
static CPASAnimParm NoParameter()
{
UParmValue valin;
valin.m_int = -1;
return CPASAnimParm(valin, EParmType::None);
}
};
}
#endif // __PSHAG_CPASANIMPARM_HPP__

View File

@ -0,0 +1,54 @@
#include "CPASAnimState.hpp"
namespace urde
{
CPASAnimState::CPASAnimState(CInputStream& in)
{
x0_id = in.readUint32Big();
u32 parmCount = in.readUint32Big();
u32 animCount = in.readUint32Big();
x4_parms.reserve(parmCount);
x14_anims.reserve(animCount);
x24_.reserve(animCount);
for (u32 i=0 ; i<parmCount ; ++i)
x4_parms.emplace_back(in);
for (u32 i=0 ; i<animCount ; ++i)
{
u32 id = in.readUint32Big();
rstl::reserved_vector<CPASAnimParm::UParmValue, 8> parms;
for (const CPASParmInfo& parm : x4_parms)
{
CPASAnimParm::UParmValue val = {};
switch (parm.GetType())
{
case CPASAnimParm::EParmType::Int32:
val.m_int = in.readInt32Big();
break;
case CPASAnimParm::EParmType::UInt32:
val.m_uint = in.readUint32Big();
break;
case CPASAnimParm::EParmType::Float:
val.m_float = in.readFloatBig();
break;
case CPASAnimParm::EParmType::Bool:
val.m_bool = in.readBool();
break;
case CPASAnimParm::EParmType::Enum:
val.m_int = in.readInt32Big();
break;
default: break;
}
parms.push_back(val);
}
auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id,
[](const CPASAnimInfo& item, const u32& testId) -> bool {return item.GetId() < testId;});
x14_anims.emplace(search, id, std::move(parms));
}
}
}

View File

@ -0,0 +1,24 @@
#ifndef __PSHAG_CPASANIMSTATE_HPP__
#define __PSHAG_CPASANIMSTATE_HPP__
#include "IOStreams.hpp"
#include "CPASParmInfo.hpp"
#include "CPASAnimInfo.hpp"
namespace urde
{
class CPASAnimState
{
u32 x0_id;
std::vector<CPASParmInfo> x4_parms;
std::vector<CPASAnimInfo> x14_anims;
std::vector<u32> x24_;
public:
CPASAnimState(CInputStream& in);
u32 GetId() const {return x0_id;}
};
}
#endif // __PSHAG_CPASANIMSTATE_HPP__

View File

@ -0,0 +1,30 @@
#include "CPASDatabase.hpp"
namespace urde
{
void CPASDatabase::AddAnimState(CPASAnimState&& state)
{
auto it = std::lower_bound(x0_states.begin(), x0_states.end(), state,
[](const CPASAnimState& item, const CPASAnimState& test) -> bool {return item.GetId() < test.GetId();});
x0_states.insert(it, std::move(state));
}
CPASDatabase::CPASDatabase(CInputStream& in)
{
in.readUint32Big();
u32 animStateCount = in.readUint32Big();
u32 defaultState = in.readUint32Big();
x0_states.reserve(animStateCount);
for (u32 i=0 ; i<animStateCount ; ++i)
{
CPASAnimState state(in);
AddAnimState(std::move(state));
}
if (animStateCount)
SetDefaultState(defaultState);
}
}

View File

@ -0,0 +1,22 @@
#ifndef __PSHAG_CPASDATABASE_HPP__
#define __PSHAG_CPASDATABASE_HPP__
#include "IOStreams.hpp"
#include "CPASAnimState.hpp"
namespace urde
{
class CPASDatabase
{
std::vector<CPASAnimState> x0_states;
u32 x10_defaultState;
void AddAnimState(CPASAnimState&& state);
void SetDefaultState(u32 state) {x10_defaultState = state;}
public:
CPASDatabase(CInputStream& in);
};
}
#endif // __PSHAG_CPASDATABASE_HPP__

View File

@ -0,0 +1,40 @@
#include "CPASParmInfo.hpp"
namespace urde
{
CPASParmInfo::CPASParmInfo(CInputStream& in)
{
xc_val1.m_int = 0;
x10_val2.m_int = 0;
x0_type = CPASAnimParm::EParmType(in.readUint32Big());
x4_unk1 = in.readUint32Big();
x8_unk2 = in.readFloatBig();
switch (x0_type)
{
case CPASAnimParm::EParmType::Int32:
xc_val1.m_int = in.readInt32Big();
x10_val2.m_int = in.readInt32Big();
break;
case CPASAnimParm::EParmType::UInt32:
xc_val1.m_uint = in.readUint32Big();
x10_val2.m_uint = in.readUint32Big();
break;
case CPASAnimParm::EParmType::Float:
xc_val1.m_float = in.readFloatBig();
x10_val2.m_float = in.readFloatBig();
break;
case CPASAnimParm::EParmType::Bool:
xc_val1.m_bool = in.readBool();
x10_val2.m_bool = in.readBool();
break;
case CPASAnimParm::EParmType::Enum:
xc_val1.m_int = in.readInt32Big();
x10_val2.m_int = in.readInt32Big();
break;
default: break;
}
}
}

View File

@ -0,0 +1,24 @@
#ifndef __PSHAG_CPASPARMINFO_HPP__
#define __PSHAG_CPASPARMINFO_HPP__
#include "IOStreams.hpp"
#include "CPASAnimParm.hpp"
namespace urde
{
class CPASParmInfo
{
CPASAnimParm::EParmType x0_type;
u32 x4_unk1;
float x8_unk2;
CPASAnimParm::UParmValue xc_val1;
CPASAnimParm::UParmValue x10_val2;
public:
CPASParmInfo(CInputStream& in);
CPASAnimParm::EParmType GetType() const {return x0_type;}
};
}
#endif // __PSHAG_CPASPARMINFO_HPP__