mirror of https://github.com/AxioDL/metaforce.git
Updated to support MP2 characters
This commit is contained in:
parent
b5d96f7040
commit
3c5b5fd39a
|
@ -36,24 +36,27 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
{
|
||||
const NOD::DiscBase::IPartition::Node* node;
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node);
|
||||
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
if (cmdlE)
|
||||
{
|
||||
if (!conn.createBlend(cmdlPath.getAbsolutePath()))
|
||||
return false;
|
||||
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
if (!conn.createBlend(cmdlPath.getAbsolutePath()))
|
||||
return false;
|
||||
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RIGPair rigPair(&cskr, &cinf);
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RIGPair rigPair(&cskr, &cinf);
|
||||
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion>
|
||||
(conn, rs, pakRouter, *cmdlE, masterShader, &rigPair);
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion>
|
||||
(conn, rs, pakRouter, *cmdlE, masterShader, &rigPair);
|
||||
|
||||
conn.saveBlend();
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +87,11 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
|
||||
for (const auto& info : chResInfo)
|
||||
{
|
||||
/* Provide data to add-on */
|
||||
os.format("actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '%s'\n\n",
|
||||
info.name.c_str());
|
||||
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(info.cinf) == cinfsDone.end())
|
||||
{
|
||||
|
@ -93,25 +101,22 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
}
|
||||
else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%08X']\n", info.cinf.toUint32());
|
||||
os << "actor_subtype.linked_armature = arm_obj.name\n";
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl);
|
||||
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePath(), pakRouter.getBestEntryName(*cmdlE), true);
|
||||
if (cmdlE)
|
||||
{
|
||||
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePath(), 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"
|
||||
"\n";
|
||||
|
||||
/* Provide data to add-on */
|
||||
os.format("actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '%s'\n"
|
||||
"actor_subtype.linked_armature = arm_obj.name\n"
|
||||
"actor_subtype.linked_mesh = obj.name\n\n",
|
||||
info.name.c_str());
|
||||
/* 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";
|
||||
}
|
||||
}
|
||||
|
||||
/* Get animation primitives */
|
||||
|
@ -120,11 +125,12 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
for (const auto& id : animResInfo)
|
||||
{
|
||||
typename ANCSDNA::ANIMType anim;
|
||||
pakRouter.lookupAndReadDNA(id.second.second, anim);
|
||||
|
||||
os.format("act = bpy.data.actions.new('%s')\n"
|
||||
"act.use_fake_user = True\n", id.second.first.c_str());
|
||||
anim.sendANIMToBlender(os, cinf);
|
||||
if (pakRouter.lookupAndReadDNA(id.second.second, anim))
|
||||
{
|
||||
os.format("act = bpy.data.actions.new('%s')\n"
|
||||
"act.use_fake_user = True\n", id.second.first.c_str());
|
||||
anim.sendANIMToBlender(os, cinf);
|
||||
}
|
||||
|
||||
os.format("actor_action = actor_data.actions.add()\n"
|
||||
"actor_action.name = '%s'\n", id.second.first.c_str());
|
||||
|
|
|
@ -15,17 +15,13 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
|
|||
case Channel::ROTATION:
|
||||
bitsPerKeyFrame += 1;
|
||||
case Channel::TRANSLATION:
|
||||
case Channel::SCALE:
|
||||
{
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
bitsPerKeyFrame += chan.q[1];
|
||||
bitsPerKeyFrame += chan.q[2];
|
||||
break;
|
||||
}
|
||||
case Channel::SCALE:
|
||||
{
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +139,7 @@ BitstreamReader::read(const atUint8* data,
|
|||
}
|
||||
case Channel::SCALE:
|
||||
{
|
||||
keys.push_back({chan.i[0] * transMult});
|
||||
keys.push_back({chan.i[0] / (float)rotDiv, chan.i[1] / (float)rotDiv, chan.i[2] / (float)rotDiv});
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
@ -179,7 +175,9 @@ BitstreamReader::read(const atUint8* data,
|
|||
case Channel::SCALE:
|
||||
{
|
||||
p[0] += dequantize(data, chan.q[0]);
|
||||
kit->push_back({p[0] * transMult});
|
||||
p[1] += dequantize(data, chan.q[1]);
|
||||
p[2] += dequantize(data, chan.q[2]);
|
||||
kit->push_back({p[0] / (float)rotDiv, p[1] / (float)rotDiv, p[2] / (float)rotDiv});
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
@ -289,7 +287,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
}
|
||||
case Channel::SCALE:
|
||||
{
|
||||
chan.i = {atInt16((*kit)[0].scale / transMultOut)};
|
||||
chan.i = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
@ -321,15 +321,15 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
case Channel::TRANSLATION:
|
||||
{
|
||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
||||
atInt16(it->v3.vec[1] / transMultOut),
|
||||
atInt16(it->v3.vec[2] / transMultOut)};
|
||||
atInt16(it->v3.vec[1] / transMultOut),
|
||||
atInt16(it->v3.vec[2] / transMultOut)};
|
||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
|
||||
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
|
||||
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
|
||||
|
@ -339,13 +339,19 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
}
|
||||
case Channel::SCALE:
|
||||
{
|
||||
atUint16 last = (*kit)[0].scale / transMultOut;
|
||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
atUint16 cur = it->scale / transMultOut;
|
||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur - last)));
|
||||
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
||||
atInt16(it->v3.vec[1] * rotDivOut),
|
||||
atInt16(it->v3.vec[2] * rotDivOut)};
|
||||
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur[0] - last[0])));
|
||||
chan.q[1] = MAX(chan.q[1], ceilf(log2f(cur[1] - last[1])));
|
||||
chan.q[2] = MAX(chan.q[2], ceilf(log2f(cur[2] - last[2])));
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
|
@ -384,15 +390,15 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
case Channel::TRANSLATION:
|
||||
{
|
||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
||||
atInt16((*kit)[0].v3.vec[1] / transMultOut),
|
||||
atInt16((*kit)[0].v3.vec[2] / transMultOut)};
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
QuantizedValue cur = {atInt16(it->v3.vec[0] / transMultOut),
|
||||
atInt16(it->v3.vec[1] / transMultOut),
|
||||
atInt16(it->v3.vec[2] / transMultOut)};
|
||||
atInt16(it->v3.vec[1] / transMultOut),
|
||||
atInt16(it->v3.vec[2] / transMultOut)};
|
||||
quantize(newData, chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData, chan.q[1], cur[1] - last[0]);
|
||||
quantize(newData, chan.q[2], cur[2] - last[0]);
|
||||
|
@ -402,13 +408,19 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
}
|
||||
case Channel::SCALE:
|
||||
{
|
||||
atUint16 last = (*kit)[0].scale / transMultOut;
|
||||
QuantizedValue last = {atInt16((*kit)[0].v3.vec[0] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[1] * rotDivOut),
|
||||
atInt16((*kit)[0].v3.vec[2] * rotDivOut)};
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
atUint16 cur = it->scale / transMultOut;
|
||||
quantize(newData, chan.q[0], cur - last);
|
||||
QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
|
||||
atInt16(it->v3.vec[1] * rotDivOut),
|
||||
atInt16(it->v3.vec[2] * rotDivOut)};
|
||||
quantize(newData, chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData, chan.q[1], cur[1] - last[0]);
|
||||
quantize(newData, chan.q[2], cur[2] - last[0]);
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -13,10 +13,8 @@ union Value
|
|||
{
|
||||
atVec3f v3;
|
||||
atVec4f v4;
|
||||
float scale;
|
||||
Value(atVec3f v) : v3(v) {}
|
||||
Value(atVec4f v) : v4(v) {}
|
||||
Value(float v) : scale(v) {}
|
||||
Value(float x, float y, float z)
|
||||
{
|
||||
v3.vec[0] = x;
|
||||
|
|
|
@ -321,7 +321,7 @@ struct ResExtractor
|
|||
std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&)> func_a;
|
||||
std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&,
|
||||
const typename PAKBRIDGE::PAKType::Entry&, bool)> func_b;
|
||||
const char* fileExt;
|
||||
const char* fileExts[4];
|
||||
unsigned weight;
|
||||
};
|
||||
|
||||
|
@ -407,21 +407,37 @@ public:
|
|||
{
|
||||
HECL::ProjectPath uniquePath = entry->unique.uniquePath(m_pakWorking);
|
||||
HECL::SystemString entName = m_pak->bestEntryName(*entry);
|
||||
if (extractor.fileExt)
|
||||
entName += extractor.fileExt;
|
||||
if (extractor.fileExts[0] && !extractor.fileExts[1])
|
||||
entName += extractor.fileExts[0];
|
||||
return HECL::ProjectPath(uniquePath, entName);
|
||||
}
|
||||
auto sharedSearch = m_sharedEntries.find(entry->id);
|
||||
if (sharedSearch != m_sharedEntries.end())
|
||||
{
|
||||
HECL::ProjectPath uniquePathPre = entry->unique.uniquePath(m_pakWorking);
|
||||
HECL::SystemString entName = m_pak->bestEntryName(*entry);
|
||||
if (extractor.fileExt)
|
||||
entName += extractor.fileExt;
|
||||
HECL::SystemString entBase = m_pak->bestEntryName(*entry);
|
||||
HECL::SystemString entName = entBase;
|
||||
if (extractor.fileExts[0] && !extractor.fileExts[1])
|
||||
entName += extractor.fileExts[0];
|
||||
HECL::ProjectPath sharedPath(m_sharedWorking, entName);
|
||||
HECL::ProjectPath uniquePath(uniquePathPre, entName);
|
||||
if (extractor.func_a || extractor.func_b)
|
||||
uniquePath.makeLinkTo(sharedPath);
|
||||
{
|
||||
if (extractor.fileExts[0] && !extractor.fileExts[1])
|
||||
uniquePath.makeLinkTo(sharedPath);
|
||||
else
|
||||
{
|
||||
for (int e=0 ; e<4 ; ++e)
|
||||
{
|
||||
if (!extractor.fileExts[e])
|
||||
break;
|
||||
HECL::SystemString entName = entBase + extractor.fileExts[e];
|
||||
HECL::ProjectPath sharedPath(m_sharedWorking, entName);
|
||||
HECL::ProjectPath uniquePath(uniquePathPre, entName);
|
||||
uniquePath.makeLinkTo(sharedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_sharedWorking.makeDir();
|
||||
return sharedPath;
|
||||
}
|
||||
|
@ -567,6 +583,7 @@ public:
|
|||
return ent;
|
||||
}
|
||||
}
|
||||
LogDNACommon.report(LogVisor::Warning, "unable to find PAK entry %s", entry.toString().c_str());
|
||||
if (nodeOut)
|
||||
*nodeOut = nullptr;
|
||||
return nullptr;
|
||||
|
@ -578,10 +595,7 @@ public:
|
|||
const NOD::DiscBase::IPartition::Node* node;
|
||||
const typename BRIDGETYPE::PAKType::Entry* entry = lookupEntry(id, &node);
|
||||
if (!entry)
|
||||
{
|
||||
LogDNACommon.report(LogVisor::Error, "unable to find PAK entry %s", id.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
PAKEntryReadStream rs = entry->beginReadStream(*node);
|
||||
out.read(rs);
|
||||
return true;
|
||||
|
|
|
@ -305,11 +305,6 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
|
|||
}
|
||||
|
||||
unk1 = reader.readUint32Big();
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
unk2 = reader.readUint32Big();
|
||||
unk3 = reader.readUint32Big();
|
||||
}
|
||||
|
||||
animAABBs.clear();
|
||||
if (sectionCount > 1)
|
||||
|
@ -344,9 +339,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||
writer.writeUint32Big(idx);
|
||||
|
||||
atUint16 sectionCount;
|
||||
if (unk2 || unk3)
|
||||
sectionCount = 10;
|
||||
else if (partResData.elsc.size())
|
||||
if (partResData.elsc.size())
|
||||
sectionCount = 6;
|
||||
else if (animIdxs.size())
|
||||
sectionCount = 5;
|
||||
|
@ -386,11 +379,6 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
|
|||
}
|
||||
|
||||
writer.writeUint32Big(unk1);
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
writer.writeUint32Big(unk2);
|
||||
writer.writeUint32Big(unk3);
|
||||
}
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
|
@ -449,11 +437,6 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
|
|||
}
|
||||
|
||||
unk1 = reader.readUint32("unk1");
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
unk2 = reader.readUint32("unk2");
|
||||
unk3 = reader.readUint32("unk3");
|
||||
}
|
||||
|
||||
animAABBs.clear();
|
||||
if (sectionCount > 1)
|
||||
|
@ -488,9 +471,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||
writer.writeUint32("idx", idx);
|
||||
|
||||
atUint16 sectionCount;
|
||||
if (unk2 || unk3)
|
||||
sectionCount = 10;
|
||||
else if (partResData.elsc.size())
|
||||
if (partResData.elsc.size())
|
||||
sectionCount = 6;
|
||||
else if (animIdxs.size())
|
||||
sectionCount = 5;
|
||||
|
@ -530,11 +511,6 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
|
|||
}
|
||||
|
||||
writer.writeUint32("unk1", unk1);
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
writer.writeUint32("unk2", unk2);
|
||||
writer.writeUint32("unk3", unk3);
|
||||
}
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
|
|
|
@ -112,8 +112,6 @@ struct ANCS : BigYAML
|
|||
} partResData;
|
||||
|
||||
atUint32 unk1 = 0;
|
||||
atUint32 unk2 = 0;
|
||||
atUint32 unk3 = 0;
|
||||
|
||||
struct ActionAABB : BigYAML
|
||||
{
|
||||
|
@ -380,24 +378,32 @@ struct ANCS : BigYAML
|
|||
const PAK::Entry& entry,
|
||||
bool force)
|
||||
{
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
|
||||
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
|
||||
if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
|
||||
ancs.toYAMLFile(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
|
||||
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
|
||||
if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
HECL::ProjectPath::PathType blendType = blendPath.getPathType();
|
||||
|
||||
if (force ||
|
||||
yamlType == HECL::ProjectPath::PT_NONE ||
|
||||
blendType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
|
||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
|
||||
return conn.saveBlend();
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
|
||||
if (force || yamlType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
|
||||
ancs.toYAMLFile(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
|
||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -5,6 +5,7 @@ make_dnalist(liblist
|
|||
ANIM
|
||||
CINF
|
||||
CSKR
|
||||
EVNT
|
||||
MAPA
|
||||
CMDLMaterials)
|
||||
add_library(DNAMP1
|
||||
|
@ -14,5 +15,6 @@ add_library(DNAMP1
|
|||
STRG.hpp STRG.cpp
|
||||
ANCS.cpp
|
||||
ANIM.cpp
|
||||
EVNT.cpp
|
||||
CMDL.hpp
|
||||
CMDLMaterials.cpp)
|
||||
|
|
|
@ -177,15 +177,15 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
|||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
return {STRG::Extract, nullptr, {".yaml"}};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
return {TXTR::Extract, nullptr, {".png"}};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 2};
|
||||
return {nullptr, CMDL::Extract, {".blend"}, 2};
|
||||
case SBIG('ANCS'):
|
||||
return {nullptr, ANCS::Extract, nullptr, 1};
|
||||
return {nullptr, ANCS::Extract, {".yaml", ".blend"}, 1};
|
||||
case SBIG('MLVL'):
|
||||
return {MLVL::Extract, nullptr, ".yaml"};
|
||||
return {MLVL::Extract, nullptr, {".yaml"}};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
#include "EVNT.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP1
|
||||
{
|
||||
|
||||
void EVNT::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
version = reader.readUint32Big();
|
||||
|
||||
atUint32 loopCount = reader.readUint32Big();
|
||||
reader.enumerate(loopEvents, loopCount);
|
||||
|
||||
uevtEvents.clear();
|
||||
if (version == 2)
|
||||
{
|
||||
atUint32 uevtCount = reader.readUint32Big();
|
||||
reader.enumerate(uevtEvents, uevtCount);
|
||||
}
|
||||
|
||||
atUint32 effectCount = reader.readUint32Big();
|
||||
reader.enumerate(effectEvents, effectCount);
|
||||
|
||||
atUint32 sfxCount = reader.readUint32Big();
|
||||
reader.enumerate(sfxEvents, sfxCount);
|
||||
}
|
||||
|
||||
void EVNT::write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(version);
|
||||
|
||||
writer.writeUint32Big(loopEvents.size());
|
||||
writer.enumerate(loopEvents);
|
||||
|
||||
if (version == 2)
|
||||
{
|
||||
writer.writeUint32Big(uevtEvents.size());
|
||||
writer.enumerate(uevtEvents);
|
||||
}
|
||||
|
||||
writer.writeUint32Big(effectEvents.size());
|
||||
writer.enumerate(effectEvents);
|
||||
|
||||
writer.writeUint32Big(sfxEvents.size());
|
||||
writer.enumerate(sfxEvents);
|
||||
}
|
||||
|
||||
void EVNT::fromYAML(Athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
version = reader.readUint32("version");
|
||||
|
||||
atUint32 loopCount = reader.readUint32("loopCount");
|
||||
reader.enumerate("loopEvents", loopEvents, loopCount);
|
||||
|
||||
uevtEvents.clear();
|
||||
if (version == 2)
|
||||
{
|
||||
atUint32 uevtCount = reader.readUint32("uevtCount");
|
||||
reader.enumerate("uevtEvents", uevtEvents, uevtCount);
|
||||
}
|
||||
|
||||
atUint32 effectCount = reader.readUint32("effectCount");
|
||||
reader.enumerate("effectEvents", effectEvents, effectCount);
|
||||
|
||||
atUint32 sfxCount = reader.readUint32("sfxCount");
|
||||
reader.enumerate("sfxEvents", sfxEvents, sfxCount);
|
||||
}
|
||||
|
||||
void EVNT::toYAML(Athena::io::YAMLDocWriter& writer) const
|
||||
{
|
||||
writer.writeUint32("version", version);
|
||||
|
||||
writer.writeUint32("loopCount", loopEvents.size());
|
||||
writer.enumerate("loopEvents", loopEvents);
|
||||
|
||||
if (version == 2)
|
||||
{
|
||||
writer.writeUint32("uevtCount", uevtEvents.size());
|
||||
writer.enumerate("uevtEvents", uevtEvents);
|
||||
}
|
||||
|
||||
writer.writeUint32("effectCount", effectEvents.size());
|
||||
writer.enumerate("effectEvents", effectEvents);
|
||||
|
||||
writer.writeUint32("sfxCount", sfxEvents.size());
|
||||
writer.enumerate("sfxEvents", sfxEvents);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef __DNAMP1_EVNT_HPP__
|
||||
#define __DNAMP1_EVNT_HPP__
|
||||
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP1
|
||||
{
|
||||
|
||||
struct EVNT : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Delete expl;
|
||||
Value<atUint32> version;
|
||||
|
||||
struct EventBase : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint16> unk0;
|
||||
String<-1> name;
|
||||
Value<atUint16> type;
|
||||
Value<float> startTime;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> idx;
|
||||
Value<atUint8> unk2;
|
||||
Value<float> unk3;
|
||||
Value<float> unk4;
|
||||
Value<atUint32> unk5;
|
||||
};
|
||||
|
||||
struct LoopEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint8> flag;
|
||||
};
|
||||
std::vector<LoopEvent> loopEvents;
|
||||
|
||||
struct UEVTEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> uevtType;
|
||||
String<-1> boneName;
|
||||
};
|
||||
std::vector<UEVTEvent> uevtEvents;
|
||||
|
||||
struct EffectEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> frameCount;
|
||||
FourCC effectType;
|
||||
UniqueID32 effectId;
|
||||
String<-1> boneName;
|
||||
Value<float> scale;
|
||||
Value<atUint32> parentMode;
|
||||
};
|
||||
std::vector<EffectEvent> effectEvents;
|
||||
|
||||
struct SFXEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> soundId;
|
||||
Value<float> smallNum;
|
||||
Value<float> bigNum;
|
||||
};
|
||||
std::vector<SFXEvent> sfxEvents;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __DNAMP1_EVNT_HPP__
|
|
@ -0,0 +1,558 @@
|
|||
#include "ANCS.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP2
|
||||
{
|
||||
|
||||
void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
idx = reader.readUint32Big();
|
||||
atUint16 sectionCount = reader.readUint16Big();
|
||||
name = reader.readString();
|
||||
cmdl.read(reader);
|
||||
cskr.read(reader);
|
||||
cinf.read(reader);
|
||||
|
||||
atUint32 animationCount = reader.readUint32Big();
|
||||
reader.enumerate(animations, animationCount);
|
||||
|
||||
pasDatabase.read(reader);
|
||||
|
||||
atUint32 partCount = reader.readUint32Big();
|
||||
reader.enumerate(partResData.part, partCount);
|
||||
|
||||
atUint32 swhcCount = reader.readUint32Big();
|
||||
reader.enumerate(partResData.swhc, swhcCount);
|
||||
|
||||
atUint32 unkCount = reader.readUint32Big();
|
||||
reader.enumerate(partResData.unk, unkCount);
|
||||
|
||||
atUint32 elscCount = reader.readUint32Big();
|
||||
reader.enumerate(partResData.elsc, elscCount);
|
||||
|
||||
atUint32 spscCount = reader.readUint32Big();
|
||||
reader.enumerate(partResData.spsc, spscCount);
|
||||
|
||||
atUint32 unkCount2 = reader.readUint32Big();
|
||||
if (unkCount2)
|
||||
abort();
|
||||
reader.enumerate(partResData.unk2, unkCount2);
|
||||
|
||||
unk1 = reader.readUint32Big();
|
||||
|
||||
animAABBs.clear();
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
atUint32 aabbCount = reader.readUint32Big();
|
||||
reader.enumerate(animAABBs, aabbCount);
|
||||
}
|
||||
|
||||
effects.clear();
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
atUint32 effectCount = reader.readUint32Big();
|
||||
reader.enumerate(effects, effectCount);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
cmdlOverride.read(reader);
|
||||
cskrOverride.read(reader);
|
||||
}
|
||||
|
||||
animIdxs.clear();
|
||||
if (sectionCount > 4)
|
||||
{
|
||||
atUint32 aidxCount = reader.readUint32Big();
|
||||
reader.enumerateBig(animIdxs, aidxCount);
|
||||
}
|
||||
|
||||
extents.clear();
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
unk4 = reader.readUint32Big();
|
||||
unk5 = reader.readUByte();
|
||||
atUint32 extentsCount = reader.readUint32Big();
|
||||
reader.enumerate(extents, extentsCount);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(idx);
|
||||
|
||||
atUint16 sectionCount;
|
||||
if (unk4 || unk5 || extents.size())
|
||||
sectionCount = 10;
|
||||
else if (partResData.elsc.size())
|
||||
sectionCount = 6;
|
||||
else if (animIdxs.size())
|
||||
sectionCount = 5;
|
||||
else if (cmdlOverride)
|
||||
sectionCount = 4;
|
||||
else if (effects.size())
|
||||
sectionCount = 3;
|
||||
else if (animAABBs.size())
|
||||
sectionCount = 2;
|
||||
else
|
||||
sectionCount = 1;
|
||||
writer.writeUint16Big(sectionCount);
|
||||
|
||||
writer.writeString(name);
|
||||
cmdl.write(writer);
|
||||
cskr.write(writer);
|
||||
cinf.write(writer);
|
||||
|
||||
writer.writeUint32Big(animations.size());
|
||||
writer.enumerate(animations);
|
||||
|
||||
pasDatabase.write(writer);
|
||||
|
||||
writer.writeUint32Big(partResData.part.size());
|
||||
writer.enumerate(partResData.part);
|
||||
|
||||
writer.writeUint32Big(partResData.swhc.size());
|
||||
writer.enumerate(partResData.swhc);
|
||||
|
||||
writer.writeUint32Big(partResData.unk.size());
|
||||
writer.enumerate(partResData.unk);
|
||||
|
||||
writer.writeUint32Big(partResData.elsc.size());
|
||||
writer.enumerate(partResData.elsc);
|
||||
|
||||
writer.writeUint32Big(partResData.spsc.size());
|
||||
writer.enumerate(partResData.spsc);
|
||||
|
||||
writer.writeUint32Big(partResData.unk2.size());
|
||||
writer.enumerate(partResData.unk2);
|
||||
|
||||
writer.writeUint32Big(unk1);
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
writer.writeUint32Big(animAABBs.size());
|
||||
writer.enumerate(animAABBs);
|
||||
}
|
||||
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
writer.writeUint32Big(effects.size());
|
||||
writer.enumerate(effects);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
cmdlOverride.write(writer);
|
||||
cskrOverride.write(writer);
|
||||
}
|
||||
|
||||
if (sectionCount > 4)
|
||||
{
|
||||
writer.writeUint32Big(animIdxs.size());
|
||||
for (atUint32 idx : animIdxs)
|
||||
writer.writeUint32Big(idx);
|
||||
}
|
||||
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
writer.writeUint32Big(unk4);
|
||||
writer.writeUByte(unk5);
|
||||
writer.writeUint32Big(extents.size());
|
||||
writer.enumerate(extents);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
idx = reader.readUint32("idx");
|
||||
atUint16 sectionCount = reader.readUint16("sectionCount");
|
||||
name = reader.readString("name");
|
||||
reader.enumerate("cmdl", cmdl);
|
||||
reader.enumerate("cskr", cskr);
|
||||
reader.enumerate("cinf", cinf);
|
||||
|
||||
atUint32 animationCount = reader.readUint32("animationCount");
|
||||
reader.enumerate("animations", animations, animationCount);
|
||||
|
||||
reader.enumerate("pasDatabase", pasDatabase);
|
||||
|
||||
atUint32 partCount = reader.readUint32("partCount");
|
||||
reader.enumerate("part", partResData.part, partCount);
|
||||
|
||||
atUint32 swhcCount = reader.readUint32("swhcCount");
|
||||
reader.enumerate("swhc", partResData.swhc, swhcCount);
|
||||
|
||||
atUint32 unkCount = reader.readUint32("unkCount");
|
||||
reader.enumerate("unk", partResData.unk, unkCount);
|
||||
|
||||
atUint32 elscCount = reader.readUint32("elscCount");
|
||||
reader.enumerate("elsc", partResData.elsc, elscCount);
|
||||
|
||||
atUint32 spscCount = reader.readUint32("spscCount");
|
||||
reader.enumerate("spsc", partResData.spsc, spscCount);
|
||||
|
||||
atUint32 unk2Count = reader.readUint32("unk2Count");
|
||||
reader.enumerate("unk2", partResData.unk2, unk2Count);
|
||||
|
||||
unk1 = reader.readUint32("unk1");
|
||||
|
||||
animAABBs.clear();
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
atUint32 aabbCount = reader.readUint32("animAABBCount");
|
||||
reader.enumerate("part", animAABBs, aabbCount);
|
||||
}
|
||||
|
||||
effects.clear();
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
atUint32 effectCount = reader.readUint32("effectCount");
|
||||
reader.enumerate("effects", effects, effectCount);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
reader.enumerate("cmdlOverride", cmdlOverride);
|
||||
reader.enumerate("cskrOverride", cskrOverride);
|
||||
}
|
||||
|
||||
animIdxs.clear();
|
||||
if (sectionCount > 4)
|
||||
{
|
||||
atUint32 animIdxCount = reader.readUint32("animIdxCount");
|
||||
reader.enumerate("animIdxs", animIdxs, animIdxCount);
|
||||
}
|
||||
|
||||
extents.clear();
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
unk4 = reader.readUint32("unk4");
|
||||
unk5 = reader.readUByte("unk5");
|
||||
atUint32 extentsCount = reader.readUint32("extentsCount");
|
||||
reader.enumerate("extents", extents, extentsCount);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer) const
|
||||
{
|
||||
writer.writeUint32("idx", idx);
|
||||
|
||||
atUint16 sectionCount;
|
||||
if (unk4 || unk5 || extents.size())
|
||||
sectionCount = 10;
|
||||
else if (partResData.elsc.size())
|
||||
sectionCount = 6;
|
||||
else if (animIdxs.size())
|
||||
sectionCount = 5;
|
||||
else if (cmdlOverride)
|
||||
sectionCount = 4;
|
||||
else if (effects.size())
|
||||
sectionCount = 3;
|
||||
else if (animAABBs.size())
|
||||
sectionCount = 2;
|
||||
else
|
||||
sectionCount = 1;
|
||||
writer.writeUint16("sectionCount", sectionCount);
|
||||
|
||||
writer.writeString("name", name);
|
||||
writer.enumerate("cmdl", cmdl);
|
||||
writer.enumerate("cskr", cskr);
|
||||
writer.enumerate("cinf", cinf);
|
||||
|
||||
writer.writeUint32("animationCount", animations.size());
|
||||
writer.enumerate("animations", animations);
|
||||
|
||||
writer.enumerate("pasDatabase", pasDatabase);
|
||||
|
||||
writer.writeUint32("partCount", partResData.part.size());
|
||||
writer.enumerate("part", partResData.part);
|
||||
|
||||
writer.writeUint32("swhcCount", partResData.swhc.size());
|
||||
writer.enumerate("swhc", partResData.swhc);
|
||||
|
||||
writer.writeUint32("unkCount", partResData.unk.size());
|
||||
writer.enumerate("unk", partResData.unk);
|
||||
|
||||
writer.writeUint32("elscCount", partResData.elsc.size());
|
||||
writer.enumerate("elsc", partResData.elsc);
|
||||
|
||||
writer.writeUint32("spscCount", partResData.spsc.size());
|
||||
writer.enumerate("spsc", partResData.spsc);
|
||||
|
||||
writer.writeUint32("unk2Count", partResData.unk2.size());
|
||||
writer.enumerate("unk2", partResData.unk2);
|
||||
|
||||
writer.writeUint32("unk1", unk1);
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
writer.writeUint32("animAABBCount", animAABBs.size());
|
||||
writer.enumerate("animAABBs", animAABBs);
|
||||
}
|
||||
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
writer.writeUint32("effectCount", effects.size());
|
||||
writer.enumerate("effects", effects);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
writer.enumerate("cmdlOverride", cmdlOverride);
|
||||
writer.enumerate("cskrOverride", cskrOverride);
|
||||
}
|
||||
|
||||
if (sectionCount > 4)
|
||||
{
|
||||
writer.writeUint32("animIdxCount", animIdxs.size());
|
||||
writer.enumerate("animIdxs", animIdxs);
|
||||
}
|
||||
|
||||
if (sectionCount > 9)
|
||||
{
|
||||
writer.writeUint32("unk4", unk4);
|
||||
writer.writeUByte("unk5", unk5);
|
||||
writer.writeUint32("extentsCount", extents.size());
|
||||
writer.enumerate("extents", extents);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
atUint16 sectionCount = reader.readUint16Big();
|
||||
|
||||
atUint32 animationCount = reader.readUint32Big();
|
||||
reader.enumerate(animations, animationCount);
|
||||
|
||||
atUint32 transitionCount = reader.readUint32Big();
|
||||
reader.enumerate(transitions, transitionCount);
|
||||
defaultTransition.read(reader);
|
||||
|
||||
additiveAnims.clear();
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
atUint32 additiveAnimCount = reader.readUint32Big();
|
||||
reader.enumerate(additiveAnims, additiveAnimCount);
|
||||
floatA = reader.readFloatBig();
|
||||
floatB = reader.readFloatBig();
|
||||
}
|
||||
|
||||
halfTransitions.clear();
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
atUint32 halfTransitionCount = reader.readUint32Big();
|
||||
reader.enumerate(halfTransitions, halfTransitionCount);
|
||||
}
|
||||
|
||||
evnts.clear();
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
atUint32 evntsCount = reader.readUint32Big();
|
||||
reader.enumerate(evnts, evntsCount);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
atUint16 sectionCount;
|
||||
if (evnts.size())
|
||||
sectionCount = 4;
|
||||
else if (halfTransitions.size())
|
||||
sectionCount = 3;
|
||||
else if (additiveAnims.size())
|
||||
sectionCount = 2;
|
||||
else
|
||||
sectionCount = 1;
|
||||
|
||||
writer.writeUint16Big(sectionCount);
|
||||
|
||||
writer.writeUint32Big(animations.size());
|
||||
writer.enumerate(animations);
|
||||
|
||||
writer.writeUint32Big(transitions.size());
|
||||
writer.enumerate(transitions);
|
||||
defaultTransition.write(writer);
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
writer.writeUint32Big(additiveAnims.size());
|
||||
writer.enumerate(additiveAnims);
|
||||
writer.writeFloatBig(floatA);
|
||||
writer.writeFloatBig(floatB);
|
||||
}
|
||||
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
writer.writeUint32Big(halfTransitions.size());
|
||||
writer.enumerate(halfTransitions);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
writer.writeUint32Big(evnts.size());
|
||||
writer.enumerate(evnts);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::fromYAML(Athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
atUint16 sectionCount = reader.readUint16("sectionCount");
|
||||
|
||||
atUint32 animationCount = reader.readUint32("animationCount");
|
||||
reader.enumerate("animations", animations, animationCount);
|
||||
|
||||
atUint32 transitionCount = reader.readUint32("transitionCount");
|
||||
reader.enumerate("transitions", transitions, transitionCount);
|
||||
reader.enumerate("defaultTransition", defaultTransition);
|
||||
|
||||
additiveAnims.clear();
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
atUint32 additiveAnimCount = reader.readUint32("additiveAnimCount");
|
||||
reader.enumerate("additiveAnims", additiveAnims, additiveAnimCount);
|
||||
floatA = reader.readFloat("floatA");
|
||||
floatB = reader.readFloat("floatB");
|
||||
}
|
||||
|
||||
halfTransitions.clear();
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
atUint32 halfTransitionCount = reader.readUint32("halfTransitionCount");
|
||||
reader.enumerate("halfTransitions", halfTransitions, halfTransitionCount);
|
||||
}
|
||||
|
||||
evnts.clear();
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
atUint32 evntsCount = reader.readUint32("evntsCount");
|
||||
reader.enumerate("evnts", evnts, evntsCount);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::toYAML(Athena::io::YAMLDocWriter& writer) const
|
||||
{
|
||||
atUint16 sectionCount;
|
||||
if (evnts.size())
|
||||
sectionCount = 4;
|
||||
else if (halfTransitions.size())
|
||||
sectionCount = 3;
|
||||
else if (additiveAnims.size())
|
||||
sectionCount = 2;
|
||||
else
|
||||
sectionCount = 1;
|
||||
|
||||
writer.writeUint16("sectionCount", sectionCount);
|
||||
|
||||
writer.writeUint32("animationCount", animations.size());
|
||||
writer.enumerate("animations", animations);
|
||||
|
||||
writer.writeUint32("transitionCount", transitions.size());
|
||||
writer.enumerate("transitions", transitions);
|
||||
writer.enumerate("defaultTransition", defaultTransition);
|
||||
|
||||
if (sectionCount > 1)
|
||||
{
|
||||
writer.writeUint32("additiveAnimCount", additiveAnims.size());
|
||||
writer.enumerate("additiveAnims", additiveAnims);
|
||||
writer.writeFloat("floatA", floatA);
|
||||
writer.writeFloat("floatB", floatB);
|
||||
}
|
||||
|
||||
if (sectionCount > 2)
|
||||
{
|
||||
writer.writeUint32("halfTransitionCount", halfTransitions.size());
|
||||
writer.enumerate("halfTransitions", halfTransitions);
|
||||
}
|
||||
|
||||
if (sectionCount > 3)
|
||||
{
|
||||
writer.writeUint32("evntsCount", evnts.size());
|
||||
writer.enumerate("evnts", evnts);
|
||||
}
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::EVNT::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
version = reader.readUint32Big();
|
||||
|
||||
atUint32 loopCount = reader.readUint32Big();
|
||||
reader.enumerate(loopEvents, loopCount);
|
||||
|
||||
uevtEvents.clear();
|
||||
if (version == 2)
|
||||
{
|
||||
atUint32 uevtCount = reader.readUint32Big();
|
||||
reader.enumerate(uevtEvents, uevtCount);
|
||||
}
|
||||
|
||||
atUint32 effectCount = reader.readUint32Big();
|
||||
reader.enumerate(effectEvents, effectCount);
|
||||
|
||||
atUint32 sfxCount = reader.readUint32Big();
|
||||
reader.enumerate(sfxEvents, sfxCount);
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::EVNT::write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(version);
|
||||
|
||||
writer.writeUint32Big(loopEvents.size());
|
||||
writer.enumerate(loopEvents);
|
||||
|
||||
if (version == 2)
|
||||
{
|
||||
writer.writeUint32Big(uevtEvents.size());
|
||||
writer.enumerate(uevtEvents);
|
||||
}
|
||||
|
||||
writer.writeUint32Big(effectEvents.size());
|
||||
writer.enumerate(effectEvents);
|
||||
|
||||
writer.writeUint32Big(sfxEvents.size());
|
||||
writer.enumerate(sfxEvents);
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::EVNT::fromYAML(Athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
version = reader.readUint32("version");
|
||||
|
||||
atUint32 loopCount = reader.readUint32("loopCount");
|
||||
reader.enumerate("loopEvents", loopEvents, loopCount);
|
||||
|
||||
uevtEvents.clear();
|
||||
if (version == 2)
|
||||
{
|
||||
atUint32 uevtCount = reader.readUint32("uevtCount");
|
||||
reader.enumerate("uevtEvents", uevtEvents, uevtCount);
|
||||
}
|
||||
|
||||
atUint32 effectCount = reader.readUint32("effectCount");
|
||||
reader.enumerate("effectEvents", effectEvents, effectCount);
|
||||
|
||||
atUint32 sfxCount = reader.readUint32("sfxCount");
|
||||
reader.enumerate("sfxEvents", sfxEvents, sfxCount);
|
||||
}
|
||||
|
||||
void ANCS::AnimationSet::EVNT::toYAML(Athena::io::YAMLDocWriter& writer) const
|
||||
{
|
||||
writer.writeUint32("version", version);
|
||||
|
||||
writer.writeUint32("loopCount", loopEvents.size());
|
||||
writer.enumerate("loopEvents", loopEvents);
|
||||
|
||||
if (version == 2)
|
||||
{
|
||||
writer.writeUint32("uevtCount", uevtEvents.size());
|
||||
writer.enumerate("uevtEvents", uevtEvents);
|
||||
}
|
||||
|
||||
writer.writeUint32("effectCount", effectEvents.size());
|
||||
writer.enumerate("effectEvents", effectEvents);
|
||||
|
||||
writer.writeUint32("sfxCount", sfxEvents.size());
|
||||
writer.enumerate("sfxEvents", sfxEvents);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -25,14 +25,172 @@ struct ANCS : BigYAML
|
|||
DECL_YAML
|
||||
Value<atUint16> version;
|
||||
|
||||
DNAMP1::ANCS::CharacterSet characterSet;
|
||||
DNAMP1::ANCS::AnimationSet animationSet;
|
||||
struct CharacterSet : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint16> version;
|
||||
Value<atUint32> characterCount;
|
||||
struct CharacterInfo : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Delete expl;
|
||||
using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo;
|
||||
|
||||
atUint32 idx;
|
||||
std::string name;
|
||||
UniqueID32 cmdl;
|
||||
UniqueID32 cskr;
|
||||
UniqueID32 cinf;
|
||||
|
||||
struct Animation : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> animIdx;
|
||||
String<-1> strA;
|
||||
};
|
||||
std::vector<Animation> animations;
|
||||
|
||||
MP1CharacterInfo::PASDatabase pasDatabase;
|
||||
struct ParticleResData
|
||||
{
|
||||
std::vector<UniqueID32> part;
|
||||
std::vector<UniqueID32> swhc;
|
||||
std::vector<UniqueID32> unk;
|
||||
std::vector<UniqueID32> elsc;
|
||||
std::vector<UniqueID32> spsc;
|
||||
std::vector<UniqueID32> unk2;
|
||||
} partResData;
|
||||
|
||||
atUint32 unk1 = 0;
|
||||
|
||||
std::vector<MP1CharacterInfo::ActionAABB> animAABBs;
|
||||
|
||||
struct Effect : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> compCount;
|
||||
struct EffectComponent : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
String<-1> name;
|
||||
FourCC type;
|
||||
UniqueID32 id;
|
||||
Value<atUint32> unkMP2;
|
||||
Value<float> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> unk3;
|
||||
};
|
||||
Vector<EffectComponent, DNA_COUNT(compCount)> comps;
|
||||
};
|
||||
std::vector<Effect> effects;
|
||||
|
||||
UniqueID32 cmdlOverride;
|
||||
UniqueID32 cskrOverride;
|
||||
|
||||
std::vector<atUint32> animIdxs;
|
||||
|
||||
atUint32 unk4;
|
||||
atUint8 unk5;
|
||||
|
||||
struct Extents : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> animIdx;
|
||||
Value<atVec3f> aabb[2];
|
||||
};
|
||||
std::vector<Extents> extents;
|
||||
};
|
||||
Vector<CharacterInfo, DNA_COUNT(characterCount)> characters;
|
||||
} characterSet;
|
||||
|
||||
struct AnimationSet : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Delete expl;
|
||||
using MP1AnimationSet = DNAMP1::ANCS::AnimationSet;
|
||||
|
||||
std::vector<MP1AnimationSet::Animation> animations;
|
||||
|
||||
std::vector<MP1AnimationSet::Transition> transitions;
|
||||
MP1AnimationSet::MetaTransFactory defaultTransition;
|
||||
|
||||
std::vector<MP1AnimationSet::AdditiveAnimationInfo> additiveAnims;
|
||||
|
||||
float floatA = 0.0;
|
||||
float floatB = 0.0;
|
||||
|
||||
std::vector<MP1AnimationSet::HalfTransition> halfTransitions;
|
||||
|
||||
struct EVNT : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Delete expl;
|
||||
atUint32 version;
|
||||
|
||||
struct EventBase : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint16> unk0;
|
||||
String<-1> name;
|
||||
Value<atUint16> type;
|
||||
Value<float> startTime;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> idx;
|
||||
Value<atUint8> unk2;
|
||||
Value<float> unk3;
|
||||
Value<float> unk4;
|
||||
Value<atUint32> unk5;
|
||||
};
|
||||
|
||||
struct LoopEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint8> flag;
|
||||
};
|
||||
std::vector<LoopEvent> loopEvents;
|
||||
|
||||
struct UEVTEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> uevtType;
|
||||
String<-1> boneName;
|
||||
};
|
||||
std::vector<UEVTEvent> uevtEvents;
|
||||
|
||||
struct EffectEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> frameCount;
|
||||
FourCC effectType;
|
||||
UniqueID32 effectId;
|
||||
Value<atUint32> boneId;
|
||||
Value<float> scale;
|
||||
Value<atUint32> parentMode;
|
||||
};
|
||||
std::vector<EffectEvent> effectEvents;
|
||||
|
||||
struct SFXEvent : EventBase
|
||||
{
|
||||
DECL_YAML
|
||||
Value<atUint32> soundId;
|
||||
Value<float> smallNum;
|
||||
Value<float> bigNum;
|
||||
Value<atUint32> sfxUnk1;
|
||||
Value<atUint16> sfxUnk2;
|
||||
Value<atUint16> sfxUnk3;
|
||||
Value<float> sfxUnk4;
|
||||
};
|
||||
std::vector<SFXEvent> sfxEvents;
|
||||
};
|
||||
std::vector<EVNT> evnts;
|
||||
} animationSet;
|
||||
|
||||
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const
|
||||
{
|
||||
out.clear();
|
||||
out.reserve(characterSet.characters.size());
|
||||
for (const DNAMP1::ANCS::CharacterSet::CharacterInfo& ci : characterSet.characters)
|
||||
for (const CharacterSet::CharacterInfo& ci : characterSet.characters)
|
||||
{
|
||||
out.emplace_back();
|
||||
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
|
||||
|
@ -57,24 +215,32 @@ struct ANCS : BigYAML
|
|||
const DNAMP1::PAK::Entry& entry,
|
||||
bool force)
|
||||
{
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
|
||||
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
|
||||
if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
|
||||
ancs.toYAMLFile(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
|
||||
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
|
||||
if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE)
|
||||
HECL::ProjectPath::PathType blendType = blendPath.getPathType();
|
||||
|
||||
if (force ||
|
||||
yamlType == HECL::ProjectPath::PT_NONE ||
|
||||
blendType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
|
||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
|
||||
return conn.saveBlend();
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
|
||||
if (force || yamlType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
|
||||
ancs.toYAMLFile(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (force || blendType == HECL::ProjectPath::PT_NONE)
|
||||
{
|
||||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
|
||||
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -10,19 +10,21 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
|
|||
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
||||
|
||||
auto kit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
|
||||
os << "action_group = act.groups.new(bone_string)\n"
|
||||
"\n"
|
||||
"rotCurves = []\n"
|
||||
"\n";
|
||||
|
||||
if (std::get<0>(bone.second))
|
||||
os << "rotCurves = []\n"
|
||||
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n"
|
||||
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n"
|
||||
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n"
|
||||
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n"
|
||||
"\n";
|
||||
|
||||
if (bone.second)
|
||||
if (std::get<1>(bone.second))
|
||||
os << "bone_trans_head = (0.0,0.0,0.0)\n"
|
||||
"if arm_obj.data.bones[bone_string].parent is not None:\n"
|
||||
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
|
||||
|
@ -32,26 +34,36 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
|
|||
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
|
||||
"\n";
|
||||
|
||||
if (std::get<2>(bone.second))
|
||||
os << "scaleCurves = []\n"
|
||||
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, action_group=bone_string))\n"
|
||||
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, action_group=bone_string))\n"
|
||||
"scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, action_group=bone_string))\n"
|
||||
"\n";
|
||||
|
||||
os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].co = (0, 0)\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"\n";
|
||||
|
||||
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
|
||||
auto frameit = frames.begin();
|
||||
for (const DNAANIM::Value& val : rotKeys)
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
atUint32 frame = *frameit++;
|
||||
for (int c=0 ; c<4 ; ++c)
|
||||
os.format("crv = rotCurves[%d]\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%u, %f)\n",
|
||||
c, frame, val.v4.vec[c]);
|
||||
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
|
||||
auto frameit = frames.begin();
|
||||
for (const DNAANIM::Value& val : rotKeys)
|
||||
{
|
||||
atUint32 frame = *frameit++;
|
||||
for (int c=0 ; c<4 ; ++c)
|
||||
os.format("crv = rotCurves[%d]\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%u, %f)\n",
|
||||
c, frame, val.v4.vec[c]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bone.second)
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& transKeys = *kit++;
|
||||
auto frameit = frames.begin();
|
||||
|
@ -63,7 +75,23 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
|
|||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%u, %f - bone_trans_head[%d])\n",
|
||||
c, frame, val.v4.vec[c], c);
|
||||
c, frame, val.v3.vec[c], c);
|
||||
}
|
||||
}
|
||||
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& scaleKeys = *kit++;
|
||||
auto frameit = frames.begin();
|
||||
for (const DNAANIM::Value& val : scaleKeys)
|
||||
{
|
||||
atUint32 frame = *frameit++;
|
||||
for (int c=0 ; c<3 ; ++c)
|
||||
os.format("crv = scaleCurves[%d]\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%u, %f)\n",
|
||||
c, frame, val.v3.vec[c], c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,43 +120,66 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
|
|||
atUint32 boneCount = reader.readUint32Big();
|
||||
bones.clear();
|
||||
bones.reserve(boneCount);
|
||||
channels.clear();
|
||||
for (size_t b=0 ; b<boneCount ; ++b)
|
||||
{
|
||||
bones.emplace_back(boneMap[b], false);
|
||||
bones.emplace_back(boneMap[b], std::make_tuple(false, false, false));
|
||||
atUint8 idx = reader.readUByte();
|
||||
channels.emplace_back();
|
||||
DNAANIM::Channel& chan = channels.back();
|
||||
chan.type = DNAANIM::Channel::ROTATION;
|
||||
if (idx != 0xff)
|
||||
std::get<0>(bones.back().second) = true;
|
||||
}
|
||||
|
||||
boneCount = reader.readUint32Big();
|
||||
for (size_t b=0 ; b<boneCount ; ++b)
|
||||
{
|
||||
atUint8 idx = reader.readUByte();
|
||||
if (idx != 0xff)
|
||||
std::get<1>(bones.back().second) = true;
|
||||
}
|
||||
|
||||
boneCount = reader.readUint32Big();
|
||||
for (size_t b=0 ; b<boneCount ; ++b)
|
||||
{
|
||||
atUint8 idx = reader.readUByte();
|
||||
if (idx != 0xff)
|
||||
std::get<2>(bones.back().second) = true;
|
||||
}
|
||||
|
||||
channels.clear();
|
||||
chanKeys.clear();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
channels.emplace_back();
|
||||
DNAANIM::Channel& chan = channels.back();
|
||||
chan.type = DNAANIM::Channel::ROTATION;
|
||||
chanKeys.emplace_back();
|
||||
}
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
bones.back().second = true;
|
||||
channels.emplace_back();
|
||||
DNAANIM::Channel& chan = channels.back();
|
||||
chan.type = DNAANIM::Channel::TRANSLATION;
|
||||
chanKeys.emplace_back();
|
||||
}
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
channels.emplace_back();
|
||||
DNAANIM::Channel& chan = channels.back();
|
||||
chan.type = DNAANIM::Channel::SCALE;
|
||||
chanKeys.emplace_back();
|
||||
}
|
||||
}
|
||||
|
||||
reader.readUint32Big();
|
||||
chanKeys.clear();
|
||||
chanKeys.reserve(channels.size());
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
{
|
||||
chanKeys.emplace_back();
|
||||
std::vector<DNAANIM::Value>& keys = chanKeys.back();
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
keys.emplace_back(reader.readVec4fBig());
|
||||
|
||||
if (bone.second)
|
||||
chanKeys.emplace_back();
|
||||
}
|
||||
|
||||
reader.readUint32Big();
|
||||
auto kit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
++kit;
|
||||
if (bone.second)
|
||||
if (std::get<0>(bone.second))
|
||||
++kit;
|
||||
if (std::get<1>(bone.second))
|
||||
++kit;
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
std::vector<DNAANIM::Value>& keys = *kit++;
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
|
@ -136,7 +187,38 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
|
|||
}
|
||||
}
|
||||
|
||||
evnt.read(reader);
|
||||
reader.readUint32Big();
|
||||
kit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
chanKeys.emplace_back();
|
||||
std::vector<DNAANIM::Value>& keys = chanKeys.back();
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
keys.emplace_back(reader.readVec4fBig());
|
||||
}
|
||||
if (std::get<1>(bone.second))
|
||||
++kit;
|
||||
if (std::get<2>(bone.second))
|
||||
++kit;
|
||||
}
|
||||
|
||||
reader.readUint32Big();
|
||||
kit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
++kit;
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
std::vector<DNAANIM::Value>& keys = *kit++;
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
keys.emplace_back(reader.readVec3fBig());
|
||||
}
|
||||
if (std::get<2>(bone.second))
|
||||
++kit;
|
||||
}
|
||||
}
|
||||
|
||||
void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
||||
|
@ -150,7 +232,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||
head.interval = mainInterval;
|
||||
|
||||
atUint32 maxId = 0;
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
maxId = MAX(maxId, bone.first);
|
||||
head.boneSlotCount = maxId + 1;
|
||||
head.write(writer);
|
||||
|
@ -159,7 +241,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||
{
|
||||
size_t boneIdx = 0;
|
||||
bool found = false;
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (s == bone.first)
|
||||
{
|
||||
|
@ -175,37 +257,58 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||
|
||||
writer.writeUint32Big(bones.size());
|
||||
size_t boneIdx = 0;
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
size_t rotKeyCount = 0;
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (bone.second)
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
writer.writeUByte(boneIdx);
|
||||
++rotKeyCount;
|
||||
}
|
||||
else
|
||||
writer.writeUByte(0xff);
|
||||
++boneIdx;
|
||||
}
|
||||
|
||||
writer.writeUint32Big(bones.size() * head.keyCount);
|
||||
auto cit = chanKeys.begin();
|
||||
atUint32 transKeyCount = 0;
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
writer.writeUint32Big(bones.size());
|
||||
boneIdx = 0;
|
||||
size_t transKeyCount = 0;
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& keys = *cit++;
|
||||
auto kit = keys.begin();
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
writer.writeVec4fBig((*kit++).v4);
|
||||
if (bone.second)
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
transKeyCount += head.keyCount;
|
||||
++cit;
|
||||
writer.writeUByte(boneIdx);
|
||||
++transKeyCount;
|
||||
}
|
||||
else
|
||||
writer.writeUByte(0xff);
|
||||
++boneIdx;
|
||||
}
|
||||
|
||||
writer.writeUint32Big(transKeyCount);
|
||||
cit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
writer.writeUint32Big(bones.size());
|
||||
boneIdx = 0;
|
||||
size_t scaleKeyCount = 0;
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
++cit;
|
||||
if (bone.second)
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
writer.writeUByte(boneIdx);
|
||||
++scaleKeyCount;
|
||||
}
|
||||
else
|
||||
writer.writeUByte(0xff);
|
||||
++boneIdx;
|
||||
}
|
||||
|
||||
writer.writeUint32Big(scaleKeyCount * head.keyCount);
|
||||
auto cit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
++cit;
|
||||
if (std::get<1>(bone.second))
|
||||
++cit;
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& keys = *cit++;
|
||||
auto kit = keys.begin();
|
||||
|
@ -214,14 +317,45 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
|
|||
}
|
||||
}
|
||||
|
||||
evnt.write(writer);
|
||||
writer.writeUint32Big(rotKeyCount * head.keyCount);
|
||||
cit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& keys = *cit++;
|
||||
auto kit = keys.begin();
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
writer.writeVec4fBig((*kit++).v4);
|
||||
}
|
||||
if (std::get<1>(bone.second))
|
||||
++cit;
|
||||
if (std::get<2>(bone.second))
|
||||
++cit;
|
||||
}
|
||||
|
||||
writer.writeUint32Big(transKeyCount * head.keyCount);
|
||||
cit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
if (std::get<0>(bone.second))
|
||||
++cit;
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& keys = *cit++;
|
||||
auto kit = keys.begin();
|
||||
for (size_t k=0 ; k<head.keyCount ; ++k)
|
||||
writer.writeVec3fBig((*kit++).v3);
|
||||
}
|
||||
if (std::get<2>(bone.second))
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
|
||||
void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
Header head;
|
||||
head.read(reader);
|
||||
evnt = head.evnt;
|
||||
mainInterval = head.interval;
|
||||
|
||||
WordBitmap keyBmp;
|
||||
|
@ -234,7 +368,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||
frames.push_back(frameAccum);
|
||||
++frameAccum;
|
||||
}
|
||||
reader.seek(8);
|
||||
reader.seek(4);
|
||||
|
||||
bones.clear();
|
||||
bones.reserve(head.boneChannelCount);
|
||||
|
@ -245,7 +379,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||
{
|
||||
ChannelDesc desc;
|
||||
desc.read(reader);
|
||||
bones.emplace_back(desc.id, desc.keyCount2);
|
||||
bones.emplace_back(desc.id, std::make_tuple(desc.keyCount1, desc.keyCount2, desc.keyCount3));
|
||||
|
||||
if (desc.keyCount1)
|
||||
{
|
||||
|
@ -273,6 +407,21 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||
chan.i[2] = desc.initTZ;
|
||||
chan.q[2] = desc.qTZ;
|
||||
}
|
||||
keyframeCount = MAX(keyframeCount, desc.keyCount2);
|
||||
|
||||
if (desc.keyCount3)
|
||||
{
|
||||
channels.emplace_back();
|
||||
DNAANIM::Channel& chan = channels.back();
|
||||
chan.type = DNAANIM::Channel::SCALE;
|
||||
chan.i[0] = desc.initSX;
|
||||
chan.q[0] = desc.qSX;
|
||||
chan.i[1] = desc.initSY;
|
||||
chan.q[1] = desc.qSY;
|
||||
chan.i[2] = desc.initSZ;
|
||||
chan.q[2] = desc.qSZ;
|
||||
}
|
||||
keyframeCount = MAX(keyframeCount, desc.keyCount3);
|
||||
}
|
||||
|
||||
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
|
||||
|
@ -284,12 +433,13 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||
void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
Header head;
|
||||
head.evnt = evnt;
|
||||
head.unk0 = 1;
|
||||
head.unk1 = 1;
|
||||
head.unk2 = 1;
|
||||
head.interval = mainInterval;
|
||||
head.unk1 = 3;
|
||||
head.unk2 = 0;
|
||||
head.unk3 = 1;
|
||||
head.unk3 = 0;
|
||||
head.unk4 = 0;
|
||||
head.unk5 = 0;
|
||||
head.unk6 = 1;
|
||||
|
||||
WordBitmap keyBmp;
|
||||
size_t frameCount = 0;
|
||||
|
@ -317,21 +467,22 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
|
|||
head.write(writer);
|
||||
keyBmp.write(writer);
|
||||
writer.writeUint32Big(head.boneChannelCount);
|
||||
writer.writeUint32Big(head.boneChannelCount);
|
||||
auto cit = qChannels.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
|
||||
{
|
||||
ChannelDesc desc;
|
||||
desc.id = bone.first;
|
||||
DNAANIM::Channel& chan = *cit++;
|
||||
desc.keyCount1 = keyframeCount;
|
||||
desc.initRX = chan.i[0];
|
||||
desc.qRX = chan.q[0];
|
||||
desc.initRY = chan.i[1];
|
||||
desc.qRY = chan.q[1];
|
||||
desc.initRZ = chan.i[2];
|
||||
desc.qRZ = chan.q[2];
|
||||
if (bone.second)
|
||||
if (std::get<0>(bone.second))
|
||||
{
|
||||
DNAANIM::Channel& chan = *cit++;
|
||||
desc.keyCount1 = keyframeCount;
|
||||
desc.initRX = chan.i[0];
|
||||
desc.qRX = chan.q[0];
|
||||
desc.initRY = chan.i[1];
|
||||
desc.qRY = chan.q[1];
|
||||
desc.initRZ = chan.i[2];
|
||||
desc.qRZ = chan.q[2];
|
||||
}
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
DNAANIM::Channel& chan = *cit++;
|
||||
desc.keyCount2 = keyframeCount;
|
||||
|
@ -342,7 +493,17 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
|
|||
desc.initTZ = chan.i[2];
|
||||
desc.qTZ = chan.q[2];
|
||||
}
|
||||
desc.write(writer);
|
||||
if (std::get<2>(bone.second))
|
||||
{
|
||||
DNAANIM::Channel& chan = *cit++;
|
||||
desc.keyCount3 = keyframeCount;
|
||||
desc.initSX = chan.i[0];
|
||||
desc.qSX = chan.q[0];
|
||||
desc.initSY = chan.i[1];
|
||||
desc.qSY = chan.q[1];
|
||||
desc.initSZ = chan.i[2];
|
||||
desc.qSZ = chan.q[2];
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeUBytes(bsData.get(), bsSize);
|
||||
|
|
|
@ -21,12 +21,11 @@ struct ANIM : BigDNA
|
|||
atUint32 m_version;
|
||||
IANIM(atUint32 version) : m_version(version) {}
|
||||
|
||||
std::vector<std::pair<atUint32, bool>> bones;
|
||||
std::vector<std::pair<atUint32, std::tuple<bool,bool,bool>>> bones;
|
||||
std::vector<atUint32> frames;
|
||||
std::vector<DNAANIM::Channel> channels;
|
||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
UniqueID32 evnt;
|
||||
|
||||
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const;
|
||||
};
|
||||
|
@ -58,23 +57,24 @@ struct ANIM : BigDNA
|
|||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> scratchSize;
|
||||
UniqueID32 evnt;
|
||||
Value<atUint32> unk0;
|
||||
Value<atUint8> unk1;
|
||||
Value<atUint8> unk2;
|
||||
Value<float> duration;
|
||||
Value<float> interval;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> unk3;
|
||||
Value<atUint32> unk4;
|
||||
Value<atUint32> rotDiv;
|
||||
Value<float> translationMult;
|
||||
Value<atUint32> unk5;
|
||||
Value<atUint32> boneChannelCount;
|
||||
Value<atUint32> unk3;
|
||||
Value<atUint32> unk6;
|
||||
Value<atUint32> keyBitmapBitCount;
|
||||
};
|
||||
|
||||
struct ChannelDesc : BigDNA
|
||||
{
|
||||
Delete expl;
|
||||
Value<atUint32> id = 0;
|
||||
Value<atUint8> id = 0;
|
||||
Value<atUint16> keyCount1 = 0;
|
||||
Value<atUint16> initRX = 0;
|
||||
Value<atUint8> qRX = 0;
|
||||
|
@ -89,17 +89,27 @@ struct ANIM : BigDNA
|
|||
Value<atUint8> qTY = 0;
|
||||
Value<atUint16> initTZ = 0;
|
||||
Value<atUint8> qTZ = 0;
|
||||
Value<atUint16> keyCount3 = 0;
|
||||
Value<atUint16> initSX = 0;
|
||||
Value<atUint8> qSX = 0;
|
||||
Value<atUint16> initSY = 0;
|
||||
Value<atUint8> qSY = 0;
|
||||
Value<atUint16> initSZ = 0;
|
||||
Value<atUint8> qSZ = 0;
|
||||
|
||||
void read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint32Big();
|
||||
id = reader.readUByte();
|
||||
keyCount1 = reader.readUint16Big();
|
||||
initRX = reader.readUint16Big();
|
||||
qRX = reader.readUByte();
|
||||
initRY = reader.readUint16Big();
|
||||
qRY = reader.readUByte();
|
||||
initRZ = reader.readUint16Big();
|
||||
qRZ = reader.readUByte();
|
||||
if (keyCount1)
|
||||
{
|
||||
initRX = reader.readUint16Big();
|
||||
qRX = reader.readUByte();
|
||||
initRY = reader.readUint16Big();
|
||||
qRY = reader.readUByte();
|
||||
initRZ = reader.readUint16Big();
|
||||
qRZ = reader.readUByte();
|
||||
}
|
||||
keyCount2 = reader.readUint16Big();
|
||||
if (keyCount2)
|
||||
{
|
||||
|
@ -110,17 +120,30 @@ struct ANIM : BigDNA
|
|||
initTZ = reader.readUint16Big();
|
||||
qTZ = reader.readUByte();
|
||||
}
|
||||
keyCount3 = reader.readUint16Big();
|
||||
if (keyCount3)
|
||||
{
|
||||
initSX = reader.readUint16Big();
|
||||
qSX = reader.readUByte();
|
||||
initSY = reader.readUint16Big();
|
||||
qSY = reader.readUByte();
|
||||
initSZ = reader.readUint16Big();
|
||||
qSZ = reader.readUByte();
|
||||
}
|
||||
}
|
||||
void write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(id);
|
||||
writer.writeUByte(id);
|
||||
writer.writeUint16Big(keyCount1);
|
||||
writer.writeUint16Big(initRX);
|
||||
writer.writeUByte(qRX);
|
||||
writer.writeUint16Big(initRY);
|
||||
writer.writeUByte(qRY);
|
||||
writer.writeUint16Big(initRZ);
|
||||
writer.writeUByte(qRZ);
|
||||
if (keyCount1)
|
||||
{
|
||||
writer.writeUint16Big(initRX);
|
||||
writer.writeUByte(qRX);
|
||||
writer.writeUint16Big(initRY);
|
||||
writer.writeUByte(qRY);
|
||||
writer.writeUint16Big(initRZ);
|
||||
writer.writeUByte(qRZ);
|
||||
}
|
||||
writer.writeUint16Big(keyCount2);
|
||||
if (keyCount2)
|
||||
{
|
||||
|
@ -131,6 +154,16 @@ struct ANIM : BigDNA
|
|||
writer.writeUint16Big(initTZ);
|
||||
writer.writeUByte(qTZ);
|
||||
}
|
||||
writer.writeUint16Big(keyCount3);
|
||||
if (keyCount3)
|
||||
{
|
||||
writer.writeUint16Big(initSX);
|
||||
writer.writeUByte(qSX);
|
||||
writer.writeUint16Big(initSY);
|
||||
writer.writeUByte(qSY);
|
||||
writer.writeUint16Big(initSZ);
|
||||
writer.writeUByte(qSZ);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -150,7 +183,7 @@ struct ANIM : BigDNA
|
|||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
Log.report(LogVisor::Error, "unrecognized ANIM version");
|
||||
Log.report(LogVisor::FatalError, "unrecognized ANIM version");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ struct CINF : BigDNA
|
|||
Value<atUint32> id;
|
||||
Value<atUint32> parentId;
|
||||
Value<atVec3f> origin;
|
||||
Value<float> skinMetrics[8];
|
||||
Value<atUint32> linkedCount;
|
||||
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
||||
};
|
||||
|
@ -90,7 +91,7 @@ struct CINF : BigDNA
|
|||
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
if (bone.parentId != 97)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
|
|
@ -9,5 +9,6 @@ add_library(DNAMP2
|
|||
DNAMP2.hpp DNAMP2.cpp
|
||||
${liblist}
|
||||
ANIM.cpp
|
||||
ANCS.cpp
|
||||
CMDL.hpp
|
||||
STRG.hpp STRG.cpp)
|
||||
|
|
|
@ -34,7 +34,7 @@ struct CSKR : BigDNA
|
|||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules)
|
||||
{
|
||||
if (idx < accum + rule.vertCount)
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n",
|
||||
cinf.getBoneIdxFromId(weight.boneId),
|
||||
|
|
|
@ -185,13 +185,13 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
|
|||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
return {STRG::Extract, nullptr, {".yaml"}};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
return {TXTR::Extract, nullptr, {".png"}};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 2};
|
||||
return {nullptr, CMDL::Extract, {".blend"}, 2};
|
||||
case SBIG('ANCS'):
|
||||
return {nullptr, ANCS::Extract, nullptr, 1};
|
||||
return {nullptr, ANCS::Extract, {".yaml", ".blend"}, 1};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -58,11 +58,11 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
|||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
return {STRG::Extract, nullptr, {".yaml"}};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
return {TXTR::Extract, nullptr, {".png"}};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 1};
|
||||
return {nullptr, CMDL::Extract, {".blend"}, 1};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue