mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 15:47:46 +00:00
Merge branch 'master' of https://github.com/AxioDL/urde
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
#include "DNACommon.hpp"
|
||||
#include "PAK.hpp"
|
||||
#include "boo/ThreadLocalPtr.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
logvisor::Module LogDNACommon("urde::DNACommon");
|
||||
SpecBase* g_curSpec = nullptr;
|
||||
PAKRouterBase* g_PakRouter = nullptr;
|
||||
hecl::Database::Project* UniqueIDBridge::s_Project = nullptr;
|
||||
ThreadLocalPtr<SpecBase> g_curSpec;
|
||||
ThreadLocalPtr<PAKRouterBase> g_PakRouter;
|
||||
ThreadLocalPtr<hecl::Database::Project> UniqueIDBridge::s_Project;
|
||||
UniqueID32 UniqueID32::kInvalidId;
|
||||
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
#include "hecl/hecl.hpp"
|
||||
#include "hecl/Database.hpp"
|
||||
#include "../SpecBase.hpp"
|
||||
#include "boo/ThreadLocalPtr.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
|
||||
extern logvisor::Module LogDNACommon;
|
||||
extern SpecBase* g_curSpec;
|
||||
extern class PAKRouterBase* g_PakRouter;
|
||||
extern ThreadLocalPtr<SpecBase> g_curSpec;
|
||||
extern ThreadLocalPtr<class PAKRouterBase> g_PakRouter;
|
||||
|
||||
/* This comes up a great deal */
|
||||
typedef athena::io::DNA<athena::BigEndian> BigDNA;
|
||||
@@ -84,22 +85,24 @@ class UniqueIDBridge
|
||||
friend class UniqueID32;
|
||||
friend class UniqueID64;
|
||||
|
||||
static hecl::Database::Project* s_Project;
|
||||
static ThreadLocalPtr<hecl::Database::Project> s_Project;
|
||||
public:
|
||||
template <class IDType>
|
||||
static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings=false)
|
||||
{
|
||||
if (!g_PakRouter)
|
||||
PAKRouterBase* pakRouter = g_PakRouter.get();
|
||||
if (!pakRouter)
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"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)
|
||||
{
|
||||
if (!s_Project)
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project)
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"UniqueIDBridge::setGlobalProject must be called before MakePathFromString");
|
||||
return hecl::ProjectPath(*s_Project, str);
|
||||
return hecl::ProjectPath(*project, str);
|
||||
}
|
||||
template <class IDType>
|
||||
static void TransformOldHashToNewHash(IDType& id)
|
||||
@@ -109,7 +112,7 @@ public:
|
||||
|
||||
static void setGlobalProject(hecl::Database::Project& project)
|
||||
{
|
||||
s_Project = &project;
|
||||
s_Project.reset(&project);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ void PAKRouter<BRIDGETYPE>::build(std::vector<BRIDGETYPE>& bridges, std::functio
|
||||
template <class BRIDGETYPE>
|
||||
void PAKRouter<BRIDGETYPE>::enterPAKBridge(const BRIDGETYPE& pakBridge)
|
||||
{
|
||||
g_PakRouter = this;
|
||||
g_PakRouter.reset(this);
|
||||
auto pit = m_bridgePaths.begin();
|
||||
size_t bridgeIdx = 0;
|
||||
for (const BRIDGETYPE& bridge : *m_bridges)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
extern hecl::Database::DataSpecEntry SpecEntMP1PC;
|
||||
|
||||
namespace DNAMP1
|
||||
{
|
||||
|
||||
@@ -1005,6 +1007,255 @@ const char* ANCS::AnimationSet::DNAType()
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -534,183 +534,12 @@ struct ANCS : BigYAML
|
||||
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;
|
||||
}
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ struct CMDL
|
||||
|
||||
/* Output skinning intermediate */
|
||||
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());
|
||||
for (const std::vector<DNACMDL::Mesh::SkinBind> skin : skinMesh.skins)
|
||||
{
|
||||
@@ -126,7 +126,7 @@ struct CMDL
|
||||
return false;
|
||||
|
||||
/* 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());
|
||||
for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks)
|
||||
{
|
||||
|
||||
@@ -93,7 +93,7 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
|
||||
|
||||
void SpecBase::doExtract(const ExtractPassInfo& info, FProgress progress)
|
||||
{
|
||||
DataSpec::g_curSpec = this;
|
||||
DataSpec::g_curSpec.reset(this);
|
||||
if (!Blender::BuildMasterShader(m_masterShader))
|
||||
Log.report(logvisor::Fatal, "Unable to build master shader blend");
|
||||
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,
|
||||
bool fast, hecl::BlenderToken& btok, FCookProgress progress)
|
||||
{
|
||||
DataSpec::g_curSpec = this;
|
||||
DataSpec::g_curSpec.reset(this);
|
||||
if (hecl::IsPathBlend(path))
|
||||
{
|
||||
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:
|
||||
{
|
||||
hecl::BlenderConnection::DataStream ds = conn.beginData();
|
||||
cookMesh(cookedPath, path, ds, fast, progress);
|
||||
cookMesh(cookedPath, path, ds, fast, btok, progress);
|
||||
break;
|
||||
}
|
||||
case hecl::BlenderConnection::BlendType::Actor:
|
||||
{
|
||||
hecl::BlenderConnection::DataStream ds = conn.beginData();
|
||||
cookActor(cookedPath, path, ds, fast, progress);
|
||||
cookActor(cookedPath, path, ds, fast, btok, progress);
|
||||
break;
|
||||
}
|
||||
case hecl::BlenderConnection::BlendType::Area:
|
||||
{
|
||||
hecl::BlenderConnection::DataStream ds = conn.beginData();
|
||||
cookArea(cookedPath, path, ds, fast, progress);
|
||||
cookArea(cookedPath, path, ds, fast, btok, progress);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
||||
@@ -56,13 +56,16 @@ struct SpecBase : hecl::Database::IDataSpec
|
||||
using Actor = BlendStream::Actor;
|
||||
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
FILE* fin, FCookProgress progress) const=0;
|
||||
FILE* fin, FCookProgress progress)=0;
|
||||
|
||||
const hecl::ProjectPath& getMasterShaderPath() const {return m_masterShader;}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace DataSpec
|
||||
|
||||
static logvisor::Module Log("urde::SpecMP1");
|
||||
extern hecl::Database::DataSpecEntry SpecEntMP1;
|
||||
extern hecl::Database::DataSpecEntry SpecEntMP1PC;
|
||||
|
||||
struct SpecMP1 : SpecBase
|
||||
{
|
||||
@@ -343,7 +344,8 @@ struct SpecMP1 : SpecBase
|
||||
}
|
||||
|
||||
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,
|
||||
[&progress](int surfCount)
|
||||
@@ -358,19 +360,31 @@ struct SpecMP1 : SpecBase
|
||||
}
|
||||
|
||||
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();
|
||||
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,
|
||||
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,
|
||||
FILE* fin, FCookProgress progress) const
|
||||
FILE* fin, FCookProgress progress)
|
||||
{
|
||||
athena::io::YAMLDocReader reader;
|
||||
yaml_parser_set_input_file(reader.getParser(), fin);
|
||||
|
||||
@@ -295,22 +295,25 @@ struct SpecMP2 : SpecBase
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
FILE* fin, FCookProgress progress) const
|
||||
FILE* fin, FCookProgress progress)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -490,22 +490,25 @@ struct SpecMP3 : SpecBase
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
FILE* fin, FCookProgress progress) const
|
||||
FILE* fin, FCookProgress progress)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user